#archived-dots
1 messages · Page 229 of 1
just doing a quick readup there i think with lambda expressions i've really got the impression that they are 'slow' from Linq stuff
so i don't think was a fair statement
Yea it's all contextual. Functional influences show up in rust and are nicely compiled into efficient code
Yeah, there's def different benefits to the different paradigms.. even oop hehe
for example the little framework someone posted here yesterday for getting 'events' from added and removed components
dod purists would probably have a fit.. but it's essentially taking some of the benefits of oop and overlaying it onto a dod framework, which i think is quite cool
Referring to this one, just noticed there's another post that may get confused
if i include a component in a ForEach, i can't then use GetComponent with that component type to grab from another entity
another annoying little anecdote
or pass in i think any array with that same component type
so if i do:
Entities.ForEach((in MyTag myTag, in LocalToWorld) =>
{
var otherLTW = GetComponent<LocalToWorld>(someOtherEntity);
}```
it doesn't like it
could also build a hashmap instead of using ComponentDataFromEntity<T>
technically you can take it a step further as long as you don't do structural changes to your entities, grab the pointer and set it directly
how do you get a pointer with this?
@gusty coyote you can consider Collections, Jobs, and Burst safely to enhance your gameobjects/OOP game as they're getting quite stable now. Forget everything else DOTS related for the time being
so what are the big benefits of source generators for dots? I keep hearing about this but am really out of the loop on what exactly it means vs what the current setup is
Source generators are pretty much code gen and you can feed it a template (or signal it via attributes). The benefit is really c# has a native way of generating source code without doing IL weaving.
They're inspectable and debuggable so you can just rely on native toolsets supported by the compiler versus hooking something in
Don't remember from the top of my head, you'd have to inspect the source and reverse engineer it (wouldn't really recommend it though)
What is the recommended way for to get prefab functionality? Are subscenes the way to go? For starters I load them from files, but eventually I will deliver the objects over internet.
I tried subscenes and it seems a little awkward, as I need to dynamically place the objects.
I also tried this approach but didn't quite get it to work https://forum.unity.com/threads/storing-converted-entity-prefabs-other-than-subscenes.941198/
my matrix/vector math is terrible anybody know how to convert a local matrix to world?
i think this will convert objectMatrix to relative/local matrix right:
math.mul(math.inverse(parentMatrix), objectMatrix);
wondering how to do the opposite, convert from a local/relative matrix to global
Hey, I'm using Jobs System, and my job uses container which I supposed to dispose after the job is done.
But in order to do that, I have to wait for it to complete in main thread, which is blocked, which is bad for UX.
So, is there a way to dispose a container after job, but don't block main thread?
Thanks in advance
I have written about this here: https://coffeebraingames.wordpress.com/2021/05/09/how-to-run-jobs-using-componentdatafromentity-in-parallel/
We did it this way: https://coffeebraingames.wordpress.com/2020/07/19/entity-prefab-management/. It's not necessarily the recommended way. Just one of the ways.
There's Dispose(JobHandle). You pass in the handle which you have scheduled.
Isn't that just math.mul(localMat, parentMat)?
Thanks, then we'll try to add those
Omg, totally! Thanks! Feel kinda dumb that didn't see it before.
And one more, if you don't mind. I have a quite complex task that I'd like to Jobify, but it uses array of colliders for calculations. I test them to contain a point, so I can't extract some data and pass container with it. And colliders are obviously managed.
How to handle this?..
One way is collect that data that you need for your calculations in a NativeArray or NativeList of structs then use that in a job for the calculation.
For example, NativeArray<ColliderData>
Yes, it doesn't work, because collider doesn't provide me with such data.
Like, array of points, for example.
You can copy those points into a native container.
I can't extract them 🙂
What you mean you can't extract them? You're using them for calculations.
Yes, collider is a class, it doesn't expose those points, for example.
Show the calculation code
private bool CheckIsOccupied(IEnumerable<Collider> colliders, OctreeNode node) {
return colliders.Any(c => IsPointWithinCollider(c, node));
}
private static bool IsPointWithinCollider(Collider collider, OctreeNode node) {
var closestPoint = collider.ClosestPoint(node.Position);
return node.Bounds.Contains(closestPoint);
}
That's how I use collider
Maybe I could somehow pass native array of ClosestPoint delegates?
Right. So first is why would you need DOTS here? Like are you expecting too many colliders? How many?
I expect a lot of nodes, it's octree, depending on it's size it may be 100000 iterations
Amount of colliders can vary too, scene dependent
It's the bottleneck of everything right now 🙂
And I don't want to do that in main thread.
Honestly, you wouldn't gain much here if you just translate CheckIsOccupied() into burstable code. The real gain then is the iteration of nodes.
Can you show code where CheckIsOccupied() is used.
private void Subdivide(OctreeNode node, int depth) {
float offset = node.Size * 0.25f;
for (int i = 0; i < 8; i++) {
var newPosition = node.Position;
// Adjust position
newPosition.y += (i & 4) == 4 ? offset : -offset;
newPosition.x += (i & 2) == 2 ? offset : -offset;
newPosition.z += (i & 1) == 1 ? offset : -offset;
var childNode = new OctreeNode {
Position = newPosition,
Size = offset * 2,
ParentIndex = node.Index,
Index = nodes.Length,
Bounds = new Bounds(newPosition, Vector3.one * (offset * 2)),
};
bool nodeIsOccupied = CheckIsOccupied(_colliders, childNode);
childNode.IsOccupied = nodeIsOccupied && depth <= 0;
childNode.IsLeaf = !nodeIsOccupied || depth <= 0 ;
if (childNode.IsOccupied) {
childNode.renderColor = new Color(1, 0, 0, 0.3f);
}
nodes.Add(childNode);
Children.Add(node.Index, childNode.Index);
if (depth > 0 && nodeIsOccupied) {
Subdivide(childNode, depth - 1);
}
}
}
Yep
_colliders is a list of Colliders I assume?
Yeah, OOP is generally hard to translate to pure value types.
Yes, kinda different paradigm, have to think it a different way.
I think the bottleneck is really in frequent calls to collider.ClosestPoint() and it's a black box.
Even if you cache that into structs and jobify the rest, the cost to executing that is already paid.
Well, yes, but I don’t want to block UI for a few seconds, if I can’t gain performance, at least fullfill that
By job i mean
I would suggest using .NET threads but I think Collider methods will only run in main thread.
I thought about it
See if you can execute ClosesPoint() in a different thread. If you can, then you can move that calculation in a separate thread.
But after that I have jobified tasks, they depend on this Subdivide. I can’t run jobs from different thread
You can wait for the thread to finish before scheduling those tasks.
If the problem is just responsive UI, you could also distribute the execution in multiple frames instead
One way is to use coroutine
float offset = node.Size * 0.25f;
for (int i = 0; i < 8; i++) {
var newPosition = node.Position;
// Adjust position
newPosition.y += (i & 4) == 4 ? offset : -offset;
newPosition.x += (i & 2) == 2 ? offset : -offset;
newPosition.z += (i & 1) == 1 ? offset : -offset;
var childNode = new OctreeNode {
Position = newPosition,
Size = offset * 2,
ParentIndex = node.Index,
Index = nodes.Length,
Bounds = new Bounds(newPosition, Vector3.one * (offset * 2)),
};
bool nodeIsOccupied = CheckIsOccupied(_colliders, childNode);
yield return null;
childNode.IsOccupied = nodeIsOccupied && depth <= 0;
childNode.IsLeaf = !nodeIsOccupied || depth <= 0 ;
if (childNode.IsOccupied) {
childNode.renderColor = new Color(1, 0, 0, 0.3f);
}
nodes.Add(childNode);
Children.Add(node.Index, childNode.Index);
if (depth > 0 && nodeIsOccupied) {
Subdivide(childNode, depth - 1);
yield return null;
}
}
}```
This way you only call CheckIsOccupied() and Subdivide() once per frame
I got the idea, thanks!
This is insanely useful, thanks marnel. There's a whole bunch of useful ideas and practical discussion of dots in there. I'll def be reading more of your articles.
should this be working for WASM builds ?
var JSON_interface = new TinyJsonInterface("[0,1]", Allocator.Temp);
[libil2cpp] A managed exception was thrown. The Tiny runtime does not support managed exceptions.
[libil2cpp] The exception message is: ToString is not implemented on System.Object for the Tiny profile. Please override ToString in the derived class if it is required.
Any ideas for how to go about debugging this kind of exception? Everything works fine for most of the levels I load up, but if it's a large level that takes a few seconds to load, there's a chance that at some point following that, everything falls over.
Thanks!
Quick question
Im using an IJobChunk
How the heck do i get the entity array instead of the component array ?
Ok i found a solution
Next question... how do i use an entity command buffer threadsafe ?
You use AsParallelWriter. There's an example in the manual https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/entity_command_buffer.html
THanks ! This changes some methods... AddComponent now requires a sort key... whats that ?
It explains it on that page
I dont really understand that :/ A sortKey wasnt mentioned at all
To ensure that the sequence of the commands in the ECB does not depend on how the work is distributed across jobs, you must also pass the index of the entity in the current query to each operation.
pass the entityInQueryIndex to the operation so the ECB can play back the commands in the right order
Alright, thanks ^^ I thought entityInQueryIndex != sortKey
Another little question... is there any way to acess an object in burst code ? I mean we can use ptrs in there... but what happens if the ptr points to an pinned object ? Can we acess that object or will it throw an error ?
any ideas to help me diagnose this? #archived-dots message
I'm thinking it's potentially a timing or a total memory usage issue but haven't been able to work out what's going on. If I load a smaller structure as the level, it works so I've resorted to that as a temporary workaround but this could potentially happen on a weaker system with the current data and that would be baaaad.
When i move some of my system into the init-system group they will stop being updated.
Any idea why this might happen ?
In the simulation group they always get updated
Alright updatealways solved that problem
When i create entities with the entity manager and add components to it, when does the entity appear ? At start of the initialize group ? At the next buffer system ?
The EntityManager tries to add it "now", but it waits for any running job to finish, prevents any new one to start, and blocks the main thread. That's what's referred to as a sync point.
At the next buffer system ?
You would use an ECB for that
Thanks ! Well this makes it a bit difficult. Lets say i want that all entities are running trough the whole systems-loop and do not enter it at any random point. How would i do that ?
There's nothing "random" about what they just described
"Waits for any running job to finish"... so i assume that the entities would appear somewhere in simulation for example. Which is kinda random for me.... or is there a way to determine when exactly they might appear in the loop ?
It forces all running jobs to finish, blocking the main thread until then as soon as you call the function causing the sync point. If you don't want that you use an ECB so you have a predictable spot in your game loop when this happens
Thanks, so the only predictable way are ecb's ^^
Is there a way to buffer a add/set/remove of an component object ?
For entityManager there is that "AddComponentObject" but its not available for the ecb
I don't think so, ecbs are meant to work inside jobs and that would require passing around managed references
You can create your own system that runs just before or after an existing entitycommandbuffersystem though
Looking for this ?
I never tried
but we talked about it with someone here some days ago ^^
don't expect multi-threading or burst there 😛
like Sark hinted
got to go eat, see ya
Alright thanks to both of you ! Im gonna look at that 😄 I actually think its not in my current version yet... so ill probably should update
I make one minor change to a system and suddenly the entire data cache (my own code) is invalidated and needs to be regenerated. Fuck me. Now im sitting here hitting a button over and over again with a single line change and wondering why my code isnt working after 10 minutes of file parsing. God Unity, I wish I had coroutines in DOTS systems...
I have a problem. At startup of my program (im not calling it a game any time soon), I need to load about 5,000 to 6,000 JSON files from the hard drive. They're split up to make it much easier to edit and view in case something messed up on the file parsing side or in case I need to custom edit something. This of course takes quite a while, especially on hard drives. Right now, I have all this loading process occur in one "OnStartRunning()" event all in one frame, so startup after the Unity Splash Screen is black for quite a while and may even stop responding.
So a loading screen is pretty much mandatory, to prevent the user from panicking and alt-f4 from my program and complaining in a Git Issue that their program crashed on startup.
But how can I do that? In Mono-Land, this would be trivial to solve. Use Coroutines to split up the files into 10 file size chunks to read, deserialize, and create the relevant number of GameObjects. Then wait for end of frame by a yield return null and let the loading screen animation progress by 1 frame or something.
DOTS however doesnt have Coroutines and I would like to avoid chaining a system to a monobehavior script just for access to Coroutines.
https://docs.unity3d.com/Packages/com.unity.netcode@0.6/manual/getting-started.html this page still seems to have instructions for deprecated classes. Is there a guide that has instructions that aren't deprecated?
Yea... netcode is not in a good place right now
@robust scaffold the tutorials or is it just kinda broken?
Use that tutorial, it's up to date with 0.6 (despite being a year old). Pretty much everything outside the main core Entities is either undocumented or broken. Usually both.
nice. thanks!
The next DOTS release (estimated around a year or two from now, if ever) will probably invalidate everything we know about DOTS so starting now is not a great idea.
Because either everything is going to change, or it's dead.
it is not dead and it will be less than a year until the 0.18 release
I'll see it to believe it. And it'll probably be 0.20, skipping 0.18 and 0.19, according to hints from various "minor" bugs with DOTS that were marked down as fixed
we'll see. be at the end of the year at the earliest though
End of year is really optimistic. Quarter 2 or 3 of 2022 probably.
nah. it was stated that end of the year was possible, or early 2022
When has the DOTS team ever stuck to a timeline before?
What was the old Roadmap, full DOTS by late 2020?
there was never a real release date, only estimates
They recently applied for patent for their implementation of ECS, so probably it's related.
they did? interesting. i'm all for it though
but i think it's more than that since it is not usable in 2021 unity
you will only get errors
It's broken? I use only job systems and burst, they work
no, job and burst is fine but the ecs component Entities 0.17 is broken. and there's a thread about it in the unity forum
Even with 2021.1? Which is released?
but they officially said that it will be broken while jobs and burst will continue to work
yes
but they stated that it's not dead and they are definitely working on it but it will be compatible again with 2021 at the end of the year at the earliest
Okay, got it... We'll see, the idea itself is quite promising.
my read into it is that going public has made unity more risk adverse in terms of committing to timelines and openly sharing “experimental” packages. I would be extremely surprised if entities doesn’t get another release though
The reason they haven’t been more transparent is because the point is that they believe they need to be less transparent
Or rather, that they’ve been too transparent
I have a IJobParallelFor running trying to run this code: ```public void Execute(int index) {
distance = Vector3.Distance(positionData[index], currentCamPos); // Compute distance to main cam
for (int i = 0; i < LODDistances.Length; i++) { // Iterate over LOD distances
if (distance < LODDistances[i]) { // Find applicable LOD Level
lodDataOutput[index] = i; // Set LOD Level
return;
}
}
lodDataOutput[index] = -1; // Out of range, set -1 to disable rendering
}and of course i'm getting this error:System.IndexOutOfRangeException: Index {0} is out of range of '{1}' Length.``` I need the LOD distances to be available to test against, but I'm not sure how to get around this index problem. Could use some pointers.
any idea what this might be caused by?
Exception: NullReferenceException: Object reference not set to an instance of an object
at Reese.Nav.NavSurfaceAuthoring.get_surfaceSystem () [0x00000] in C:\repos\fremwerk\Library\PackageCache\com.reese.nav@0.22.2\Surface\NavSurfaceAuthoring.cs:33
at Reese.Nav.NavSurfaceAuthoring.Convert (Unity.Entities.Entity entity, Unity.Entities.EntityManager dstManager, GameObjectConversionSystem conversionSystem) [0x0004e] in C:\repos\fremwerk\Library\PackageCache\com.reese.nav@0.22.2\Surface\NavSurfaceAuthoring.cs:43
at Unity.Entities.Conversion.ConvertGameObjectToEntitySystem.Convert (UnityEngine.Transform transform, System.Collections.Generic.List`1[T] convertibles) [0x0004b] in C:\repos\fremwerk\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities.Hybrid\GameObjectConversion\ConvertGameObjectToEntitySystem.cs:44 from Ground000
the referenced line is
NavSurfaceSystem surfaceSystem => World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<NavSurfaceSystem>();
@dense oriole What is Reese.Nav.NavSurfaceAuthoring? And it would help to see some code on how your using it
Oh, a DOTS nav package
Remove [BurstCompile] to allow errors to be properly interpolated.
working on it
Otherwise, it depends on the ParallelFor index assigment, my guess is that positionData and lodDataOutput lengths are not equal and near the end you're trying to [index] out of bounds of one of them.
Also dont use Vector3, use Unity.Mathematics and replace everything with that package's types. So Vector3 with float3 and so on. And for Vector3.Distance(), you would use math.length().
Oh thats very good to know!
Vector3 isnt supported by Burst. Float3 is and allows, if you're really coding hard for it, vectorization and extreme speed boosts. But conversion to Mathematics is a real pain in the ass when all the tutorials are using Vector3.
I originally thought the error was caused by me accessing the array containing the lod distances
that only the value of INDEX could be used to access any array in the job
What?
Yes well I was wrong haha
You can use the index in Execute(int index) for anything. It's just an int. Just make sure all the array lengths line up properly with the initial job scheduling length.
I mean, In the job I need to iterate over each value in LODDistances and test it agasint the distance of each entity. I thought it was complaining about me trying to access another index in LODDistances than the one specified by INDEX.
Gotta remember to remove the burst attribute...
BTW what do you mean by coding for it in "Float3 is and allows, if you're really coding hard for it" ?
I feel as there's a better way somewhere to determine LOD distances between entities that involve spacial partitioning and NativeMultiHashMap....
mmm
Loop Vectorization is the extreme deep end of Burst. Let me see if I can find the docs (which only barely scratches the surface of it). It speeds up calculation of math between variables by 10x on top of base Burst.
wow
It's fucking magic and you need to spend hours looking at compiled machine code to figure out if it's actually working.
It's like shader optimization except even less documented.
Would definitly like to have a link to that document if you find it
if you have something to read on " determine LOD distances between entities that involve spacial partitioning and NativeMultiHashMap" that would be nice to
I have been playing around with an octree but keeping 100k entity position updated in it is a challenge
That was years ago back when Unity bothered to talk to us. I cant remember where I saw it and I was still fairly new to DOTS so I couldnt understand it well either.
Bothered to talk to us... i know the feeling 🙂
So like in a UNITY/GDC conference about DOTS when it came out?
Yea. About the now long gone NativeMultiHashMap extension functions (IJobNativeMultiHashMapForEachIndex or something like that) that have been purged from the codebase about a year ago. The only use was speeding up distance between entity calculations.
Oh... sure what a good reason to get rid of it, anything replaces it?
They were using an example for Boids separation and attraction calculation. I think they're still in the old DOTS example github. I've actually implemented it once manually since Unity did expose the unsafe variables buried inside UnsafeHashMap required to make it work so it's possible if you copy paste the code and swap around some of the parameters to functions.
But nothing replaced it. You need to code it manually to use it.
look at that i was feeding the wrong length to my job 😆 at least thats fixed
Heh, yea.
OK im gonna save this whole conversation haha
Discord needs an Export to PDF feature
You can also just roll back the Entities package to before they removed it and then copy paste the Job code for NMHM extensions. You'll need to fix it up for the most recent version of Entities when you go back to 0.17.
Thats a good idea
BTW you mentioned the math library earlier, does it have a replacement for Matrix4x4.TRS() ?
Dont known what TRS is off the top of my head but 99% probably not. Unless there's an equivalent in HLSL since the Mathematics library intentionally mirrors HLSL and lacks a lot of the nice to have functions.
It creates a Translation Rotation and Scaling matrix4x4
So you'll need to find the Matrix4x4 function implementation and so the same manually with Mathematics Float4x4.
Definitely. Float4x4 is well supported with Burst Loop Vectorization.
float4x4.TRS already exists
Oh man you have given me a lot to work with, can't try to try all that
!
Amazing! thanks Sark!
And thank you VERY much KornFlaks for all that valuable info
NP, we're all that's left of this mess of DOTS so we've gotta prop each other up.
mmm yeah.... DOTS...
I'm just using the job system for now
Didnt feel like converting my whole project
That's good. You're smart.
Non Im lazy hahahahha
You can actually use functional unity version. We're stuck in the dark ages of LTS with Entities / Hybrid
Oh yeah I read about that. That sucks!
But "functional" is a big word for unity lol
I have stumbled into so may undocumented issues and new bugs in the past years it's unbelievable.
Parallel meta file creation (well more parallel than LTS right now) in 2021.1 (or was it .2) is so nice. I got over 5,000 json files that I occasionally need to reimport and sitting at my desk staring at the progress bar slowly grind through all the files are pain.
Stuff that should just work but doesn't...
Ohhhhh
What version are stuck at?
Im actually on 2019.4 cause... lazy haha
oh, ha. 2020.3
I usually upgrade only once a year if there are no issues... I guess im falling behind
Anything broken in 2020 from 2019?
Dot/Job wise?
No clue. Havent tried to make that large of a jump. Burst / Job are exactly the same (maybe minus some of the Apple chip intrinsics that IIRC only work with 2020+).
If you havent heard of Loop Vectorization, dont even think about chip specific intrinsics. It doesnt matter.
Yea its above my pay grade for now haha
same 2020.3.8f1 and it seems to all work pretty well so far seems to be a sweet spot.. i don't think using latest versions is ever a good idea in any software in any case
The bad: None of the fancy new features of HDRP (even if I turn 99% of them off anyways). The good: My project I'm working on that I just defrosted from a 5 month break works perfectly out of the microwave and compiles without error.
As an alpha build chaser, that is a brand new feeling for me.
Ah i haven't tried HDRP at all tbh.. As a long time 3d animation/rendering person i would normally want every bit of visual tech i can get but for game dev i'm happy enough to take the middle lane and go with URP basically just for accessibility..
I don't know the exact details as i haven't looked much into it but i think HDRP is pretty much high end only right.
Yea, kinda. I'm pretty much only using it for built in virtual texturing since I'm plastering about five 16k x 8k textures on a single sphere.
Everything else I've turned off. Reflections, refractions, raytracing, etc etc are all off.
environment mapping?
Yea, globe normals and texturing.
- normals. 2. terrain. 3. water. 4. city night lighting. 5. atmosphere
I've always kinda thought Unreal Engine was a no brainer for high end realtime stuff but i think Unity def has a lot of potential and is moving in that direction
Unreal had virtual texturing years before Unity but I'm in too deep with DOTS to make the switch over
Well i genuinely think that DOTS could really transform Unity in terms of performance and what it's capable of.. it's always been seen as the kinda indy platform whereas Unreal does all the high end triple-A stuff.. but the potential is there with Unity
I think with Unreal it just has all the tools in place and ready to go, you can essentially jump right in and create a triple-A looking mockup in a matter of hours/days
ArgumentException: A component with type:CellStatus has not been added to the entity. What? Just adding an IComponentData to a prototype entity in a bootstrap monobehaviour...
maybe your system code is running before your mono adds the component or something
What is the line of code that threw that error? If you're using SetComponentData(), the component must first exist. You can instead use AddComponentData() if it doesnt already but will throw an error if it does exist.
I've made an extension method off EntityManager called AddOrSetComponentData() for both cases but only used in creation as SetComponent will pretty much be the only thing you need in runtime.
@robust scaffold Ah the component is new. I didn't even see addcomponentdata in intellisense. Oops.
Nice, that's pretty cool
Some youtuber did a really cool environment haze shader thing tutorial recently, can't remember which one
i think it did all the diffraction stuff to simulate the colors in the atmosphere around a planet etc
this one, quite cool:
https://www.youtube.com/watch?v=DxfEbulyFcY
The planets in my solar system project are looking a bit hostile and uninviting, so in this video I'll be attempting to add some cozy atmospheres around them.
Watch the previous solar system video: here: https://youtu.be/lctXaT9pxA0
Some notes:
• I made a little build where you can play with the atmosphere settings yourself, which you can find...
Oh Seb has amazing tutorials
Oh I saw that. Might be a bit much since the camera doesnt actually enter the atmosphere
indeed, there are a bunch of ways i think the glow around the planet could be simulated or cheated
looks like in your gif you've applied some kind of fresnel effect to achieve something similar right
Yea, it's a shortcut way based off directional light direction
i think your normals are a touch too strong but i'd guess you've exaggerated the strength to actually see the effect of it
On the planet? Yea. It's maxed out from the BW -> Normal map conversion or else why waste memory on a 16k texture if you're barely gonna see it.
It was an idea... give me a sec to dig it back up
It was going to be two cloud textures with UV moving at different speeds (that gif had 1, easy enough to implement 2) but I couldnt find a second cloud texture
now the mobile compressed / embedded version looks really sparkly though
that's pretty nice, looks good with the cloud layer
i don't think they need to move at all tbh
I sacrificed the night map due to some issues with compression I think...
Thats some very nice work Korn!
is there normals on the cloud layer?
Nope, not on the clouds
It's a blend between the terrain texture and cloud texture by lerp of the BW color value of the cloud texture
nice, looks great
I didnt exactly want to make a nice looking globe so I scrapped the clouds and went instead to coding a "game"
that looks very interesting 🙂
the normals looks good in the context of the map view ( in the removed image )
And here's roughly where Im at. The borders remain pixelated and I still need to figure out a way to antialias it with decent performance.
are you using any kind of lod on the textures
LOD is handled by Unity virtual texturing. I sure as hell cant code it
yeah it's not something i've looked at in unity, lod textures
would make sense for a globe sized map though if there's any kind of zooming involved
Yep, unity and their magic box does all that for me. I cant quite find the screenshot of when I plastered eight 16k textures onto a single globe (maximum resolution available from NASA where I'm getting these textures from). There were seam issues due to how badly I did the UV mapping in blender but Unity's virtual texturing took it like a champ
8 16k textures would consume a bit of vram i'd guess hehe
i guess unity resamples them down when they're imported?
In the settings, you can set the maximum vram used by all virtual textures (256 MB is default and they dont recommend increasing it regardless). Zooming far in, it was clearly one of the 16k textures (I had a comparison somewhere... dont know where I posted it).
eight 16k definitely maxed out the allocated virtual texture count but from a zoomed out view, it was largely indistinguishable from the gif above, just with 8x the file size for terrain coloring.
Not sure how with my terrible matrix maths but i've managed to get my dots ragdoll to follow my dots skinned/animated mesh
what?? how the performance gains are crazy high
The performance gains are due to Burst and Jobs, which are chugging along in Alpha build right now perfectly fine. Entities is.... ehhhhhh. Hybrid renderer definitely not.
I can see Unity working right now to convert the underlying base engine code to job-ified Bursted systems but the GO exterior into DOTS? Probably not.
but isn't jobs built on top of entity components aka dots?
Nope. Other way around
Burst and Jobs existed long before DOTS, despite the lack of documentation on the latter.
i mean the gains
aren't jobs getting massive perf boosts from the data being arranged in entity chunks?
Job performance gain is based off linear array mathematics. You can achieve the same gains if you format everything into a NativeArray before passing it into a Job then parsing it out into GOs. Hence why IJobTransform exists.
In fact, doing so gives better performance (right now) than going Hybrid Renderer.
I mean I get that but the OOP architecture with game objects doesn't exactly make that the default approach
Yeaaaa, but thats why you implement Data Oriented Design yourself rather than use Unity DOTS.
sounds like reinventing the wheel =[
Thing is, Unity is reinventing the wheel with Hybrid Renderer, and failing badly at it. HDRP was built with GOs in mind and work with GOs. So use GOs instead.
Sorry, GOs?
Game objects
oh
surely not?
DOD is as simple as maintaining a static class with static arrays containing NativeArrays of game object data. Then GOs can pull from if requesting data.
Then you can code out bursted Job structs that operate on those NAs in Monobehavior.
Test it yourself. Anything less than about 1,000 cloned (same texture, same mesh) entities actually render faster using the equivalent number of GOs because HR has such high overhead.
If you start breaking up those entities into different meshes and textures, it gets even worse from there
Ah really.. i hadn't tested anything like that, have only really been using it so far as a replacement for skinned mesh AI and projectiles
HR relies on having the full 16KB entity chunk fully filled with the same identical entity. Anything less is a waste of memory space. And how often are you filling a full 16KB chunk?
Maybe in a video game where every single bullet has a physics mesh and everyone is equipped with machine guns it might make sense. But right now without dynamic chunk sizes, it falls short
something i've not looked at yet is chunk utilization is that something that can be inspected in the Profiler?
Entity Debugger, a separate tool window. And quite esoteric to understand in the first place
Thanks for the info i'll look into that
So If I understand what you're saying. You're asserting that where Hybrid Renderer misses its opportunity to beat custom data oriented design + game objects is the design implementation of the standard sized entity component chunks of 16KB?
So it quite probably makes sense if you have a scenario where it needs to be scalable from few to very many objects to consider implementing a two-tier approach ie using IJobTransform for few and Hybrid for many
Yes, combined with it being additional overhead on top of the already massive render pipelines
Yep. That's the way forward right now. And the definition of "many" is so high, it's quite unrealistic to reach unless you're specifically making a game for that
Why would writing a custom DOD + component and job system be cheaper / faster?
A custom DOD, as mentioned earlier, is as simple as a static class filled with static native arrays, each with a index for each GO. A component type is a new array. That is basically what DOTS is, except fancier arrays.
Interesting.. i mean for what i have at the moment which as i said is mostly skinned mesh AI characters it's completely outstripped anything i could do previously with SkinnedMeshRenderer and Animator, but i think that's much more to do with jobified animation pipeline and physics etc
The improvement with performance is from the lack of overhead. Using Entities and not Hybrid Renderer is fine. I'm doing so myself. Base Entities is quite performant and optimized but the rendering is garbage.
I dont believe DOTS animation or physics is in a usable state right now, especially the former. So stick with the well developed GO versions and communicate Job processed data manually
However, there is a madman who's taking it upon himself to code DOTS animation manually. Crazy guy: https://github.com/Dreaming381/Latios-Framework/tree/v0.4.1
And yea, even published an arguably better basic physics implementation then Microsoft (aka Havoc) themselves. He's going places even if DOTS itself is six feet under.
yeah i had a quick look at that not in detail though
The features he made are clearly from experience. Blackboard singleton entities is just revolutionary when I first read it. Makes me wonder if Unity even uses DOTS themselves.
As it stands at the moment, it works for the basic stuff i need.. famous last words though, i may yet hit some serious issues
Go as far as you can, it's a learning experience about DOD if nothing else.
Yeah it's impressive when you see someone just go full tilt on something like that
I'm optimistic for dots animation though, i've dug into the source quite a bit and i think it has a ton of potential to just transform the animation pipeline in unity to something insanely performant
i do wonder when/if they'll start offloading stuff to the gpu though, that seems a bit of a no brainer
i guess the cost of streaming data to the gpu is high, but i'm sure there's scope to do stuff there
DOTS was definitely created with the intent for easy integration with compute shaders. The mirroring of vector types in Mathematics makes that clear enough. But yea, that's also a major bottleneck with Hybrid Renderer as well as, IIRC, sends the mesh to the GPU at any positional change for some reason. The devs made it clear there was some serious improvements coming down the pipeline until... it didnt.
Hybrid Render prebaked the texture on the mesh or something insane that required high informational transfer between memory and GPU that was a source of a lot of headaches
hmm
There was a lot of discussion on the topic before Unity practically decapitated any conversations by shifting it into a separate sub-forum
Hehe damn.. yeah i can understand the frustration as it's been on-off i think for so long
They're still hinting at improvements. All these months and years (practically) later
i can only guess they're constrained by the fact that the structural changes are enormous in terms of the overall life-cycle of the entire game engine and the implications of how dots impacts and changes that
all i can say is.. at least it's not f***** adobe that's running things
Who knows, maybe. Unity has a simply fantastic magical box known as Burst. Now they're trying to build a game engine around it.
Or oracle.
hehe or autodesk
Although patenting DOTS in its current state does give me pause on that Oracle comparison
hehe ouch
Anyways, I've gotta go. Hungry as fuck and my usual haunt closes at 8 on the weekends. Nice chatting with ya
You too laters 🙂
Is there a way to endlessly index a NativeArray<> such that an index call into it that's higher than the length "loops" back around into the array?
eg: NativeArray length = 100, an indexed call into it of [120] returns the 20th index, [130] returns the 30th index etc.
(index + n) % NativeArray<T>.Length
@coarse turtle without doing anything like that
no maths, just having a looping index. No conditionals.
okay, that's an odd requirement
not sure how'd you do that without using some math or conditions 🤔
I know, but I saw it somewhere, and I can't remember where I saw it, and how it's named or done.
maybe a custom iterator or some thing
It was yesterday, and I thought "oh, that's interesting... I'll never need that..." and today, I need it.
It was something about the way the array was defined, such that it was told to be a looping index array. But I can't remember what I was reading, or where, or even which language it was in.
maybe a custom wrapper for an array
well that's just a ring buffer ¯_(ツ)_/¯
How is a ring buffer done on an array's indexing without any maths/conditionals?
don't know, usually increment and decrement in a ring buffer uses the modulo operator
I'm still not sure why you wouldn't want to use a conditional or math. Having a hard time on figuring out the use case and why it could possibly be a bottleneck 🤔
It requires math, just Unity is doing it for you
@robust scaffold can I be reasonably sure that since Unity is doing it for me, their Burst/Jobs will love it , and be optimally quick through indexing this array?
I'm doing DSP, making waves, and want to loop over them, within loops that are far longer, in the most optimal way. More faster = more sounds with more effects and less glitches and audio spikes.
Waves? Have you tried trigonometry and sine-cosine stacking? The most optimal is just pure mathematics, no buffers.
Has anyone had an issue where a system seems to be updating in the wrong order despite showing in the correct order in the editor?
The system update list is not guarenteed unless you use [UpdateBefore / UpdateAfter] tags
I do have them, and the systems are in the same group.
That's impossible then. Are you sure they're not being updated in the right order then?
@robust scaffold Audio requires the creation of at least 512 samples in an array, to be pushed/given to the audiosystem, each "tick" of the audio system. So if you want to blend 4 waves, 4 noises and mod each with volumes/gain/distortion and add ADSR control over them over time, buffers are the only way to realistically achieve this in the small bits of time available. Waves need to be pre-baked into buffers, so the final signal is just a matter of summing and multiplying them by their gains and ADSR envelopers
This is how my systems are configured
Good noise, for example, can't possibly be calculated in realtime. It's quite heavy random functions with filtering to make a well "pitched" spectrum of noise.
Oh audio, no clue then. Uh, I've done some noise stacking (noise on noise in a for loop to get interesting patterns) and just iterating through a for loop multiple times using itsjustblank's (index + n) % NativeArray<T>.Length is good. You wont find much more optimization than this. The greatest performance hog will be the actual addition and setting of the index value in the native array. That's where you look towards loop vectorization methods.
You just need one [UpdateBefore / UpdateAfter]. Two related to each other may result in some conflicting errors in the system update order method. Try removing one.
That's what I'm doiing... heavy use of float4 to fill the registers and do the most possible with each clock. But there's an issue with feeding the contents in, which requires me do lots of conditionals, or rely on infinitely looping indexing (ideally) that's fast.
Yea, just set the for loop to be X * Length of the array where X is the number of loops.
And then use remainder (%) to determine which index you're at from the current for loop index.
I have tried every variation sadly 😦
Everything is using .Run(), it should all be on the main thread.
I really don't understand at all why this is happening
will have to think about this, never done it before. And will require reconsidering how I feed in data and assess what needs to be sent where. Cheers!
since you're dealing with curves - it reminded me of this talk where they spent time optimizing trig functions with a margin of error: https://youtu.be/uK87jZmeT7Y?list=PLX2vGYjWbI0RtjGyAFd6MdhG5kRokv4uI&t=1690
This session looks at the traffic simulation in the demo examining the compute kernels and the code that Burst produces for them. We will also cover the spline-based AI agents and how they were developed with the ECS.
Speakers: Andreas Fredriksson (Unity Technologies), Lee Hammerton (Unity Technologies)
Here's a method to enforce system update order but may result in a system being run in the next frame over. Use RequireSingletonForUpdate<>() with the second system and CreateEntity(typeof(singletonComponent)) at the end of the first system.
The second system wont run until the first system reaches the end of its logic and creates the singleton entity. If it's ordered in front of the first system, then it'll run in the next frame. Still after the first system though.
@robust scaffold here's an attempt to partially visually describe the problem, at two different audio buffer sizes.
I personally use RequireSingletonForUpdate<>() a lot for multi-frame systems like my initial loading / authoring systems. I cant use [UpdateAfter()] since these systems run for multiple frames before finishing so I instead chain singleton enablers together.
And you want to add these two buffers together?
Thanks @coarse turtle , will watch. Above a partial diagram of the problem of the audio buffer's needs at two different sizes of buffer. Because players have different screen refresh rates, I set the buffer size to the best matching latency (lowest) for them, so their audio experience closely matches their visual experience.
The downside of audio done procedurally is that the slower the target device, the more audio data needs to be generated per frame. So the problem of generating audio is... a problem. The audio buffer wants what the audio buffer wants.
No, these two buffers represent two different devices, and how they have slightly different problems. The top one is a device running at 240fps with a 256 samples buffer, the bottom one is a more normal device, at 60fps with a 1024 samples buffer. In between you can imagine a 120fps device with a 512 samples bufffer.
at 44100 samples per second (pretty much the standard), the smallest audio tick on a 240fps game machine is 256/44100 - about 1/172nd of a second.
@robust scaffold Can I just index into an UnsafeRingQueue in the same way I might into a NativeSlice, but also with the ability to call higher values than the index range, and rely on it to loop through, like a ring buffer?
I'm le dumb, the system that was triggering the other 2 was out of order.
Thanks for bouncing ideas back mate!
A RingQueue is like a Queue, you need to iterate it through multiple times and you cant just [Index] it like an array.
Sorry, @robust scaffold I have no idea what you mean by Queue and iterating though, nor why it's not possible to index into it.
A queue is not an array. You can not index to a specific value by position from the "beginning" like an array because the "beginning" is always changing. Like one of those bicycle locks with cylindrical number passwords. You cant skip to 9 from 4, you need to rotate the cylinder through 5, 6, 7, and 8 before getting to 9.
@robust scaffold this seems somewhat different to anything I know. What are these used for, and how would they be applicable to the issue of regurgitating looped waves without worrying about "out of bounds" of an array's length?
Oh, and unity's ring queue has no way to "peek" or readonly access to the buffer. You apparently must dequeue and requeue to make an infinite buffer... what the fuck is this thing even used for? This isnt a ring queue.
Yea, you'll need to use a NativeArray, or UnsafeArray if you need multiple dimensions, and indexing using remainders for "infinite" access.
@robust scaffold THANK YOU!!! These are the rules I need, so that i don't go on wild goose chases seeking ways and means that are only in my imagination. THANK YOU!!!
@robust scaffold About replacing my Vector3 by Float3, I was reading the link you sent me on vectorization and found this mentioned about Unity.Mathematics: Note that currently, for an optimal usage of this library, it is recommended to use SIMD 4 wide types (float4, int4, bool4...)
does this mean I should use an array of int4 instead of int? Leaving the other 3 internal int go to waste?
I have a very strange issue...
Yesterday my system worked fine... today it does not.
I have a system which runs a IJobChunk and this seems to create an infinite loop. Im stuck in the Application.EnterPlayMode
Any idea what might cause the infinite loop ? I dont get it...
This is actually the piece of code which creates the loop somehow
Ignore the first message.txt... the second one is somehow making my editor being stuck in the "EnterPlayMode" process
The 4 sized variables are most supported by loop vectorization but smaller ones work as well.
Anyone having an idea regarding my code
So i do this in one job...
/// <summary>
/// A job which runs asynchron and copies the <see cref="TComponent"/> into the <see cref="State"/> in an fast and efficient, generic way.
/// </summary>
[BurstCompile]
private struct AddedJob : IJobChunk {
public EntityCommandBuffer.ParallelWriter ecb;
[ReadOnly] public EntityTypeHandle entityHandle;
[ReadOnly] public ComponentTypeHandle<TComponent> componentHandle;
[NativeDisableUnsafePtrRestriction] public IntPtr reactorsPtr;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
// Get original component and the state array
var entityArray = chunk.GetNativeArray(entityHandle);
var componentArray = chunk.GetNativeArray(componentHandle);
var reactors = (ConcurrentQueue<IComponentReactor<TComponent>>)((GCHandle) reactorsPtr).Target;
// Copy the component into the state
for (var i = 0; i < chunk.Count; i++) {
var entity = entityArray[i];
var component = componentArray[i];
// Call the reactor and add the components
foreach(var reactor in reactors)
Debug.Log("TEST");
ecb.AddComponent(chunkIndex, entity, new TAdded());
ecb.AddComponent(chunkIndex, entity, new State{component = component});
}
}
}
I basically iterate over a managed concurrent queue... and once i do this, my job creates an endless loop ( The foreach )
Why does this happen ? Without that line it works fine... I need to iterate a list with interfaces in that damn job :/ Any ideas ?
Oh and is there a way to store a Action<..> in a burstable struct ? There was an alternative to "action" which could be stored in in components easily... how was it called again ?
I think you can use a GCHandle to get an IntPtr to pass along instead, and use that to get the Action back in the job
wont work in a burst job tho
I'm getting 'HashMap is Full` errors trying to run a NativeMultiHashMap.AsParallelWriter through a parallel ForEach.. any ideas what might cause this?
one would presume you're over the capacity
can't call Add if you've used all the capacity you allocated
yeah i've tried increasing it by a multiple and still the same
That could work, but there was a native way which was burst compatible. Just cant remember the name anymore :/ it was kinda like a precompiled action
hmm i just multiplied the capacity by 100 and it worked
odd
problem must be at my end, i'd read a thread on the forum about parallel multihashmaps being buggy
yep, problem was mine, doh!
You can probably take the pointer to a burst compiled method and pass that along somehow, but not an "Action"
Okay another question. I'm creating a NativeHashMap, then wrapping it as .AsParallelWriter() so that i can push it through a parallel job and fill it with values.. I then push the underlying hashmap through a parallel job with AsReadOnly - however this underlying hashmap is showing as empty.. Is wrapping the hashmap in this way not possible?
var matrixMap = new NativeHashMap<Entity, float4x4>(count, Allocator.TempJob);
var matrixMap_WRITER = matrixMap.AsParallelWriter();
var Handle_GatherMatrices = Entities.ForEach((Entity e, ref LocalToWorld ltw) =>
{
// add to the matrixMap_WRITER
}).ScheduleParallel(Dependency);
var Handle_UseMatrices = Entities.WithReadOnly(matrixMap).ForEach((Entity e, ref Translation t) =>
{
// read from the underlying matrixMap
}).ScheduleParallel(Handle_GatherMatrices);
Ah wait, yet again, the problem is mine. Method above is fine. Don't code on a Sunday with a fuzzy head folks.
Did you not actually write to the map 😉 ?
cough
uhmm
i basically had this..
if (nativeThreadIndex == 0) matrixMap_WRITER.TryAdd(entity, ltw);
apparently nativeThreadIndex was never 0
i'm basically iterating a bunch of children of multiple parents and only wanted to fill this matrixMap for each parent once
and this silly bit of code did not help with that
FunctionPointers
Hey guys. Just released a new DOTS related article. We're using a pattern that we frequently used for our AI frameworks. https://coffeebraingames.wordpress.com/2021/09/26/agent-actions-as-entities/
Thanks ! 🙂
Is there any way to use managed objects in burst code ? What happens when i mark an method inside the job as BurstDiscard ? It says its used to operate on objects, but what happens in detail ?
I have a very weird issue... when click on the play button in the editor... one system causes an infinite loop.
When i attach a debugger first and then run it the same way... it suddenly works.
Anyone ever experienced similar issues ?
What the fuck... sometimes it does work... sometimes it does not. What am im doing wrong ?
/// <summary>
/// A job which runs asynchron and copies the <see cref="TComponent"/> into the <see cref="State"/> in an fast and efficient, generic way.
/// </summary>
[BurstCompile]
private struct AddedJob : IJobChunk {
public EntityCommandBuffer.ParallelWriter ecb;
[ReadOnly] public EntityTypeHandle entityHandle;
[ReadOnly] public ComponentTypeHandle<TComponent> componentHandle;
[NativeDisableUnsafePtrRestriction] public IntPtr reactorsPtr;
public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex) {
// Get original component and the state array
var entityArray = chunk.GetNativeArray(entityHandle);
var componentArray = chunk.GetNativeArray(componentHandle);
// Copy the component into the state
for (var i = 0; i < chunk.Count; i++) {
var entity = entityArray[i];
var component = componentArray[i];
React(ref component);
ecb.AddComponent(chunkIndex, entity, new TAdded());
ecb.AddComponent(chunkIndex, entity, new State {component = component});
}
}
[BurstDiscard]
private void React(ref TComponent component) {
// Call the reactor and add the components
var reactors = (List<IComponentReactor<TComponent>>) ((GCHandle) reactorsPtr).Target;
for (var index = 0; index < reactors.Count; index++) {
var reactor = reactors[index];
reactor.Added(ref component);
}
}
}
This is my job im running... when i loop over the list ( The managed one ), it leads to an unity endless loop.
Any ideas what i might be doing wrong ?
Could really need some help... im stuck with this since hours... no errors just that endless player enter mode loop thing
I don't think so and I wouldn't try since it will lead to undefined behaviour.
The best thing you can do is make value type copies and work on that instead.
Well that would explain why my code sometimes works and sometimes it causes and infinite loop xD
But are you sure ? I lately found "BurstDiscard" which is listed on the docs for a solution to work with managed objects
Well, I'm not sure but I've used BurstDiscard and it's not what I expected. A good guiding principle is do not used managed objects inside a job at all.
I do know that you can run unmanaged code in a job. I have an article about that.
Hmmm... ok. My problem is basically the following. I want my jobs to fire callbacks so i can hook up code from the outside to execute or log stuff there. My current solution is to have a List<IComponentReactor> which contains those methods which should be executed. This is only possible with managed code... have no clue how i should ever realize this in unmanaged code however
You can't use BurstCompile on it, though
And it doesn't have safety checks. You're on your own.
Well this a bit different from the ecs jobs im using ^^ But i mean... actually its the same im doing right ? Pinning the object that will be used, passing it to the job and using it there.
Where are you running this? In a system or MonoBehaviour?
Well, what you can do is schedule the value type parts then call Complete(), then you can call the callbacks.
Based on the code that you shown, you only need a NativeArray of the components.
I dont understand this could you explain your idea further ? ... i mean the part where i iterate over the managed list causes the "infinite" loop ( Application.EnterPlayMode for ever ).
But why ? It doesnt even make sense... theres no reason for it to do this. I just dont get it
Not really, because i wanna invoke those damn interface method ^^
Alright thanks ^^
Another interesting thing i just saw... when i enable burst enable compilation... the BurstDiscard method is not being invoked ( or atleast i cant debug in there and no debug logs are called )... and when compilation is off, it does
I'd do it this way:
It's not a compiling code but I hope you get the gist
If the reactors need to write to the component, then that code won't work. You'll need the entity so you can update the component via ComponentDataFromEntity.
Ahhhh i seee 😄 So you mean i should just add the components to an list and invoke the callbacks in the update method instead... damn thats much easier ^^ thanks !
What about the performance ? I mean .Complete should block, right ?
Yeah but that job is still Burst compiled and runs in parallel. Still faster than non job version.
Thanks a lot ! Im gonna try this 😄
If you want to work with managed types, you have to make a few sacrifices.
Consider this because it's not what you might expect.
Yeah i see :/ but thats a sacrifice im willing to make... because it eases listening for added components and i could add listeners from the ui which is great for updating entity informations ^^
And thanks for your time !
👍
Not everyone would post such an detailed example ^^
So it looks like it works 😄 Thanks a lot !
Oh, about the performance, that will depend on your reactors. If they're many and slow, well, it will be slow.
Looks more like the code is completely stripped out of the build. And not "it's the way to go to make it work with managed objects".
Thanks ! That would explain the behaviour... I thought its a silver bullet for that managed object problem ^^
I can easily see how the name is confusing yeah
So i updated my reactive system : https://forum.unity.com/threads/reactive-system-for-everyone.1173812/#post-7518350
In case someone is interessted. It combines two ways... either iterate via markers over added or remove components... or register callbacks ( perfect for ui )
congrats and neat - GOAP 🙂
What UPDATEINGROUP(typeof( ??? Simulation ???))) & EntityCommandBufferSystem do I use when I want to destroy entities. Seems like my [UpdateInGroup(typeof(FixedStepSimulationSystem)] is complaining entities are deleted when looking through queries n stuff. Destroy file: https://pastebin.com/wNSKKHs8 Drone enemyAI file: https://pastebin.com/4cGejQ0a
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
if I just pick at random as I am doing now, it is 5* 5* 5* 5 or 625 permutations of system guesses, and there are probably many solutions, but if that isn't the problem... I will waste a day.
ALSO A GENERAL Q: How do I go over the limit of .foreach arguments? queries and native arrays?
You use chunk iteration.
cool site thx
Marshal.GetFunctionPointerForDelegate(OnAddedConcurrent) makes unity crash... without an error message.
Anyone having an idea why that might happen ?
OnAddedConcurrent is initialized and basically looks like this public delegate void OnAdded<T>(ref Entity en, ref T cmp);
Anyone having an idea why this might happen ? I basically just wanna pass a delegate to an job for executing callbacks async but its crashing when i run that marshal 🙂
If crashing, disable Burst from the dropdown and you should see an error.
Thanks ! Burst Compilation is already disabled but it still crashes once i call that Marshal operation... I even surrounded it with try and catch, but once it runs that Marshal operation it just crashes...
Is that marshal operation not implemented ? Or why this might happen ? Do i need to pin the object first ? I bet its an stupid mistake :/
// in System
public delegate void OnAdded<T>(ref Entity en, ref T cmp);
public OnAdded<T> OnAdded = (...);
// In Update
var test = Marshal.GetFunctionPointerForDelegate(OnAdded); // Editor crashes, no logs, no exception
Ok i solved this one
Well ComponentTypeHandle<T> is for structs... is there a ComponentTypeHandle for component objects ? Managed ones ?
Is there any way to acess managed component objects in an job ?
So i found this var managedComponentArray = chunk.GetManagedComponentAccessor(componentHandle, ref e); but how do i get the componenthandle of a managed class type ? GetComponentHandle<MyClass> does not work
You mean GameObject components?
No, managed components for entities... class : IComponent for example ^^
Is it possible to use them in jobs ?
@stone osprey Seems like it has to be a struct:
An IComponentData implementation must be a struct and can only contain unmanaged, blittable types, including:
https://docs.unity3d.com/Packages/com.unity.entities@0.1/api/Unity.Entities.IComponentData.html
No... its possible... look up EntityManager.AddComponentObject();
Furthermore theres a method called "GetManagedComponentAccessor" in archetypechunk for working with them
There's no way to use class Icomponentdata in jobs and a lot of the EntityManager macros dont apply to class based components (like Get / Set singleton).
Apparently it syncs with the main thread.
Important: This function creates a sync point, which means that the EntityManager waits for all currently running Jobs to complete before adding the object and no additional Jobs can start before the function is finished. A sync point can cause a drop in performance because the ECS framework may not be able to make use of the processing power of all available cores.
Alright thanks to both of you :/
Looks like it works for Unity
with a managed ICD
public class EcsTestManagedComponent : IComponentData {}
But yeah you're not supposed to work with managed data in jobs
Thanks a lot ! 🙂 Well thats kinda pitty... because i need to iterate over a bunch of managed components in an efficient way... is there one ? The only way that comes in my mind is to use a query and get all the entities from it... but thats very, very slow
Grab everytihing you need in Native containers, do your bulk work, then get the results and update your mono objects
Or is it possible to run a job without burst ?
Hmmm... alright, thanks ^^ Is there a way to get a chunk/native array of components which is NOT a copy on the main ? Till now i only saw this happening in jobs
you'll need the ArchetypeChunkIterator
The apis to construct it are internal, so you'll need to do some looking up in the source
Isn't that for iterating the entities on the main thread?
Ah i see 😄 Theres a RunWithoutJobs... that should be more efficient than my query to component array stuff, thanks !
the iterator would point to an ArchetypeChunk, so yea you can iterate on entities & their components
I have a stupid basic question, do you have to use SetComponent all the time just to set variables even captured by the Entities.Foreach
not for a component on an entity that is captured by that query
as long as the component is passed in as ref
doh! 
Entities.WithReadOnly(FoodItemsbarcodes).ForEach((RobotCompState currRobstate, RobotsPhysicalmoney currphysmoney, CurrentRobotIntVal Timetowait, DynamicBuffer <ItemstoBuy> curritemms) =>
{```
I was passing them in like that
Entities
.ForEach((Entity entity, ref LastFrameTranslationComponent lastFrameTranslationComponent, in Translation translation) => {
})
here the lastFrameTranslationComponent can be accessed as read/write, translation is readonly
yeah I don't know how I forgot to use the ref, I'm surprised it even worked without the ref to be honest 
and use in also so the order can be optimized when things are readonly
I have a tricky problem that I suspect is something to do with timings/order of execution but I'm struggling to diagnose what I've done wrong.
I now have a fairly complex set of systems as this project has been going for a long time now. It's seen Entities from I think 0.5 or so, which probably doesn't help!
If I stress the systems with more entities, suddenly it'll enter a state where I get NREs spamming the console like the attached:
there are a variety of different errors, covering lots of different systems, and which I get seems to be random
at lower loads, it's completely stable, runs great, but obviously I have done something wrong and don't want people on lower end hardware to have crashes because I've done boo boos
I had a couple of fairly slow processes which I optimised today by switching from brute-force calculating some distance-related thing for all elements of an 2000-or so long array to using a spatial partitioning system I'd written to help with rendering. That improved frame-times significantly when more entities were present, and also raised the threshold where I get errors - but it didn't remove it , so that's why I suspect it's a timing issue (rather than eg memory)
I'm after some tips/ideas on how to go about diagnosing the problem, really! Once I understand what it is I have done wrong I'll be able to fix it, but the error messages haven't so far led me to anywhere useful 😦
FWIW it seems to be connected to events - eg linking between monobehaviour land UI/audio and a SystemBase GameStateSystem which curates ECS empty-component entity events that gate a whole bunch of systems via RequireForUpdate(entityQuery);
I don't know it looks like its an issue with something not existing that should exist, an issue with an EntityQuery or GetSingleton, it should tell you in which system that is
I tried putting a breakpoint in the ChunkDataUtility to see if I could work out what is returning null when this error state happens (which only happens under artificially long frame-times), but I didn't find anything different between a working state and the error state and nothing appeared to be null.
trying to catch the first frame when an issue is caught but it's tricky. Here's why it's not simply "something is null" - yes, there is a null ref but the cause of that is the issue, it's not traceable to a specific system trying to access something that's always null, because the game works fine under normal load. Here, for example, the first exception arises quoting the line in the TimeSystem shown on the right, it doesn't make sense to me how that could return a null reference, and I'm sure it's not a problem in the GetSingletonEntity code because as I said it works most of the time, I only see this when an event is fired under conditions of high load.
Might be that under high loads, there may be a structural change of sorts, causing the current pointer to be invalidated?
Yes that sounds like it's the issue, there are a few systems that make structural changes. I'm not sure if it's possible to refactor all of these out to use ECBs, but if it's going to eliminate the potential for this kind of failure I could have a crack at it
any ideas for how I might go about confirming the hypothesis before attempting such a big refactor?
lot's of laborious line by line analysis and patience?
not sure how that would help diagnose it tbh
You have your jobs debugger enabled right? I don't see how such a big concurrency issue would not get caught by it..
yeah I mean if you can't find exactly where it is then you could first eliminate all the places it isn't
Yup
can Unity Dots be used for VR?
I can't believe it's been about a week more or less, and I still can't delete entities after a time.
@ashen parcel I dont think its recommended for now
is Dots like Nanite but for Unity?
@ashen parcel well regarding rendering at least. youre fine to use burst, collections and jobs, and then ecs probably no major issues but i think hybrid renderer isnt well tested with vr
no its not
I only have 7-30 hrs of dev left before release, and when I delete objects, another job is upset. Look at this monster error. All I know is one line: DOTS_DRONE_AI.cs which is my drone AI file. The rest makes no sense to me other than knowing system files. https://pastebin.com/FjG3C0eX I think it is order of operations, I Destroy Entities in another job.
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
It's been a week of only 7-30 hours til release because I can't get through this wall
I think I got it. It isn't order of operations at all, but entities store a reference to another entity as target
when target is deleted, it tries to use the old reference
Now I just need to test for destroyed and remove target. I think I'm good to go.
That's the weird ass thing of new techs... Sometimes you think you're doing something wrong with the new tech, when you're just doing an old wrong. It's like when you play buggy ass League of Legends and you're not sure if you messed up or the game did.
If I have a memory address pointer to an Entity. Say Entity e; And I want to know if e exists or is destroyed... Anyone know syntax? This is awesome.
entityManager.Exists(ed.targetEntity);
Bingo bango I think I'm good to go. Thanks to my yolo bros.
nope... still got error. lol. This is challenging to know what is even causing the problem.
Oh, since I'm not getting a line number, I could try massive amounts of print statements, the offending last line will be identified because the print before it will be issued before the error. K!
Well this is strange! This happens AFTER the SystemBase that has the error is over!
It says DOTS_DRONE_AI has the error
But the Systembase was already done. Even the entityCommandBuffer was done
UnityEngine.Debug.Log("50");
}
}//The End
Its saying an error occurs in this file, when this file has concluded. Does EntityCommandBuffer take a while after the SystemBase is concluded to resolve?
Looks like an answer was given here: https://forum.unity.com/threads/entitycommandbuffer-isnt-happy-when-destroying-an-entity.1172360/
When I send simply one destroy message to an Entity Command Buffer, it starts giving errors: https://pastebin.com/DRcF3M75 in code:...
I was correct on assuming it was order of processing of something ECS with ECBs
Someone told me to use .AsParallelWriter for EntityComponentBuffer, but I get an error about this not being allowed in SystemBase and only allowed in Jobs: https://pastebin.com/Z6eBPHNG
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Still stuck on this, day 8.
Posting random errors without code makes it pretty unlikely anyone will be able to help you. Best way to get help fast is to post a minimal repro of the code that's causing the error, and a short explanation of what you're trying to accomplish
Yeah that's my issue, too, it's a large, complex project and I only get the errors when I push the load.
I'll duplicate the project and try chopping stuff out until I don't get the error, see how minimal I can make it
yah Sark, that is right. I just figured people saw this before... It shouldn't bust the system to destroy entities. Unity at least should give a clean way to destroy em... I thought that was the whole point of Entity Command Buffers, to do stuff at safe times. That's a good idea when I have enough rest in me.
good night
I cut out some code that deals with slowing down time and the error state changed to this, which sounds quite promising as a lead, but I'm not sure how to work out what structural change led to the invalidation it refers to:
This is the job where line 35 in this file is 130 in the error message above: https://hastebin.com/wulajufade.pl
I should say that I can also get the errors to occur without ever hitting this method, though, so perhaps it's not this that's the cause, I don't know any more 😦
so I have a few events that trigger from button presses to kick things off (eg confirm game start button, etc) - these do call the GameStateSystem publicly to make structural changes to control the other systems that run. I suppose those presses could happen at any point during the DOTS Update loop, which may account for some systems running where the previous expected systems haven't run within that update. I could try queuing those up to run via an ECB instead of instantly on demand?
object disposed could mean you deleted a component and tried to access it elsewhere? I dunno, just geussing
oh yeah
it says you'r trying to get a componentdatafromentity
yeah, it happens I think only on an event being fired that changes which systems run, and only when some of the systems are given a lot of work to do, at all other times it's all tickety-boo
in the process of making sure now that the events queue up entity creation/deletion in an ECB to see if that fixes it. Basically flying blind because the error messages don't lead to any specific place - I can force the error 5 times and get 5 different sets of error messages
@remote crater I think you are looking in the wrong place. It has nothing to do with the code in the systems but rather with the ordering of systems and this entity command buffer you are sending command to. Try to add [UpdateBefore(typeof(EndInitializationEntityCommandBufferSystem)] (or something along those lines) to your SystemDestroyAfterTime system and change the command buffer your DOTS_DRONE_AI system is using to something that runs at the end of the frame
Seeing some really weird behaviour with NativeMultiHashMap AsParallelWriter that i'm struggling to get to the bottom of
Hey guys, I've recently started with unity and I'm trying to use ECS but I'm a little stuck on something that seems simple...
I want to do something if Entities of ArchetypeA are within a range(distance) of Entities of ArchetypeB.
What approach would you recommend for this? I feel like it would involve something with ComponentDataFromEntity, or being able to make two seperate EntityQueries and iterate through both comparing...but I can't seem to figure it out. Hopefully this is ok to ask here. 😛
You can get a list of components like this:
var positions = GetComponentDataFromEntity<LocalToWorld>(true);
and use it in your foreach query afterwards. You just have to make sure to add:
.WithReadOnly(positions)
to the query
If you need sth more complex you can create complete queries without foreach like this:
EntityQuery enemyQuery = GetEntityQuery(ComponentType.ReadOnly<TagEnemy>(), ComponentType.ReadOnly<LocalToWorld>());
var enemyArray = enemyQuery.ToEntityArray(Allocator.TempJob);
var enemyLTWArray = enemyQuery.ToComponentDataArray<LocalToWorld>(Allocator.TempJob);
@pulsar jay Thanks! So in that first example, if positions are passed in as a dependancy, (if my foreach is over ArchetypeA for example) I could check to see if it's close to another entity, but how would I know if it's of ArchetypeB? or fetch other values from said ArchB?
In that case it would be better to use the 2nd approach as you can create a custom query for archetypeB. It is also possible to use HasComponent<> to check if an entity has a specific component inside a query but I guess the query approach would be faster
Oh btw you also need to use .WithDisposeOnCompletion(array) with your foreach query with each of the arrays to dispose them afterwards
That's what I thought too for the past week, but I'm not sure which ones to use, check this thread: https://old.reddit.com/r/Unity3D/comments/pwu6ru/very_weird_ecs_dots_error_i_get_an_error_in_a/
A weird question: Is there a limit to 9 components to a .foreach. This could help my design of my system architecture. I want to limit how many variables in each component due to the write cost of many when reassigning entire structs, yet at the same time if only 9 components allowed, I need to push extra data into related structs... This is a loss of organization and a puzzle challenge if cramped into 9 components. I could see myself commonly using 15+ if allowed.
I recently removed 1 component completely (to be fair it wasn't actually strictly needed) just to get in under 6 on one particularly heavy system. I try to keep each system to a minimum, I can't imagine many cases where you'd want anything like 15 components
I'm asking this question now, because if I assume only 9 components are allowed in a .foreach, but many more are able, then my structs are ugly and crammed. For long term sanity, I want to be able to access 15, 30 or even more in a .foreach
I like to have my components small because when you change em, you need to rewrite the entire struct.
So if your structs are bigger, this is more costly.
yes, and you want only the bare minimum of them for a job so that you can make efficient use of the cache
Also having all sorts of different structs allows for cool organizational technique
So you're saying proper design RooBubba is to make structs with hundreds of variables, not hundreds of structs?
of course I'm not
2nd question: Can you access components from an entity found in a .foreach not requested in the ref or in parts of the arguments?
Cuz that'd fix everything for me.
I'm already crammed at 9 non stop
And I keep condensing em
1 for entity, 1 for translation, 1 for physics mass, 1 for physics velocity, 1 for collision data, 1 for my general entity data, only left with 3 for actual custom stuff.
for SIMD goodness if we're going to extremes here, you can pack them more efficiently with float4 stride, but this really sounds like premature/microooptimisation
3 components isn't a lot to go with...
You can extend it to write more overloads than the 6 components + Entity + index + dynamic buffer if you want
Roo, how would I go about doing that? I might have to.
@remote crater You can write custom delegates that take in more than 8 parameters, but it's not advised because now you want 15 but later if you want 14 or 16 you'll have to write one new delegate for each one.
Usually you would rather go through jobs at this point.
You guys are very helpful. I'm gathering general info: Lets reel back to my secondary question: If I have entity in a .for each loop, can I just grab EntityComponentData, or is it dirty not slid in parallel memory if i do that?
And 15 is a lot, maybe your system is trying to do too much things at once ? Can't you really split the work on a bunch of more little dedicated systems ?
I thought I heard jobs were being obfuscated and depreciated
I like to make classes and scripts that apply to many different types of entities.
JobComponentSystem were deprecated in favor of SystemBase, but you can use Jobs
if that's what you're referring
So like above: CustomCollisionData & CustomEntityData might be applied to most of my entities processed in their own system. But I could have different stuff like,"Affinity towards objects", "Alignment", "Personality", it could go on and on.
Thank you VERY much
I am thankful
I don't want to bother you
You got me more than enough, don't want to bother.
That's okay, most important thing is not staying stuck for a long time
I don't need to get too crazy into it.
I'm stuck for 8 days
Trying to delete an entity.
In gameobject, this takes me 30 seconds.
I think I have a couple angle of attacks to get unstuck today.
If I get unstuck, I'm 7-30 hours out from a Finished MOBA +Finished MMORPG engine at the same time!
You know sometimes crossing the finishline is as tough as half of the entire race.
@pulsar jay So if i'm using that second example, I'd create those arrays with EntityQueries (with your example for enemies, presumbly add in more array's for a player), then create a job for them, then after scheduling the job call WithDisposeOnCompletion?
meanwhile I'm not able to track down this bug, but on the plus side I'm tidying up a few things as I go and getting some extra performance which is nice
Roo, I hear ya bro. If we do get stuck, best thing is not to get frustrated and walk away, just work on other parts. I guess I'm getting stubborn.
Tech hurdles are my mortal enemy. I hire a guy from India to do em for me, lol.
This project has been quite some time in the making, I'm not going anywhere until I get it right
The query defines the archetype you are looking for (archetypeB in your example). If you have your query you can create as many component arrays from it as you need. E.g. if you need to find enemies and access their position and health: Create a query with EnemyTag, Position and Health and then use ToComponentDataArray to create position and health arrays
and then dispose them after your foreach
Oh I pass the entityquery into the foreach? I somehow missed that lol
the arrays from it.
yeah you pass the arrays into the foreach query so you can access them
Foreach can generally acces every var you define in OnUpdate. You just have to be careful to dispose them afterwards as they are nativearrays
Thanks a bunch. Really appreciate it. I'll try that out. 🙂
good luck!
is SystemBase OnUpdate() called at the same time as the MonoBehaviour updates?
sorry that's a bit of an XY... I'm calling public methods on a SystemBase which then calls Invoke() on a System.Action to which lots of the UI/audio stuff is subscribed, I'm suspicious that this could be the cause of at least some of my issues
anyone know offhand the math (or where to look for the math) for transforming a float3 in local space into a worldspace position using a 4x4 local to world matrix?
I think the math literally might just be multiplication
nope, if you find out can you let my know, because I was trying to figure that out a while ago
but I can't remember
okay will do. I'm like 95% sure you can just multiply the 3x1 by the 4x4 to get the worldspace 3x1
yea that's how unity's transform system does it, TRSLocalToWorldSystem/LocalToParentSystem or something like
oh, yeah, its kind of like that except you cant multiply a 3x1 by a 4x4 because thats not how math works. You first need to put your 3x1 into a 4x4 so that its a space, then you multiply it.
so, like
L = [ 1 0 0 x ]
[ 0 1 0 y ]
[ 0 0 1 z ]
[ 0 0 0 1 ]
then the answer is L * ltw
so, @pliant pike in entities maths terms, thats:
math.mul(float4x4.Translate(myFloat3LocalPos), ltw.Value).c3.xyz
oh, I guess that gets you a 4x4 back, so then you have to...
fixed
that's awesome, thanks
might have fixed it 😮
hey definitely not sure how to answer your question, but what does that phrase mean? "a bit of an XY" -- sounds useful lol
yeah I was asking question X whereas I should have been asking question Y, the XY problem 😄
BUT... I seem to have fixed it, and I think I understand why which is awesome. It was all to do with raising events from within a SystemBase for everything else to subscribe to (UI, audio etc) to sort the game loop out properly, trigger creation/deletion of entities as needed. I ended up using entity command buffers for this to make sure all the entities used to gate systems are only created or destroyed at a sync point rather than at random times during the frame. I just stress tested it and couldn't get it to crash, which is a great sign. Going to put burst back on now and see how it looks in a build!
@pulsar jay worked like a charm 🙂
OMG my stress test without burst and with all the debugging in the editor was running at 170ms per frame (for 1000 enemies all running custom physics against a structure containing 2000 atoms). I figured it'd be slow in the build but it's easily running it > 60fps 😄
woohoo! congrats!
Cheers! Yeah that's exceeded my expectations (and I've been using DOTS for a long time in this project now!)
just started seeing this error when entering playmode.. any idea what the heck this means?
sorry, thats unrelated to your success haha
thats a general question
are you using a tuple somewhere in a burst compiled job?
oh, damn, yeah I am. A function is returning a tuple
wow, right, obvious
thank you lol
heh NP glad to be of help instead of whining about my failures for a change! 😄
what was the problem? 👀
I was raising events in a SystemBase for monobehaviourland to subscribe to. But when I called invoke on those, I was immediately creating/destroying the required empty components that are used to gate various systems, instead of syncing those to the update loop via an ecb. I had to do this across a couple of systems and I needed to introduce a 1 frame delay on a UI button (bleh), but it's all looking great now, and I understand where I went wrong.
Nice, congrats on nailing it down and getting it working too 🎉
Cheers! It's a pretty big project and I'm doing this solo (plus it's my first major project) so pretty relieved to have fixed it, even if it would probably not have been noticeable for 99% of users!
Is there a way to add an prefab-tagged entity to an ecb ?
Like telling the ecb it should copy an entity with all its values ?
Thanks ! Uhm... how does that work ? xD ecb.CreateEntity(existingEntity) ?
ecb.Instantiate(Entity e);
Alright thanks ! 😄 What happens if one of the components contains a unsafelist for example ? I bet the whole list wont get copied and its just a shallow copy ?
I don't know
Yea believe its just a shallow copy, don't think it's going to request memory in the chunk
Alright thanks !
Is there any way to check if an entity in the ecb has an component buffered ? So like an HasComponent<T> for the ecb ?
There need to be a way, right ?
I don't think so because it doesn't exist yet
But its buffered and the buffered data needs to be stored somewhere 😮 so its actually possible to make such an lookup... but it isnt implemented ?
Well I mean you either give the data and it is there or it isn't which would be an error surely
How would a buffered command deal with a hascomponent
Isn't that just checking what components are included in an archetypechunk?
If the component doesn't exist, you know it hasn't been 'buffered'
therefore no ecb has been played back to add a component
Thats right ^^ but is there a way to get the archetype of an buffered entity somehow ?
get the archetype before attempting to schedule a command buffer?
I'm not really sure what answer you're looking for
The only reason I can imagine why you're not already aware of what entity archetypes that you're buffering is because of generics, yeah?
If you had 3 systems that are checking for something similar, such as proximity of entities, would you move them to the same system (still 3 seperate for each) or leave them as 3 seperate systems?
I'd separate them out, easier to find stuff that way imo
depends how similar, if the jobs arent I might personally lean on keeping in one, but then again you can disable systems so maybe separating into 3 systems might make more sense for testing
questions about job system here?
@craggy steeple yep
can I have structs in the main struct? idk what its called
it looks like I cant use arrays or other structs
you can use the collections package to add native types which replace managed arrays,lists etc
how do I use a 2d bool array?
can I still have an array as a parameter of the struct?
can you post what you are trying to do? not sure if I understand
public struct Data
{
NativeArray
public Data(bool[] a)
{
// convert bool[] to nativearray
}
}
I just upgraded my project from 2019.4 to 2020.3 and I lost about 100fps in my project with no changes beside the upgrade. I only use the job system. I Can't figure out where the perf went...
this is what I pass to the job if I know what you mean
if i have arrays it doesnt work, but what if I only have array as parameter and dont save it when creating the instances?
anyway just something like
var array = new NativeArray<bool>(a.Length, Allocator.TempJob)
for(var i = 0; i < a.Length; i++){
array[i] = a[i];
}
btw even though I'm not doing anything with it yet I lost 50fps using jobsystem
Im giving it around 400 "Data" with empty "Run" methods
..that it calls and gets results from
alright
but generally speaking, I think you should lean on the native arrays just being part of the job struct, they need to be disposed manually if you are using them as persistent
I dispose them at end of "Run()"?
some extra reading on the allocators for native collections - https://www.jacksondunstan.com/articles/5406
JacksonDunstan.com covers game programming
and what is causing the lag?
@vital sandal use the profiler if you have a backup of your project prior to upgrading and profile before and after upgrading
@safe lintel good idea
if you use .Run() it will run the job on the mainthread immediately, and potentially force any other jobs going on to also complete, you should be using schedule or scheduleparallel
I have this
🔥 Save 50% on ALL assets from Synty Studios with code SYNTY2021 (offer ends 9/11/21)
https://assetstore.unity.com/publisher-sale?aid=1100l3e8M
In this video, we'll use the Unity Job System to optimize some CPU-intensive code.
#Unity3D #GameDevelopment
Unity's Data-Oriented Technology Stack — Unity DOTS for short — is a package that consists o...
7:57
shouldnt this run "Run" on all 400 instances in a fast way?
Are you using the stats view to read the fps out?
If I remember correctly there have been some changes to it to make it display a more accurate number in the editor
I couldn't find the forum thread where I read that, maybe someone else knows more..
@craggy steeple well he schedules and then completes, which is slightly different in that it uses job threads but then completes immediately.
@north bay Mmm.. strange, the latency just after hitting play with nothing in scene has gone from 0.2ms in 2019 to 0.8ms in 2020 but when my job code is running it went down from 0.4 to 3.7 and using another fps script I was at 590fps and now 778fps.... so which is which? hahah Maybe it would be better to compile it but it appears there is no perf loss after all.
thank you
what should I do?
seems internally they are working on entities 0.20 : https://github.com/Unity-Technologies/DOTS-training-samples/commit/9fd59f0de752a2d80925a1e562dfb7adb697e72c (info from forum - github address is from dots samples)
also netcode current version devs are working on is 0.8 and last published is 0.6
(info is from netcode forum by the devs)
One of my entity command buffers somehow record an Entity.Null which throws errors... i already disabled burst and enabled the debugging, but it still cant tell me where the heck that entity is being recorded. The exception says the location is unknown...
How do i ever find the place where an entity.null gets inserted ? It could actually be everywhere in my code 😮
stupid question but what is the difference between dynamicbuffer.Isempty and dynamicbuffer.length = 0
what the hell does it mean to get the cross product of a position and an angular momentum vector 😵💫
im not sure. what leads you to believe there is a difference? maybe isEmpty is implemented with a length check
I don't think there is a difference, I'm just making sure I haven't misunderstood or something
Is this the right place for Animation Rigging questions?
Specifically, where do I inject bone transforms if I want Animation Rigging to modify them?
@craggy steeple use schedule when you can
@ruby frigate I think the animation rigging package falls outside of this channel though internally they may use jobs & burst for it
What does the error say? The entity has been destroyed?
I'm not sure how an ecb would record an entity.null unless you were the one passing it
Which is a different problem from an ecb trying to access a destroyed entity
How do you guys use to check if a NativeList or NativeHashSet needs to be disposed on destroy?
I've been using if (array != default) array.Dispose() but that doesn't work for NativeHashSet and NativeLists. Are we supposed to use IsCreated? I read a lot of posts mentioning problems with it and suggesting to check if default instead.
There's IsCreated
@shell berry and never had a problem when using IsCreated? meaning it works reliably?
Yeah
Thank you
Wow, I do this in a job myNativeHashSet.Add(index); MyNativeList.AddNoResize(index); and when I print them out in the console I completely different list of numbers. It looks like the list may be out of order but the HashSet is ok.
I'm using ParallelWriter if that changes anything
hmmm.. after testing, the content is the same but the order of the list is all messed up. Is it normal to have to sort the list?
If it's created in parallel, you can't guarantee the order
Yet NativeHashSet has no issue preserving the order
I don't know enough about how the HativeHashSet<T>.Enumerator works to answer that - I'd query how it's being iterated first (I seem to recall NativeHashSets having a different layout than regular HashSets but I am hazy on the details)
at Unity.Entities.EntityComponentStore.ThrowIfEntitiesPerWorldIsTooHigh(Unity.Entities.EntityComponentStore* this, long newValue) ```
This is weird, it even says in the header comments in EntityComponentStore:
```cs
// ---------------------------------------------------------------------------------------------------------
// EntityComponentStore
// ---------------------------------------------------------------------------------------------------------
// - Internal interface to Archetype, Entity, and Chunk data.
// - Throwing exceptions in this code not supported. (Can be called from burst delegate from main thread.)
// ---------------------------------------------------------------------------------------------------------
then on line 370 it's got the throw:```cs
void ThrowIfEntitiesPerWorldIsTooHigh(long newValue)
{
if (newValue > math.ceilpow2(k_MaximumEntitiesPerWorld))
{
m_IntentionallyInconsistent = 1;
throw new InvalidOperationException(
$"Maximum Entities in World is {k_MaximumEntitiesPerWorld}. Attempted to allocate {newValue}.");
}
}
does anyone else see this error when building in Entities 17 preview 42?
so it checks length + created or not
this would be the normal of a plane containing the position point and the vector. Not really a DOTS question :p but there sure is methods in the math package
oh cool thanks @karmic basin
Burst doesn't support throwing exceptions. The error tells you you can ignore it with the given flag, because it's okay for debugging for example, but that shouldn't happen in a build.
I'm curious, how many entities did you have that triggered this exception ?
internal const long k_MaximumEntitiesPerWorld = 128L * 1024L * 1024L; // roughly 128 million Entities per World, maximum
Did you have an infinite loop or something ? 😛
no I'm not spawning any entities for this, the error being thrown during the build is simply that there should be no throw in the code - but that code it's all Unity's, not mine!
Oh I thought you were having this specific error message
Then yeah whatever throw in build you have, you should fix it. I know, mindblowing 😛
its unity code?
Yeah the component store is Unity's
Is the message you get actually an error that stops your build from completing?
I think they changed it to be a warning a good while back
sorry yes that was nonspecific, it doesn't affect the build, I think it's a warning or a message, certainly not an exception
I'm not calling throw anywhere, Unity is!
Yeah but what does it blame you for ?
Why does it throw ? There's def a reason, and you need to find which one, and fix it
True, could be that too :)
It's only referencing Entities classes all the way down in every warning, there's no reference to any of my code at any point
I'll hunt around for exception calls, just to make sure
Whats the most efficient way to query or search entities ?
Currently i do it like this...
var query = CreateQuery(...);
var entities = query.ToEntityArray(Allocator.TempJob);
var components = query.ToComponentArray<...>(...);
// Loop over them
// Dipose
I do this quite often to search for entities with certain values... Is there any gc free way of doing this ? Some sort of direct acess ?
https://docs.unity3d.com/Packages/com.unity.burst@1.5/manual/docs/Warnings.html So yeah I'm getting these warnings but the only time I throw exceptions are within a monobehaviour dedicated to disk read/write, there's nothing from anything using burst or entities. I was just wondering if anyone else found this before I tell unity about it. At the very least, it should point to where it thinks this is coming from!
this incurs GC? Thought they're allocated via nativearray. Also is this really slow because you're iterating over thousands of entities?
The code you posted is gc free. You could also pass in a NativeReference<Entity> to a regular ForEach and stick the entity you're looking for into the reference
It's only GC free if ToComponentDataArray doesn't target a managed type
So right now I currently have basically no game objects, everything is an entity and I'd like to let the user click on and select certain entities.
Do I need to allow items I want clickable to also have a corresponding game object to fire click events?
Or should I try capturing the location of the click and check if a clickable entity is at that location?
What's the normal/ideal way to do this?
Do I need to allow items I want clickable to also have a corresponding game object to fire click events?
I would avoid this voodoo unless you already map entities to gameobjects
I project the bounding boxes of my entities into screen space and check whether the mouse is inside any of them that approach works pretty well for me
Yeah that definitely is more preferable to me as well. Is there any chance I could trouble you for a small/partial code snippet of that?
Sure let me copy/paste something together
Thanks
It's not very plug and play since I had to cut parts of it out of my code
It has the code to determine whether an entity is hovered but doesn't attempt to find the closest hovered entity since I don't need that for my use cases
Yeah, So you basically have an authoring script attached to your entities that checks if they're being hovered. Presumably this is attached to the prefabs you expect to allow this hover?
Also dumb question, the MousePosition value, is that a global thing or is there a special way to fetch it?
Ye I attach that authoring to the prefabs that can be hovered over
You can also add the hovering bounds during runtime If you don't use prefabs 🤷♂️
I pass the MousePosition to the job, if you use the legacy input system you can use Input.mousePosition
It just has to be from 0, 0, to Screen.Width, Screen.Height
Cool thanks a bunch 🙂
Just a random thought, is having an authoring script on each object or a system that runs the same code better?
I feel like the authoring would probably be better, but it was just a thought
Sorry, what do you mean?
The authoring doesn't exist during runtime
The could that checks whether the entity is hovered would be in a system
Oh it implicitly creates a system to do it?
No my code is just badly copy/pasted
Ah my bad.
I confused myself with my glance.
Thanks for the clarification
You clearly stated in the IJob and my mind did weird things lol
No worries 😄
Even if a bit late thanks to Sark and itsjustblank for the answer ! ^^
Is there any way to run a query in a scheduled job ? I need to query for some entities in there 😮 and if i try to use a entitymanager there it tells me its forbidden and i need to complete the job first.
So my question is basically if theres a way to query entities in an scheduled job
What about using query.ToComponentDataAsync<T>(alloc, out var handle) and similar apis?
Thats interessting ^^ How would that look like ? So can we call that method inside an job, force it to complete and then use the result ?
no
you would call it in OnUpdate, but it schedules a job which collects the ComponentData to a nativearray
you can then pass this native array to another scheduled job
var data = query.ToComponentDataArrayAsync<T>(Allocator.TempJob, out var deps);
Job.WithCode(() => {
// Do something with data
}.Schedule(deps);
Ahhh i understand 😄 thats cool... didnt knew that this would work. Im gonna try this, thanks !
Yes I've seen that! I don't remember which function it was but I ended up inspecting the code and stumbled on a bunch of methods that weren't yet implemented. All with a similar message. I guess that's why it's in "PREVIEW" I've seen some code around to make our own NativeCollections... Maybe I can implement a list based on some ideas from NativeHashSet's code.
Thank you, I'm not going mad!
no! 🙂
Is it possible to disable physics objects in unity.physics?
ie so they are not calculated at all no mass/velocity/dynamics/collisions etc
i'm guessing no simple way at this point to just 'switch them off'
yeah, its actually slightly more nuanced than that. Geometrically you're getting the normal of a plane, but semantically, when you take cross product of a position and an angular momentum vector, you're getting the instantaneous rotational impulse that you would apply to point 0,0 in order to achieve the angular velocity at that point.
And yeah, was a DOTS physics question ultimately. Ultimately what I needed to know was whether the input to ApplyImpulse was in local space or world space, since it isn't documented. (it's in local space)
so its getting angular acceleration (around a fulcrum) from linear point velocity attached to the fulcrum
Ah that's great thanks
I was looking for a way to effectively pool physics objects without the need to instantiate
so i could create a pool, apply PhysicsExclude to them, then remove when i need to wake one up
why not just instantiate?
mm i could but i'm looking for a way to integrate it more seamlessly into the existing system i have without much or any reliance on ecb etc if possible..
i may have to use ecb in any case but if the entities technically 'exist' i can refer to them within the system but defer 'awakening' to later using the ecb
If you have an enemy entity, (and say health component and velocity) does it make more sense to have an enemy tag and add those 3 components? Or add the hp/velocity to the enemy component, there in only adding one component to the entity?
do you guys store archetypes and queries on a dedicated place, so you don't have to have the same component type array in every relevant system ?
I wanted to make it that way, but it appears more difficult than it seemed, because whether the queried components are rw or readonly depends on an individual system
If it's for pooling, you might as well just disable the entity?
can you have a physics raycast job run for multiple frames if you know the all the colliders are static?
i get an access nativemultihashmap error when I do because I think the physics system rebuilds the world every frame
Definitely an empty tag for the enemy. That way you can have systems that run on health but don't care whose health it is (etc for the other component types)
Should i dispose entityArray in this case? Or DestroyEntity(entityArray ) will do for me? Unity doesn't throw exception on this case without manually Dispose()
No you shouldn't
Dispose on temp allocations doesn't do anything
UE5 just added a ton of ECS stuff to its main branch. Looks similar to dots ecs from a glance. 🤔
any follow ups on unity side for the dots state?
not sure if I can link that here, but you can find the plug in on ue5-main branch, under MassEntity plugin folder
It's far from similar to the Unity ECS, close to other C++ ECS's, like EnTT
well, obviously it is in C++, I meant similar as in using similar concepts like archetypes
do they have any docs for that?
no, it dropped in hot, and the main branch is at 5.1 right now. So it won't even be available for the 5.0 release
Ah right, I hadn't looking into the storage mechanics yet
This shows some examples of the API
they're probably using it on fortnite
ty
You're right, it's archetype based, fancy
🙈 I don't wanna look, I don't have time to switch to UE5
looks def interesting, large-scale AI system 😋
Nice, that means more pressure on unity to deliver something 👀
That didn't really work like that on terrain layering system though (they teased it for year+, then UE implemented their own system and it's been radio silence from Unity since on that topic)
fully expecting unity to get leap frogged in no time at this rate
Looks very similar to chunk iteration.
Yeah the source shows mentions of archetypes and collections of chunks attached to them
Oh shit, is this a legal battle about to happen?
Neh, because Unity wasnt the first to use archetype based storage for an ECS
It's up to Unity. They can sue for patent infringement, then Epic defends by showing prior use.
There's a court rule that it's your responsibility to defend your patents, or something like that.
I welcome the competition, though
C++ might have an edge here because they have no distinction of contiguous memory layout between objects and value types.
nah i dont think you have to defend patents to keep them
if it were trademarks i think you need to actively defend em
another general ecs question: ecs, due to its nature to be more computer-friendly, and to have implemented solutions that are either abstract or not very apparent what those do, probably needs a lot of external project documentation
do you have one ?
do you rely heavily on it ?
how do you maintain it ?
skittles ?
no no no yes?
if someone's reading through your ecs code, you should expect them to know ecs, right?
hi, im trying to convert a prefab to an entity using the ConvertGameObjectHierarchy method, however, the children of the prefab dont get tagged with the "Parent" component, do i have to do it manually?
sure, they know ecs (obviously, let's just consider it an axiom), but they don't know the project, they don't know the archetypes, systems update order, solutions that cannot be visualized with the oop real world abstractions, etc.
@gilded glacier btw im in no way qualified to talk. i still dont think so. archetypes are handles by ecs so you dont touch that. systems update order? open up the entity debugger whilst running.
but i imagine some big projects in OOP sometimes write documents to describe a system if its too complex to explain in the comments
citation required
Any tips what can cause to this error when i build app
So with DOTS what's the best way to implement varying type of something? enemies, weapons, skills, etc.
I see them and keep thinking with OOP mindset of wanting abstract classes with overwritten methods and getting instance of, etc.
So I see my enemy ComponentData and want to make it abstract or something, but it keeps complaining I can't do such things, so I feel i'm thinking about it wrong.
What do you guys tend to use for this kind of thing in DOTS?
I typically think of everything in terms of raw data without abstractions to avoid thinking about things like override. You have a minimal set of data required to do something, write functions to process that data, put them in systems so those functions execute on the entities you need.
I typically use bitflags, filter entities with the correct bitflags, and run jobs to do w/e behavior.
so the end goal is like having a bunch of different weapon prefabs with the same components and just different values
Yea pretty much
then in game if you give a couple choices to the user to pick, how do you choose to uniquely label them?
do you add a label data component?
It didn't seem to like me using string in them.
Use FixedString if anything
maybe this thread (or try to find similar on dots forum) can be helpful : https://forum.unity.com/threads/implementing-a-complex-rpg-combat-system-with-dots.809361/
strings won't work because they're classes and have to be managed in C#.
FixedString512, etc are good alternative and come with size limits so don't go thinking you can load like 50k characters. You'll probably need to break up large pieces of text somehow. (Otherwise consider something like a bump allocator of characters if you need large pieces of text)
also plenty more similar threads u can find on unity-dots forum
imo strings can always be replaced by something "better". Lets take the example of implementing different "classes" of weapons. My weapon "classes" would be tags (so empty structs) that instruct my initialiser to add the appropriate components to run the appropriate systems to make the weapon work.
imo you should only ever use strings when dealing with GUI
That's kinda what I wanted too, I just feel the desire to map them, like extend a general "Weapon Type" or something...
I really didn't want to put strings in my components, It's just the fallback. I wanted a nice component way to express the types.
i would split your weapon type into different atomic weapon systems?
Just like if you have a weapon, I think Id want to to only have 1 component for it, not 1 weapondata and 1 weapon type.
i would use multiple weapon systems (and weapon data) for 1 weapon type
for example, a sword class could have "attack system", and "block system"
then a shield class could reuse the "block system"
so then if it's like this type of lazer weapon is unblockable, how in your block system would you want to check that?
see if your attacking entity contains a component tag for lazer type? or would the weapondata have some mapped value to it's type
Could check a mask value, if the mask passes, then you know that there's a "Block" flag and the other entity is blocked, otherwise it's not blocked. Cause in the end you can just have it as damage multiplier or some gradient damage scaling system.
well i think a lazer weapon either would be "inherently" unblockable (in which case see if your attacking entity contains a component tag for unblockable type) or some lazer weapons are unblockable (in which case maybe your "shoot system" should have a unblockable bool)
i wouldnt use a mask because unless you have a whole bunch of booleans to check lots of times, its a pain in the butt
Yeah I might've gone on a tangent, I think I have to reel my thoughts back from OOP to DOTS, and think whats the practical difference besides values, if a difference exists it probably deserves a component or tag, and possibly a system
youre thinking correctly. fyi ive never implemented what im saying, i am talking shit.
yea, start with booleans since they're simpler, but if you have some thing complex - consider masks
you can have oop parts and classes on an ECS just fine
for specific things where you want your virtuals and similar
ofc pure DOTS bursted wont allow it
you can have monobehaviours seperate from ECS that uses classes just fine, you cannot have objects inside ECS* (with some special exceptions)
idk if its ideal, but thats the solution ive come up with
You might want to use an ECB for that
can i use one in a monobehavior?
Yeah
It's just a struct
You make one, use it to queue the component adds, and then call Playback on it, passing in the entityManager
If I remember correctly this combines the component adds, so the child entities wont change archetype twice
alright thank you
The way I solve these relationships is with utility functions, something I feel is an under-appreciated in most ECS discussions I've read: Take whatever abstract class you want to make, move the state into a component and move the behavior into a static function inside a static utility class. You can then "implement" the component inside a system by calling the function, going so far as to even pass in functions through action or func parameters as a replacement for abstract or virtual method overrides in objects. Unity's hybrid renderer uses this approach, and uses "description" structs to craft more parameters for functions with too many or more complex parameters.
and if you like, you can enforce usage of the utility function by making the component fields internal and treating your namespaces as the domain of data hiding and encapsulation
so something like
public float Area {get; protected set;}
private double _growTimestamp;
void Update()
Area = CalcArea();
if (Time.time - _growTimestamp > 10)
_growTimestamp = Time.time;
Grow();
abstract float CalcArea();
virtual void Grow()
{
}
becomes
struct ShapeData : IComponentData
float Area { get; internal set; }
internal double _growTimestamp;
static class ShapeUtil
public static void UpdateShape(
ref ShapeData shape, double time,
float area, Action grow)
{
shape.Area = area;
if (time - shape._growTimestamp > 10)
shape._growTimestamp = time;
grow.Invoke();
}
Quick question... How are scheduled and scheduledParallel iterations implemented ?
I mean... lets say we have two systems scheduling jobs... Do they really run parallel to each other ?
Or is it more like the first system spawns in its jobs, processes them... The second system waits for the jobs of the first system to complete and then creates its jobs ?
Jobb would only wait for Joba if joba is a dependency. Otherwise they might run in parallel, or they might not, depending on what else is going on in the scheduler
What is the absolutely lightest, fastest way to get a ParallelFor Job pushed off to OTHER cores that are not the main core of any given device?
I want to issue a Job and be (as best as possible) assured that issuing it and receiving its "we're done" status have the bare minimum impact on gameplay smoothness. None, preferably. Main concern Android devices, but all others a concern, too.
Don't care how many frames the Job takes (within reason) but do care if issuing it or receiving its "done" status cause any kind of hiccup.
You could check it in update or a coroutine and if it's complete, get the results.
As for specifying what core to execute the job on, I don't think you have control over that aside from JobHandle.Complete() that's gonna wait on the main thread until it's complete or IJob.Run() that's just gonna run it on the main thread. But I also don't think that scheduled jobs have any impact on the main thread performance.
Alright thanks... So how does it work in theory then ? I couldnt find anything about it yet ^^
I mean, why dont the scheduled Or parallel jobs dont mess up with each other ? How does the ecs make sure that those multithreaded entity iterations and modifications are working as we want ?
So i basically search for a way to replicate unitys ecs jobs ( for my server which uses a different ecs and language ). Therefore i need to understand how unitys ecs jobs work in theory ^^ would be great if someone could provide some details
It probably "locks" the native arrays that it works with and does not allow other jobs that use them to run.🤔
Does every System script that I write... just run all the time? Without attaching it to anything?
Yes, but "It's complicated"
By default, every system is added to the Simulation systemgroup, which runs every frame
But while this "runs" your system, it will not always run your OnUpdate step
It will only do this if it "needs" to, and this depends on if you have the [AlwaysUpdateSystem] attribute, or if any matching archetypes used in your system have 1 or more entities that frame
Same questions. Where do we find concrete quantification and qualifications of what is what, does what, and how, why, when and where... etc.
Does everyone just do isolated testing as research to figure this out, and then keep this information to themselves? Do the makers of this tech suffer from some inability to explain their tech?
Most of the documentation on most of the features and functionality are near perfect restatements of the method signatures. Pure tautology rather than anything close to descriptive, let alone explanatory. How few people use Burst and Jobs that this isn't considered bad form?
Granted, ECS is shifting sands, but Burst and Jobs are basically completed. Yet the docs and demos are ... barebones, if I'm being generous.
And the youtube videos... froth for 15 out of any 20 minutes, then more "watch me write code" and "dada!"
Unite conference videos? 'Learn to use float4 to get the SIMD benefit, think down not across', all of them. Each nearly an hour.
Exactly... glad im not the only one with those complains.
Unless you have the C++ source code we won't know exactly, since internally Unity will call an extern function to native code
I would rather learn how multi-threading is done in this language you use on the server, that has nothing to do with Unity anyway 🤷♂️ , right ?
Of course, but i still would like to learn how jobs are implemented in unity. I actually think its a write/read lock style... atleast it would make sense because there those ComponentType.Read<T> things.
I still don't get it, but nevermind.
There's some high-level info on the manual, dunno if that's what you're looking for or if you expected more low-level https://docs.unity3d.com/Manual/JobSystem.html
Read/Write component types have nothing to do with the way the job system works internally
You need to see unity's ecs and the job system as two separate things
No idea how the job system works internally but this is how entities handles scheduling on a high level:
Each EntityManager (or world) has a ComponentDependencyManager, this struct is responsible for tracking component read/write access
When a system needs to acquire any kind of access to a component (this can be a ComponentTypeHandle, ComponentDataFromEntity, BufferFromEntity) it adds the component type to either it's writing or reading component list
When you then later access the Dependency property it passes those lists to the ComponentDependencyManager which then builds a job handle from the passed component types and previously scheduled jobs
After your OnUpdate call has completed the internal AfterOnUpdate method will pass your systems job handle + the component lists to the ComponentDependencyManager which can then use it for the next system that asks for the components your job uses
C++ Source Access shouldn't be needed. It should be elegantly, clearly and wonderfully explained so that we can all use Jobs and Burst as best as possible, and make better games, more easily, making Unity look better, etc.
It behooves a tool maker to empower their users. Unity's good at making claims and pushing out promo pieces, but not so good at explaining what they're claiming.
Sure that'd be ideal, it's just not the reality at the moment.
It's not hard. Jobs and Burst have been finished for what... 2 years?
Yea I get the frustration - dunno what else you want me to say 🤷
What have been your discoveries of the best way to use Jobs/Burst? (let's avoid ECS, for now, as it's way too speculative)
I just experiment - everything relies on the jobhandle, so the most important thing for me is when to call JobHandle.Complete()
If you need a job to run multiple frames, then you may want to figure out a design that allows you to schedule only when needed and when there isn't a running job (if you only care about running 1 job at a time)
anybody know how LocalToWorld interacts with the fixed step stuff in physics?
like, I just stopped to consider that maybe LocalToWorld isn't being updated until the next display frame, regardless of how many physics frames run
and in particular I wonder if other things like WorldToLocal dont get updated in physics frames
physics only uses translation for dynamic/kinematic, tbh I cant remember if it uses ltw for static or still translation there too
physics basically ignores the entire transform system for rigidbodies aside from translation and rotation
Agreed. That we have to make distinctions between that which we'd like to in a frame before it renders, or other options (over one frame to the next or multiple frames) should be front and centre in all teachings on it. And that these are, for all intents and seemingly purposes, exclusive. You do one, not the others.
Yeah another I saw (but still need to do more experiments w/) is - if you schedule on LateUpdate, based on the profiler, it looks like it'll just block the main thread
Further, that Burst/Jobs are capable of incredible performance and don't have a unique, more granular timing option than frame rate or physics rate is a huge failure of imagination in design.
I've seen that, too. And been a bit worried about it in terms of what they plan there. So just avoided it because I couldn't ascertain what they were thinking... which, again, would be nice to have insight into... "we've provided this, it operates this way, as we envisage it being used for this..>" etc.
There was a forum post in how they were handling allocators - which would possibly change how jobs would handle leak detection - so something to look out for