#archived-dots
1 messages ยท Page 236 of 1
also it's still compiled against .net framework :C ......but fortunately that will change soonish too and be compiled against .net 6.0 YAY
i've no idea what .net 6 really means but it sounds cool! ๐
Dafuq. It's literally what you write code for. Well....net framework / standard in unity currently, just the newest iteration. But soon .net 6 will be available in unity as well.
I'm pretty sure I write code in Mono and Burst ๐ anyway, should been more clear, I don't know what .net6 means when VS2022 runs on it. faster? great.
Mono is .net, just a fork
And .net 6 VS means better performance, better everything, and even finally Roslyn extensions written in .net 6
And unity is slowly moving away from mono anyways. Finally.
pretty sure enzi was aware of the fact that mono is a fork, which is why he also included Burst in that list. he's pointing out that his question was facetious. He doesn't know what .net6 means to him as a developer, he's not saying he doesn't understand what it is as a concept ๐
that would make even less sense though. cause it's the newest .net version so you know by standard that there's much more developer goodies in there
I'm getting this error when using 2d entities ArgumentException: A component with type:EditorRenderData has not been added to the entity. with a sprite renderer. do i need to not use entities for 2d entities to work or am i missing something'
but it seems to work when the entitiy is in a subscene?
Ever tried IntelliJ Rider? If so, how does VS 2022 compare to it?
Right now im paying about 15 bucks a month for IntelliJ rider, but its TOTALLY worth it.
It actually properly renames both namespaces AND directories at the same time.
(IntelliJ is just excellent in general)
too sluggish imo ๐คท
Hmm, never bothered me. Seems plenty fast.
yeah i spoil myself with vim so when I hop on any other IDE it feels bad ๐ฆ
I guess I got a similar feeling whenever I switched from Android Studio (IntelliJ-based) for work to Visual Studio for game dev hobby stuff.
That ended when I discovered IntelliJ rider, ofcourse.
Something I do miss from VS Enterprise though: The code dependency graph generator!
it was excellent
but its crazy expensive, I only had it because of a student licence.
After it expired, I missed it so much I hacked together something myself that does code analysis and generates a .dgml that I can open and view in Visual Studio Community
i use rider, quite like it over vs, and it was faster than vs when I first started paying for it but that mightve changed?
lots of nice little things that afaik vs doesnt have, imo potential killer feature now is how much better working with shaders is now
like being able to navigate to definitions, for shaders is truly amazing
Oh thats right, its indeed excellent for working with shaders too
i do long for the speed of vscode but vscodes autocomplete is terrible(at least for me), and rider's intellisense can sometimes break and require restarts
Haha yeah the Rider issue is very strange
I have it too
it starts putting red error lines under completely valid code
yeah its annoying
i quit my sub right before they released the version with shader editing ๐ข kinda gutted
Rider sometimes caches invalid or partially generated assembly files during loading (if it and Unity loads at the same time) so it'll start crying about how it cant identify methods located in unknown packages but unity is all fine. Gotta invalidate caches and restart rider. Which is incredibly annoying as I have a streaming assets folder about 8,000 files large that should not be added to Rider's intelli-j identification and re-ignoring them all nearly crashes Rider.
dang
luckily takes about a minute for me
Does anyone here know how we could generate code ?
Do roslyn code generators work ?
No one ?
Uhhhh, they theoretically work? Last I heard, unity's looking into a deep integration with Burst and DOTS but that was over a year ago and nothing came of it. Now, no clue.
Weird... i found a few forum posts where people complain that they cant get roslyn to work.
And i actually wanted to generate some nice methods to ease the setting/adding/removing of components... kinda like variadic templates ( c++ )
like this : entityManager.Add<T1,T2,T3...TN>(in T1... in Tn);
Its just an example of what i wanna generate
https://docs.microsoft.com/en-us/visualstudio/modeling/writing-a-t4-text-template?view=vs-2022
I'm not sure whether this is separate from the Roslyn thing but there's something called T4 that perhaps can do this for you? Not sure, I did not look into all the details
If code generation proves to be too much of a headache, perhaps you might consider a purely code-based approach.
For example, you could write an extension method for EntityManager such as an AddComponent that accepts an EntityArchetype instead of just a single ComponentType. You can then have these EntityArchetypes pre-defined somewhere.
Although... That wont work if you want to also add the combined component data in the same method call..
Actually, couldnt you already write such an extension method for EntityManager? Or am i missing some nuances here
I have a weird case where a Burst Job produces different, incorrect results after the second time it is run (after recompilation/reload) for the SAME input arguments. The first run produces correct results.
When I disable Burst Compilation, it works as it should and every run produces correct results.
Anyone have any idea what is going on?
(NOTE: I dont do anything fancy with special attributes that disable certain safety features and such.)
It gets weirder:
Changing the job code only affects the first run (again, produces correct results).
However, for the second run, it seems to ignore any code changes. It produces the same wrong result every time - as if it used a different, very outdated cached version of the compiled Burst Job somehow.
Ill try a reimport all in Unity + IntelliJ cache invalidation
This seems to have solved it. Damn
Cache corruption of some kind it seems...
Maybe I should check out newer versions of Burst...
source generators 100% work
Hi, I'm working with some vector3 maths inside of a jobs thread and also using burst compiler. Should I replace operations like Vector3.Dot with math.dot or does burst compiler handle that automatically?
Hello all!
I've been struggling with a particular problem for a while now. My small experience has told me that when it takes this long to figure the solution my approach is probably wrong. I'll try and explain it simply:
For each entity matching a given query, instantiate a given entity prefab and destroy these entities when the source entity is destroyed.
The current design:
public struct SpawnForQuery : IComponentData
{
public EntityQuery m_query;
public Entity m_prefab;
}
And the system update:
protected override void OnUpdate()
{
EntityCommandBuffer.ParallelWriter ecb = m_ecbs.CreateCommandBuffer().AsParallelWriter();
Entities
.ForEach((int p_entityInQueryIndex, Entity p_entity, in SpawnForQuery p_source) =>
{
using NativeArray<Entity> targets = p_source.m_query.ToEntityArray(Allocator.Temp);
foreach(Entity target in targets)
{
Entity spawned = ecb.Instantiate(p_entityInQueryIndex, p_source.m_prefab);
}
});
}
The problem with the above is that the query will find entities that already have an associated dependant entity. Resulting in multiple spawns for the same source entity.
Usually we could add a component to the source to mitigate this issue (by adding an exclusion for the added component). But what component do I add? There could be multiple SpawnForQuery components that find the same source entities - so we would need a exclusion component for each instance of the SpawnForQuery component.
I would like to be able to configure the SpawnForQuery once and for it to pick up pre-existing as well as new entities that match the given query
Is this possible? Am I (most likely) overcomplicating things? if so what would be your approach?
Another thought is that SpawnForQuery could be given a UID . A component with this value would be added to the source entities and then we could exclude these source entities by excluding all components with the given UID. However, I don't believe there is an inverse SetSharedComponentFilter .. is there?
Is the m_query unique to each SpawnForQuery component?
ie is each SpawnForQuery likely to be doing a different query, looking for different components etc
Those are actually great ideas ^^ I tested T4 and it works... but well its not really dynamic like roslyn is xD
And yes i could already write such extension methods by myself... but its a lot of repeated work if you plan to support T1-Tn generics ^^
Roslyn source code generators ? If so how ? As far as i know we need to have them as a seperate project in our solution which unity doesnt support
yes math.dot is specifically optimized to work with burst if possible you should use as much as possible the classes from DOTS-specific packages / extensions and not legacy Unity ones
you can simply integrate them into your project by compiling them to a dll and putting them inside the project, and changing a few import settings for this dll. simple
Any tutorials ? Or guides ? ^^ Never done this before...
Besides that... will it still work in realtime ? Atleast the rosyln code generators i know do work like this :
I type "myClass.DoStuff<...>()" -> 1 second later roslyn analyzed the code and generated the fitting method.
if you've got any problems realizing this then i am happy to help. yes, it will still work in real time
Thanks ๐ so i just need to create a new roslyn source generator project, write my code generator, export it as a dll, put it into my unity project and thats it ? Actually sounds pretty easy.
like i said, you have to change a few import settings on the dll as well but that's it
but if you don't have the generator written right now, make sure when you do you use API 1.0 of source generators because i am relatively confident that API 2.0 aka incremental generators are not yet supported by unity
but since i haven't fully migrated my generators to the new api, i couldn't yet check
thanks
Could somebody help explain IJobParallelFor to me with a little more depth? I understand IJob, but I don't quite understand the use case of IJobParallelFor or when I would use it.
I've read the documentation but I'm still confused, I guess I need an example use case
Parallel will run in parallel, splitting your work over multiple threads
Would it be good for how I would like to generate a mesh for multiple individual chunks of voxels, using one set of pre-computed voxel edge cases?
IJobParallelFor's primary use case is iterating on single elements of large structures. So if you have to process a huge 3d array with some basic calculations.
It's an abstraction on top of the job interface for working with individual elements rather than making iteration the responsibility of the job
If you want to create multiple chunks at the same time, yes
and ceding control of that iteration helps the parallelization more efficiently pack the work
so if you have an array, you could make an IJob that does a for(i in data){doThing(i)}
but then that would all run in sequence within that job, one after the other
so the alternative is to make an IJobParallelFor(length=data.length)
and then the job definition is just data.doThing(i)
that way the scheduler can split up that work into vectors that can run in parallel
waaaay faster
Thanks you both, you've made it much clearer to me. I appreciate the explanations and examples! I think I know what I need to do now.
Correct. Each SpawnForQuery may spawn different objects too. To give an example: HUD element X needs to spawn for each entity in query Xq and HUD element Y needs to spawn for each entity in query Yq
if i understand your situation correctly, i'd maybe then suggest using a tag component to mark them for WithNone and ignore, or even a bool inside the SpawnForQuery component, OR as you i think suggested an ID if that's more flexible..
Is it possible to use WithNone for a component with a set value? (like the inverse of SetSharedComponentFilter )
i don't think you can filter queries for a specific value inside components like with SetSharedComponentFilter.. You can filter for components that have changed with AddChangedVersionFilter but i'm not sure if that helps.. I think the WithNone suggestion i basically just meant if you added a 'IgnoreMe' tag component to it, then use WithNone: ComponentType(IgnoreMe) inside the EntityQuery's EntityQueryDesc, then once a component has been used, add the IgnoreMe component onto it.. Not sure if that's useful in your case though.
Ok having a pain doing something I thought would be simple.
I have some components that have [GenerateAuthoringComponent] tag and I want to do some custom conversion for them.
How do I access them during conversion?
I'm trying to do a one to many conversion.
Like I'll have one authoring entity with these components and I want to create several entities from that one during the conversion.
I can't (don't want to) change the source of the components that I want to copy, I just wanna grab their data from the source authoring entity during conversion.
Is this possible?
you can't do this with [GenerateAuthoringComponent]. you have to write the authoring component yourself. you need a monobehaviour that also implements IConvertGameObjectToEntity and do the conversion there yourself
Well thats shithouse ๐ฆ
not really. [GenerateAuthoringComponent] does the exact same thing. you just don't have to write code yourself. but it still gets generated behind the scenes as the exact same
I managed to figure out a way that should work.. it involves adding a Processed component to the SpawnForQuery and the target entities. This way I can have 2 jobs that do the folowing:
- Handle processed targets from unprocessed sources (and process the unprocessed sources)
- Handle unprocessed targets from processed sources
I have written the system, but I need to write some surrounding logic.. so not sure it it'll 100% work yet but I'm somewhat confident!
Now for a different question! ๐
I'd like a system to run if there is 1 or many of a particular component. Is this what the RequireSingletonForUpdate functions are for?
i.e. if I add component X to Entities A, B and C. Then use RequireSingletonForUpdate<X>() on a system, is that correct?
How is this different from:
RequireForUpdate(EntityManager.CreateEntityQuery(ComponentType.ReadOnly<X>()));?
RequireSingleton will make sure that there will ONLY be 1 entity with the component on it. otherwise it'll throw an error
you know. like a SINGLETON
and btw, normal systems already run only if there is 1 or more entities that satisfy the query.
What are some proper or clever use-cases for Singleton components?
If I had to take a guess: something like an "active mission/quest" component?
anything normal singletons are used for
Oh i just realized: maybe something like game settings. I remember writing my own SingletonBehaviour for those back in my pre-DOTS days.
fair enough
So far I just make those part of the system class itself.
Not quite sure what a Singleton component could add there
yes. but you might want to access them for some entity transformation too. then it's RequireSingleton
Hmm
wdym?
Well you could just enable/disable the system instead of having whether a singleton component exists as the criteria for whether its enabled or disabled.
But then again, you have a fair point that a Singleton component helps as soon as you need to associate it with other components like Transform.
Maybe if you have like a World singleton with things like Terrain components and what not
RequireSingleton MUST ALWAYS have a singleton accessible if the query has entities associated with it. otherwise it will also error. it doesn't disable the system
e.g. i am using a singleton entity to store my mesh generation settings
oh really. Interesting.
every chunk needs it, but the chunks themselves don't need it associated with them
I couldnt decide whether I only wanted 1 or multiple worlds (planet + moon) so I had to have the mesh generation settings associated with the world entity, of which there can be multiple.
its really a pain in the ass lol
I hope its worth the trouble in the end
you'd have a moonworld singleton and a planetworld singleton since i imagine they'll have different settings
both singletons can still exist on the same entity
Hmm, I suppose there wouldnt be much to gain from having them both in the same chunk since theres only 2 of them...
wdym having them in the same chunk?
you mean entity chunk?
much better than having them in 2 seperate chunks
Well if they both have a non-singleton generic CelestialBody component and their Archetypes match exactly, you can iterate over both of them in the same Entity Chunk
Yeah but would it really help much from a performance standpoint? :p
Oh I get what you mean. Have just 1 entity for both?
that makes no sense. you wouldn't ever add a CelestialBody component to this entity
Hmm? Well its where I store important parameters such as (mean) radius and gravitational pull strength
Worth noting: my worlds are spherical lol
that should be stored on the planet entity though since this is planet specific data
Huh, but planets are celestial bodies?
Moons are too
I just generalize them both to CelestialBody
it's the same. then it should be on CelestialBody entities
...but they are? huh :p
I think somewhere you misunderstood or I explained it poorly.
yeah, but the singletons are not CelestialBodies
also you don't need singletons if you only ever use them for 1 entity
right because they couldnt be right?
Anyway nevermind, thanks for explaining Singleton components though
then just put the data on that entity
Im trying to learn as much about obscure ECS features as I can since I often end up trying to work my way around problems for which solutions already exist.
that's good.
but for singletons maybe it's better for you to look at OOP singletons again since they are almost equal to ECS singletons
Right now my problems are more performance-related.
Specifically: having to do stuff on the main thread due to having to work with SharedComponents
Hmm, perhaps you might know the answer to this:
Can I use SharedComponents in a parallel Job that is not Burst-compiled?
you really really should not. you can't know when a SharedComponent get's accessed by which thread which will likely lead to undefined behaviour / results
Because they might have references to managed objects, I presume?
SharedComponents are reference objects
Oh well I use structs for ISharedComponentData implementations as well. Never considered doing otherwise.
then that's not shared data though
I do however put object references in that struct
Anyway, I primarily use the SharedComponent to group terrain tiles into larger tile clusters.
So I can have a chunk and already know they belong to the same tile cluster
But its getting more expensive the more chunks I have...
So either I redesign it to have less chunks,
or I somehow find a way to iterate through those chunks + SharedComponent faster.
why don't you just have another component on the entities that have a clusterindex? then you can just compare the indexes and you immediately know which chunk belongs to what cluster?
Yes but say I have an expensive calculation I run for every cluster index. I would have to cache those results in a Map somewhere, or use ComponentDataFromEntity for the cluster entity.
Either way, I'll end up with random memory access.
And not always I can do this on a Burst Job, so that makes it many times worse. :/
I'm working with Mesh, MeshColliders, Texture2D and MaterialPropertyBlock here
I know there is a ECS rendering package and a DOTS Physics package
But regarding DOTS physics: there is one important thing I need that I cannot do there yet
well then just have it apply your results in non bursted jobs and get the results only through bursted jobs. that's how i do it and it's super fast and easy
Which I do. But its the exact act of delivering the results of the Burst job to the correct place that is so unexpectedly expensive at times.
wdym? just get the result off the entities again
1000 reads from ManagedComponentAccessor<T> is already like 2 ms or something
don't do managed components
like if I were to put the calculated mesh data into the Mesh-object
I wish I could
you can
Im stuck with MeshCollider because DOTS physics does not support moving colliders around within the same entity
and DOTS colliders and MeshColliders dont interact with oneanother so I cant mix them
that has nothing to do with the mesh itself though, neither texture2d or materialblockproperty
wdym moving colliders around inside the same entity?
Also Im having doubts ECS rendering has support for everything I'll need.
Aircraft landing gear, moveable flaps for example.
Car doors
Sometimes its not desireable to use separate rigidbodies for those
they should be seperate entities
You could, but this gives you a new set of problems to solve
idk exactly what you need to render, but ecs rendering is pretty fleshed out. well at least they are hooked into almost all normal rendering things. unfortunately no true ecs rendering yet
E.g. landing a 18 ton jet on landing gear that are rigidbodies themselves will cause the whole thing to practically explode.
Ive tried all sorts of Joints and joint configurations.
Meanwhile if I just make them part of the same rigidbody there is simply no problem
should they even be a rigidbody in the first place
They need collision and wheel colliders
that's not dots though
Right, so I have to do as much in DOTS as possible, while still working with traditional GameObjects.
so what's the problem?
and I definitely need DOTS: I already had a lot of this stuff done with traditional GameObjects. But the very reason I'm porting it all to DOTS/ECS is because of performance issues.
Like I said at the very start: wanting to find a faster way of iterating though SharedComponent
try to not use sharedcomponent
But then you questioned whether I even should, etc. etc.
nevermind
if you want to stick to sharedcomponent, unfortunately i can't help.
Its just really too bad there isnt a job-compatible SharedComponent variant that is just structs and no object references. Because I can eliminate the object references if I really need to.
And I know there are chunk components but I still need to iterate through SharedComponents to properly update those chunk components :/
It just feels like an issue that must have already been solved at some point, yet I cant find solutions
I could of course spend a lot of effort redesigning everything so this isnt a problem, but it would be a waste if there happened to be a solution after all
it still tastes a bit too OOP for me. so i am pretty sure that it's not the preferred way to tackle this problem using dots
Perhaps, but using DOTS at least partially has already paid off for me. (Mesh generation, height map/normal map generation, LOD calculation + assignments, etc.)
Definitely
I'm wondering, is adding an item to a Buffer technically a structural change..
Just wondering as i have the following situation - i'm currently using an ECB inside a parallel ForEach to write to an external DynamicBuffer that exists on a singleton entity.. Kinda like this:
Entities.ForEach((ref SomeComponent myComponent, in int entityInQueryIndex) =>
{
ecb_p.AppendToBuffer(entityInQueryIndex, myBufferEntity, new BufferElement{ /* some stuff */ };
}).ScheduleParallel();
Which does work, however i need to wait until the structural sync point before obviously the buffer is updated
So i've also tried this approach:
var myBuffer = GetBuffer<BufferElement>(bufferEntity);
Entities.WithDisableParallelForRestriction(myBuffer).ForEach((ref SomeComponent myComponent, in int entityInQueryIndex) =>
{
myBuffer.Add(new BufferElement{ /* some stuff */ });
}).ScheduleParallel();
Which seems to work and the compiler doesn't complain..
So i'm just wondering technically what are the implications of this..
Is writing to the buffer directly inside the job like this ok, or would i be better for example creating a NativeList<BufferElement>.ParallelWriter at the beginning of OnUpdate and using that instead of the buffer
Is someNativeArray.Dispose(jobHandleHere) the same as [DeallocateOnJobCompletion] NativeArray<T> someNativeArray ?
Did you consider checking out the CPU Timeline in the profiler? What you see there might provide a clue as to what happens behind the scenes. (E.g. various additional sync steps appearing)
Yeah i haven't done that in this case as yet, i definitely will though..
It isn't
You set an initial capacity via the attribute on the buffer struct, that determines how large it will be in a chunk. If it grows beyond that it gets moved to the heap
Okay thanks for that, very useful to know
Does my usage in the second example look okay to you? ie adding to the buffer directly inside the ForEach
Why wouldn't you just include the buffer in the query?
Oh it's for an external entity
yeah
You should use a BufferFromEntity, or use GetBuffer inside the ForEach. Retrieving the buffer on the main thread you're potentially blocking jobs
hmm
i think i read that EntityQuery's are internally filled in jobs, i did wonder if that was the same with for example GetBuffer on a system
Not sure what you mean by that, GetBuffer gives you random access. But by using it on the main thread you immediately force any other job referencing that buffer to complete, since you're essentially giving write access to that buffer on the main thread. At least as far as the scheduler is concerned
And adding to it in parallel is almost certainly a bad idea
Ah ok yeah, that makes sense
Yeah i thought that, was surprised it actually worked tbh
So BufferFromEntity does seem a better option
If you have enough entities to cross chunk bounds then you might see some fun stuff doing that
Okay will definitely avoid, i was pretty unsure on that one either way
If you need to write to a container in parallel you should be using a native containers that supports it I think
So if i used buffer from entity, could i write to the buffer inside the ForEach and then for example access that same buffer from another system within the same frame ( ie before any structural changes ) and still get the updated written buffer data
You might need to ensure the second job runs after the first, using system update attributes for example. It's possible the scheduler could arbitrarily decide to run the read job first which would be old data
But yes if they run in the right order you can do that
i do specify the systems order with UpdateAfter etc yeah, i have a few systems running
So essentially i'm trying to eliminate frame-delays with structural changes, which currently rely on ECB's to instantiate and set data etc
So for example i have a projectile system feeding hit data into a nativearray, which then feeds into a ForEach over the characters to apply damage and also trigger ragdoll spawns
It's fairly complex and particularly the ragdoll instantiation and initialization involves some intricate setup ( including transferring the characters animated bone entity positions onto the equivalent ragdoll bones etc )
And basically i'm currently getting a frame or two delay and trying to eliminate that as much as possible
So one other thing i'm a bit unsure about is.. say instead of a buffer i used a nativearray which was a member of system A for example, and written to by system A, and then system B accesses that nativearray and passes it as readonly into its ForEach..
I'd assume that system B would create a copy of that nativearray ( as i would have to create a local variable of it inside OnUpdate before i pass it into the ForEach )
And if so would the overhead of this be more than say just using a buffer with BufferFromEntity in system A, and reading from that buffer using BufferFromEntity in system B
A NativeArray is essentially a pointer to a block of memory. It can be shared at will without any copying. It only gets copied if you explicitly tell it to
So no there's no overhead to worry about in terms of sharing a native container between jobs/systems. But you do have to manually manage your job handles if you do that - unity can't do it for you like they can with components/buffers
ah i figured it may copy the array hence the requirement to assign for example system/class level variables to local variables inside the OnUpdate of a system before passing it into a ForEach
any idea of the cache implications of using a nativearray rather than a buffer
Nope. I assume native array would he faster in most cases as it doesn't require looking up components and it won't be on the heap like a buffer can be. It's just a straightforward contiguous block of memory
Okay, thanks again for the help
Is EntityQuery.GetQueryTypes likely to become public? (currently it is internal) I'd like to combine a EntityQuery with some extra types. (Note: the EntityQuery is within a component so I'm unable to use EntityQueryDesc since it is not blittable)
Edit: I solved this by creating the first and the extended EntityQuerys at the same time (from the same EntityQueryDesc. Though it still would be nice to be able to retrieve that array! ๐
how can i change material params at runtime with HybridRenderV1 and doesn't break instancing? Or its only possible to on HybridRenderV2 ? Now i me doing it like this
I can't clear a native container?
Should I just reinitialize it?
depends which nativecontainer?
Does it work with HybridRender?
No clue to be honest, but perhaps worth checking out.
Generally whenever I need to change material parameters at runtime, I use the MaterialPropertyBlock
Its a bit wasteful to duplicate and/or modify new materials for this
hey, i know nativearrays are necessary for jobs execution with burst, but in regular code, are they more optimized than normal arrays ?
i could not find any documentation on the subject
@broken cradle I dont know everything about this subject but here is what I do know:
At least when running in the Unity editor, I noticed NativeArray is a lot slower, seemingly due to a lot of additional safety checks being performed.
These in particular, when reading/writing elements one-by-one.
They can be disabled but as to when and whether you should disable these, and whether the resulting performance matches or exceeds that of normal array, I do not know.
Shouldnt be to hard to set up a small experiment, though.
Currently, what I do is do a NativeArray.Copy to a temporary normal array (which I create once, then keep reusing) and then iterate through that one. That way I dont have to worry about either safety or performance. Although, of course the code gets slightly more cluttered that way.
ok, i think i'll try both anyway. I don't know if pure memory copying (what i want to do using CopyTo like you) will be faster whether i use burst or not, i'll give it a try
Luckily, memcpy/CopyTo, etc. is super fast, even without burst and/or the main thread. No need for temporary normal array! But if you need to access 100+ or 1000+ NativeArray elements one-by-one, things wont be fast anymore.
well i need to copy 1000 arrays of 256*256 20bytes structs
so yeah that's a lot
and i need speed
my design is not the best but i already almost have realtime (0.1sec), it's still noticable and i'm looking forward to multithread and boost
1000... in 1 update?
sounds like terrain mesh/texture stuff
not everyupdate thanksfully
I was faced with a similar issue once and I merged all those array into just 1 or perhaps a few at most.
Do you ever use the deep CPU profiler?
not yet
i said 1000 because it's pretty much the worst case
but most of the time it will not exceed 100
For me, deep CPU profiler tells me exactly what I should spend my energy on for optimization. Its really good.
I would go as far as to say its necessary
If you dont do the profiler, all you're left with is a lot of guessing
yep i know, but i also know this exact operation is what makes the lag so i know i have to work on it
otherwise i have to work on a better design
Fair enough, but it would give me some context about how and where you're doing this
Example of CPU profiler output, hierarchy mode
Example of CPU profiler output, timeline mode
But I suppose you dont necessarily have to use the CPU profiler for this particular problem
Of course my understanding of what and how exactly you're doing things right now is limited, but from what I know I would suggest to try batching those copy operations somehow.
Like with what I mentioned earlier about putting it all in a single array.
Is this for a terrain system by any chance? What is it for?
i'm still prototyping, it's for a pathfinding algorithm, i compute a flow field, but for everyunit to have it's own will they have to have their own flowfield which they can modify without changing the others flowfield, so i have to deep copy it for each agent. What i can do is multithread and try burst to see if it brings improvment on pure memory copy. To make a further more optimized design i will probably chunck my terrain to copy smaller arrays
eventually i might also create a path handler which gives references or copies to units depending on if they want to perform an action by their own or follow a group
Oh so nothing about this is Bursted or multi-threaded yet?
Also, about copying smaller arrays: generally having fewer array copy operations will yield more performance improvements than operating on smaller arrays. A single memcpy is stupid fast if done right, whether its a lot of data or not.
the pathfinding algorithm is bursted and multithreaded as much as possible alreeady (as you may know A* is not multithreadable but some specific operations in the flowfield algorithm are), the part i'm looking to optimize now is provide the resulting flowfield to my units, which can go from 1 to 1000 units
i already have flattened matrix to 1d array in order to speed up things and help compiler optimize it even more
Ah
How about...
- 1 single large array for all your agent's flowfield data.
- Every agent receives a "range" within this array (starting index + length)
- When dispatching calculations to a job, all you have to do is input this entire array and you're done.
- When job is done, you copy it back to the original array (or not at all, if you simply sent the original array to the job)
I had a similar issue. I had meshes of varying "resolutions" (2x2, 4x4, all the way up to 32x32).
Doing a separate job+copy+whatever per mesh was way to slow. And super wasteful when you sometimes have meshes with just 9 vertices.
So I made a "batched vertex calculation job" system that would cram as many meshes into a 20000-vertex long array as possible, and dispatch a job for it.
If there were still meshes left, I made a new 20000-vertex long array for those, and repeat.
(Why an arbirary cap like 20000? Primarily because my old job was not multi-threaded, so it was only way to make all threads work on those meshes. But also because that way I can cap how long a job will last, regardless of how many meshes need to be processed.)
unfortunately this is a pure copy job, not sure if using gpu, not sure if even multithreading, will speed things up, since in the end it's just about HDD/SSD access and write speed
time to work
Generally this all happens in RAM right?
oh indeed i'm dumb
Hmmm, about 1 MB per agent
For the 256x256x20kB you stated
Shouldnt be an issue...
oops B i meant
that is indeed a lot
there are very few documentation on rts pathfinding in fact, most tutorials are about making a A* and calling it a day
the real difficulty is often in getting the data where you need it eh
(at least in my experience)
Anyway, id still be interested in seeing what the CPU profiler says. Its really up to you whether you want to check that out for me
I'm not exactly an expert in DOTS yet but i know some things and I know helping you will help me learn too
Maybe 1 MB memcopy is a lot after all? I just realized i copy at most 32x32x12B for my meshes.
which is a lot less
Although...
here, the pic is when i repath
Could you enable the deep profiler too for me?
disclaimer: its gonna be slow as shit if you enable it
oh yes indeed it tells purcentage of computation time for each line
good shit right ๐
not a big surprise on the costly lines though
Can I see them?
Wow you gotta put all that stuff in a job lol
You stand to gain a LOT of performance
by job do you mean only job or with burst too ?
i'm affraid it's cannot use burst with anything else than primitive variables
Definitely with burst. Its like a free 25x performance increase. Pure magic
Yes correct, but you can still try to do most of it in the burst job
I presume Rigidbody.MovePosition() happens at the very end for each agent?
yes indeed
You can probably do something like this:
Write a pure burst job that outputs a NativeArray<float3> finalRigidbodyPositions
Then AFTER the job, you just loop through your RIgidbody array and give them the final calculated positions from that array that came out of the job
mmmh, how would i calculate the final rigidbnody positions if i cannot use the ribigdody class in burst ?
By the way maybe you already knew but for Burst, you have to use float3, quaternion instead of Vector3 , Quaternion
yep indeed
Just give the Burst job everything it needs before you run it
If you can screenshot the code for me I can probably provide better help
Although it seems
sure, let me copy paste it and provide some comments
You could just paste it first, maybe its sufficiently understandable on its own
All ill be looking for is the things you cant use in Burst
i little too big for discord so here is pastebin
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.
not too long tho dojn't worry only 50 lines
Ok lets see
you are massively in the wrong here btw. 1. flowfield's are not supposed to work for single entities. that's what A* is for. 2. A* can definitely be fully multithreaded
yep i know flowfield are not supposed to work for single entities, however, there is a game mechanic called auto aggro, which states that if an ennemy unit attack you, you have to attack and pursue it. This means you have to ask the pathfinder to compute a path just for you. However the pathfinder cannot compute a new path if its flowfield is already being used and read by other agents. This means i would have to create a new pathfinder, which is very heavy. The easy way i found was for every agent to have it's own flowfield, and it will be modified by the pathfinder, instead of the pathfinder to hold the flowfield. If multiple agents need the same flowfield, we copy, if an agent wants to do something else, it asks the pathfinder to compute its path
definitly did not know for A* i'll give it a look, but for now i have bigger problems
and yes my design is crappy and i might even trash it completely for something smarter but hey i'm learning
@broken cradle Ok I didnt convert the whole thing but this should be an accurate depiction of what at least a partial conversion could/should look like.
Please take note of how everything non-Burst compatible has been left behind in the Burst job.
Oh by the way, I only show I create the NativeArrays, but I dont show me putting the actual values in those arrays
hey don't put too much effort in it, don't want to take too much of your time
thanks though
you should add [NoAlias] where applicable
Lol i havent looked into what aliasing is yet
Its alright. This is just stuff I wish someone else showed me when I started out
@haughty rampart Do I stand to gain a lot of performance if i take aliasing into account?
when no things are aliasing you will gain massive amounts of performance 95+% of the time. because then the cpu can use vectoring
oh lol so nothing gets vectorized by default without NoAlias?
Or more like, the code is actually vectorized
but it doesnt actually help
few things get vectorized if any without [NoAlias] because then the compiler has to figure out on it's own what can and cannot overlap which is very difficult.
Hmm, I'll look into it. Thanks for the hint
so most likely nothing will be vectorized
@haughty rampart Can I mess things up if I use NoAlias wrong?
e.g. nonsense calculation results
if you put [NoAlias] on aliased things, these aliased things will get vectorized and will lead to nonsense / undefined behaviour
or results for that matter
So in this example, since each element in those arrays belong to the exact same entity/agent, it can all be considered not aliased?
i have not read through the code. usually in most code things are not aliasing. but if for example you pass an array and a subarray of this array to the same method, then they will definitely alias
when you think of a good solution and you realize that NHM.ParallelWriter doesn't support ContainsKey... ๐
๐ฎ who would've guessed?! it's a ParallelWRITER
writing parallel in NHM is an atomic operation so no reason that it doesn't exist
writing has to figure out to which bucket it'll write. AFAIK there will never be 2 buckets with the same key
if (Interlocked.CompareExchange(ref buckets[num2], num, -1) != -1) where num2 is the hashed key
quite the hack to put [NativeDisableParallelForRestriction] on a normal NHM but at least it "works" until I have a way to figure out if a key exists in parallel
Howdy all. I'm starting on my ECS/DOTS journey and I've been skimming a bunch of the materials and forum posts, and I want to make sure I'm correct before starting off.
- Use Unity 2020.3 LTS for ECS/DOTS as there are some compatibility issues with 2021.x.
- The recommended minimal set of packages is
entities,rendering.hybrid, andeditor.
I did not know the big differences between standard unity physics and havok (besides it is built off of unity physics), but if I'm trying this out with a small toy 2D game I'm guessing that unity.physics will be good to go with.
(Also, in the video on Unity Learn about ECS, they say to change the API Compatibility Level from .NET Standard 2.0 to .NET 4.x, but I don't see that anywhere else --- is this still the case?)
changing the api level doesn't matter.
if you want to use ECS (which is the entities package) you currently have to use 2020.3
packages you will definitely need: entities, mathematics, collections, burst, jobs, hybridrenderer
when writing systems make sure to only derive from SystemBase everything else is deprecated
Awesome, alright. It was (is?) surprisingly difficult to figure out what was needed, so thank you!
also make sure to activate hybridrenderer v2 because the default is still v1
A dumb follow-up, not having used 2020.3 for a bit --- I can't get them by their com names from package manager, it's all github, yeah?
just add them manually to the manifest.json
The physics package as well, or is that no longer necessary to import?
you should also be able to add them via name (if it doesn't say via name, you put their name in the add via git field). Name being com.unity.entities for example
if you want physics then you need the package /s. i just named the definitely needed ones
Haha, thanks --- I honestly wasn't sure if it was one of those thing where it was like, "Oh, Unity made it the standard thing so you don't need to import it anymore..." Gotcha, and thank you vertx.
i checked case with MaterialPropertyBlock and problem that MaterialPropertyBlock need access from renderer like this
_renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetColor(colorPropertyName, color);
_renderer.SetPropertyBlock(_propertyBlock);
Buts getting RenderMesh:: ISharedComponentData have no access to method SetPropertyBlock
MaterialPropertyBlock is purely a "built-in renderer" thing. For hybrid renderer material overrides are what you use for per instance data https://docs.unity3d.com/Packages/com.unity.rendering.hybrid@0.11/manual/material-overrides-code.html
am i right that using this i need HybridRenderV2 ?
Yes
problem that we have AR app and we can't enable HybridRenderV2, because it need Vulkan api
or im mistaken ?
I'm not sure. If you're stuck on v1 though you can check here https://docs.unity3d.com/Packages/com.unity.rendering.hybrid@0.11/manual/batch-renderer-group-api.html#setting-per-instance-shader-property-input-data
Afaik the "BatchRendererGroup" api is barely documented anywhere
So I can't offer much help if you're stuck on v1
problem that i tried switch to V2 and on devices with Gles3/Metal and it doesn't render. I found some post on forum that it require Vulkan. And Vulkan can't be set with AR
ty for info about BatchRendererGroup
Yeah Hybrid renderer does not support GLES at the moment. Metal should work though. If it does not then it's a bug
Is it fine to create blob assets in the "IConvertGameObjectToEntity.Convert" methods or do I need to do it in a separate convertionSystem?
whatever works
Does anyone have experience with AsyncGPUReadback.RequestIntoNativeArray()?
An error occurs when I use the native array in a job (after using AsyncGPUReadback.WaitAllRequests())
nvm it was just a bug that was fixed recently https://issuetracker.unity3d.com/issues/asyncgpureadback-dot-requestintonativearray-causes-invalidoperationexception-on-nativearray
How to reproduce: 1. Open the attached project named "Case_129547" 2. Open the TestScene2 in the Scenes folder 3. Enter Play mode 4....
can "Jobs can only create Temp memory" be disabled?
meh, not without custom NativeContainers :/
Interesting. This is actually a clever way of doing the same in a ECS-friendly manner.
I have some 3D UI in world space, and they all are basically lowest alpha with high emission.
I want to create a "fading" effect, where I transition the HDRP/Lit Material keyword _EmissiveIntensity. Yes I have Use Emission Intensity checked and _EmissiveIntensityUnit is set to 1 (EV100)
I am setting the material item like so: material.SetFloat("_EmissiveIntensity")
Debug log confirms that the data changes. But it doesn't reflect the changes in the game view, or scene view.
Is there a step I missed? Like material.Apply() or something of the sort?
This occurs during an ECS side System OnUpdate on main thread.
has there been any DOTS news lately? i stopped using it near the beginning of 2021 because i didn't want to keep using Unity 2020.3 and haven't kept up on it
https://forum.unity.com/threads/is-dots-being-abandoned.1183621/#post-7594702 how "soon" is really soon no one knows for sure lol
hm okay. glad it's not dead at least! thanks
It's been
for over a year now
I just wish they improved their communication on this subject
oddly enough, i just tried out my old DOTS project on 2021.2 and it... just works? i was under the impression that the 2021 release cycle just wouldn't work with DOTS
that was the main thing holding me back from using it but since it works ๐คท may as well
Though it might seem to work, people have reported issues building their dots projects with 2021
good thing i dont need to build any time soon ๐ good to know though
the only thing you cannot use is the entities package
also 'soon' is referring to the end of the year or early 2022
they have aced communication on it
it's not been over a year. not even 3/4 year
Seeing the last release being [0.17.0] - 2020-11-13 That would make it over a year
The forums also have no sticky topics around the future of the ECS, any dates, a roadmap, or anything related. Neither does this Discord. That isn't exactly what I call aced communication
I guess it doesn't count as a "full year" if you consider the date the release notes to be wrong. And instead take the date of the announcement, being january. Or include the small bug fix in May.
you cannot expect anything of that sort for experimental things
Why not?
they have already stated all relevant information. what else do you want? it's incompatible with 2021. it will be made compatible at the end of the year at the earliest. it is an experimental package. they will update the situation whenever any news are available
A struct component cant store a reference to an array... right ?
Is there any way i could store an array inside an struct component ? I know theres stuff like UnsafeArray or others... but i dont wanna use them, i assume they would allocate memory again...
My problem is basically the following one, i receive an deserialized Info[] in an struct from the server.
I need to process this data inside one of my systems... so i want to treat that "command" as an entity itself. So i actually need to put that "Info[]" in an struct to attach it to an entity.
you wouldn't use an array in a struct for that. use a DynamicBuffer
But dynamic buffer does allocate memory right ? I dont wanna allocate it again... i already have it allocated, the `T[]' i receive from the server
i'm afraid that you won't get around reallocating it again. but it really doesn't matter all that much. T[] will get deallocated again so no worries there
i doubt it's big enough to really worry about that
Ah damn that sucks... I once heard that there actually ways to store references to objects in those components... Certain structs or whaterver... is there really no other way ?
is it even a nativearray or is it a plain c# array?
Just a plain c# array... Cant network native arrays because they are unity internal and my server is plain c#
if it's about ecs you can use a managed component
or you have to go where you process the packet from the server and put it into a native array
then it's probably not good to store a reference to them anyway. can't burst them
I dont even wanna burst them ^^
why
Because i dont need to... But i wanna treat them as entities however. But no need to question my decisions here
highly doubt your server sends a managed array? surely you serialize into packets?
very strange decisions here too. but hey, you do you
I send that array in an struct and deserialize it to a T[] inside that struct..
However, when i pass that array to a mative array, what happens ? Does the native array really allocate new memory ?
I basically mean the constructor... Saw that it takes an T[]
you're sending bytes right
so if you send an array you're sending a line of bytes describing [0, 1, 5] etc
it doesn't matter if your server is in java and sending it through a relay in unreal engine 5 to your game in unity
you can deserialize that line of bytes into whatever you want
I hope so - but we do not know for sure - also internally they are i think on 0.20.0 version or even higher but why they do not publish it is million $ question
yes, if you create a nativearray from a managed array it reallocates unfortunately
which will always be the case when going from managed -> unmanaged, no way around it
that's why you'd ideally catch it before it turns into a managed array
It sends bytes unter the hood. But the api itself just deserializes it back into its original form. Im using a high level api for the networking part, i simply dont have that much control.
ahh i see
they don't publish it because it's not ready and it's not compatible with any official unity version
yea in that case not sure what else you could do
if you don't care about burst then maybe use a managed component, i think all you'd have to do is replace struct with class
actually u can use 0.17 on 2021 and even 2022 unity version with some minor problems and on forum there is thread dedicated to that
yeah that'd be possible. but highly anti-dots
in an early 2021 version yes. not in the current ones
didnt know that since didnt test it and found no posts on the subject on forum - but anyways good to know
Are systems inside the "Initialization" group less called than systems inside the "Simulation" group ?
My problem summarised :
- beginInitEcb.Set<...>(...); // I buffer a component set operation
- I buffer a custom command in a custom simulation group system ( Basically made my own buffer system for some ingame operations )
- Somehow my custom command is being playbacked before the Begin-Init system was playbacked... which results in wrong behaviour
What am i missing ? Is this normal ?
Okay this is very weird... it really looks like the invocation of the init group and the simulation group are different.
I thought both are getting invoced each frame, but it looks like the init group does not run that often. Why is this ?
Also, don't worry about memory. Using this command https://docs.unity3d.com/ScriptReference/Unity.Collections.NativeArray_1-ctor.html to create the NativeArray from your Array is insanely fast, and since it's something that's come across a network the size isn't going to be a bother to anything newer than an iPhone 5
Has anyone written a truly fast target (to position) system? this is the best I could come up with with an unrolled loop: https://pastebin.com/kDKXm3ee
what sucks about it is the CDFE.DidChange
but it gives a slight speed up
I still think this could be much more efficient if you can find out which chunks of the targets have changed. but as those will be foreign chunks it's not really straight-forward to determine this. and of course, any way to vectorize this would be nice but I couldn't get it working even without the DidChange method call because the CDFE lookup is in the way
are there samples on how to use this method?
look at the code, it's just a wrapper:
i don't know what's your use case, doesn't seem likely you'd really need it
the method is used under the hood for chunk.GetNativeArray
oooh, just curious.
huh... so far ecs works in 2021.2.4f1
I forgot which version but the last time I tried it on some 2021 version it spits out errors without me touching anything
cool, can you test out an il2cpp build?
I'll build an empty scene with one invisible entity
weeeeeeelp
aaand it crashed
nice unity
Yo, this sounds dumb. I want to do an array of integers in IcomponentData and don't know how
I was trying something like: public unsafe fixed float pointx[constantine.maxWayPointArray];
But it seemed like it was shared among all of the Entities with that Component
Its not good when you google and find your own questions you couldn't figure out what they were saying : https://www.reddit.com/r/Unity3D/comments/psb8oj/how_do_you_do_arrays_right_in_icomponentdata/
Trying this: https://unitycodemonkey.com/video.php?v=XC84bc95heI
@remote crater Not sure if this is optimal but when im faced with a similar issue, I often employ a Dictionary<Entity, int[]> or NativeHashMap<Entity, NativeArray<int>> or similar for this (stored in either a System field or some static field elsewhere).
Although if you know for certain the amount of elements will not exceed a particular number (that is also somewhat low, say 10), DynamicBuffer is apparently a suitable solution. I dont have any experience with DynamicBuffer, though.
Also, I avoid putting any collections or references to collections in my IComponentData, even though I'm don't 100% know all the exact technical reasoning behind this. But "knowing I shouldnt" is enough for me, and so far things are working out.
This might be relevant: https://coffeebraingames.wordpress.com/2020/12/20/the-different-lists-allowed-in-icomponentdata/
You can't have a list that grows dynamically inside an IComponentData. This is understandable because the data is stored in chunks. The size of each row of data must be fixed. However, you can have "fixed" lists. They act like lists but they have a fixed size.
marnel, yes that is also the Code Monkey youtube way IBufferElementData
I suppose this is the way to do it
Thanks everyone. Sometimes it takes validation of confirmation. I'll get to this when I have energy, shouldn't be that tough.
Yes it's very old news
Quick word of warning: its evaluations of curves is slower than any and all other means of evaluating curves within Unity.
Whenever you have a normal array, and want to use it as a NativeArray, just pass it in here, and you get a NativeArray back - which is really a struct pointing at your normal array and prepared for thread locking. Just remember not to modify it or rely on its contents in normal C#/Unity space if/when running Jobs or other NativeArray works upon it.
And when you need examples of these things... sadly Unity is of no help. Best place to try is github to see if there's public demos by others who've been exploring it, and the wondrous works of JacksonDunstan, where this little gem of advice sit: https://www.jacksondunstan.com/articles/5274#comment-722534
JacksonDunstan.com covers game programming
And from google to the forum, here's someone answering his own question by referring to someone else answering his own question, which should give you some idea how widely used DOTS is (not) used: https://forum.unity.com/threads/how-to-use-nativearrayunsafeutility-convertexistingdatatonativearray-tvalue.1049015/
Anything I should be aware of prior to upgrading to Unity 2021.2?
So far I've only seen issues with IL2CPP but I'm going to start looking at it myself as well
Like the thing that I think will most likely fail is the hybrid renderer but I don't use it myself sooo ๐คทโโ๏ธ
(from Unity 2020.1.9)
Regarding the IL2CPP: nothing show-stopping? As in, it will still compile and run properly?
More like completely falling apart #archived-dots message
Oh dear
But Mono/JIT still works?
or is that a nonsense question
(I usually dont have to think about either when doing my daily things)
I dont care about shipping any time soon, just stable development on my PC
I guess so but haven't tried it out
Like that issue is definitely an IL2CPP one
I don't really care about mono myself..
What does Mono/ILCPP even mean? Does this only apply when making builds that are supposed to run on machine X or Y?
meaning in the context of developing and shipping stuff
(I know what the words themselves mean)
The unity docs on the subject dont exactly make me go "aha"
@sinful cipher unity will ignore your bug reports regarding entities if you have any as 2020 lts is technically the only supported version
Hmmm
Guess I'll stick to 2020 for now.
I need 2021 for shader graph + deferred URP pipeline. But that can wait I suppose
I just need the new decals, I tried porting them to URP v10 but no luck
Me too, light baking is quite wonky with entities so looking forward to deferred(heh)
I find it easier to work with LocalToWorld and LocalToParent setting the float4x4 manually. However I'm running into the issue that the TRS and Physics rely heavily on Translation and Rotation. So I forcefully remove those components when entity spawns. This then causes my ray casts to "miss" because I suspect that the Physics updates the collider position based on the TRS helper components...or something.
I tried to do another work around. I have a component that always sits on said entities, and I just slapped a WriteGroup(typeof(LocalToWorld)) on it and it worked! I was able to get them to move around by writing to LTW directly. However, Physics ray casts stopped working. Ugh.
Is there a way I can achieve working directly with LTW without ECS breaking down like a house of cards? lol
Hello! Is there a typical reason why EntityQueryDesc would throw the following?
NullReferenceException: Object reference not set to an instance of an object.
I have seen it occasionally in editor, but it happens every time on a standalone build
The callstack goes as follows:
at Unity.Entities.TypeManager.ManagedException (System.Type type) [0x00009] in C:\Projects\Personal\rikeunity\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Types\TypeManager.cs:625
at Unity.Entities.TypeManager.ManagedException[T] () [0x0000b] in C:\Projects\Personal\rikeunity\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Types\TypeManager.cs:613
at Unity.Entities.TypeManager.GetTypeIndex[T] () [0x00019] in C:\Projects\Personal\rikeunity\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Types\TypeManager.cs:641
at Unity.Entities.ComponentType.ReadWrite[T] () [0x00001] in C:\Projects\Personal\rikeunity\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Types\ComponentType.cs:34
at Unity.Entities.ComponentType.ReadOnly[T] () [0x00001] in C:\Projects\Personal\rikeunity\Library\PackageCache\com.unity.entities@0.17.0-preview.42\Unity.Entities\Types\ComponentType.cs:71
at ServerBrowserView..ctor () [0x00026] in C:\...\ServerBrowserView.cs:35
and ServerBrowserView line 35 looks like this:
private readonly EntityQueryDesc m_responseQueryDesc = new EntityQueryDesc
{
All = new[]
{
ComponentType.ReadOnly<DiscoveryResponse>()
},
None = new[]
{
ComponentType.ReadOnly<PendingDestroy>()
}
};
Is 10+ mins a long compilation time for Burst? It's almost new project with under 10 systems and jobs
is there any log for burst compilation?
restart editor? sounds like it froze
maybe you made something that the compiler cant handle, in a smallish project, ive got a ton of burst compiled things and it usually takes less than a minute, doubt its even 30 seconds
remove the burst tag from the latest things youve been working on and see how it compiles
if one thing causes it to hang, might be a nice repro bug report for them
alternatively maybe a library delete is required ๐ฆ
Not sure if I can help you with this but the problem sounded intriguing to me. Are you using DOTS physics or standard physics?
Working Directly with LTW & LTP
Burst compilation should take a few seconds at most. Even if you turned on synchronous compilation.
Barely any time for that unfortunately. University finals season. Pain and suffering
Papers to read, reports to write, projects to present. My days are booked full. Then again, I code best when I know I have deadlines coming up...
Still, I've been looking into figuring out how to use this: https://docs.unity3d.com/ScriptReference/Unity.IO.LowLevel.Unsafe.AsyncReadManager.Read.html
barely understand any of it ๐ good luck on your exams!
I've got a project with a loading sequence requiring reading about ~6000 individual json text files and Unity seems to have a built in parallel file reader. File-reading was benchmarked to tank only 2 or 3 seconds out of a total of 30 second loading (2.5M entities) so it's barely anything but every little bit counts.
what are you using now to read the files?
I'm now looking inside Hybrid Render System and i can't find where is very Draw call happening?
A bit late but I'm just reading them in sequence using a for loop and Files.ReadLines() in an IJob.
Anyone know if you can use ProfilerRecorder to grab worker thread timing?
https://docs.unity3d.com/2020.2/Documentation/ScriptReference/Unity.Profiling.ProfilerRecorder.html
https://docs.unity3d.com/2020.2/Documentation/ScriptReference/Unity.Profiling.LowLevel.Unsafe.ProfilerRecorderHandle.GetAvailable.html nvm looks like it's possible if you find the jobs you want to capture
created new project and tried installing entities 0.17.0
have anyone seen this error before :
Library\PackageCache\com.unity.jobs@0.8.0-preview.23\Unity.Jobs\IJobParallelForDefer.cs(77,85): error CS8377: The type 'U' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'NativeList<T>'
Is ECS still lockets to 2020 LTS ?
Its recommended to use 2020 but it works - with some issues though - on 2021 and even 2022 : https://forum.unity.com/threads/dots-and-2021-2-known-issues.1183456/
Hello, is there a way to convert just the root of a GameObject Hierarchy to an Entity? As opposed to the entire Hierarchy of children, grandchildren, etc.
Make sure your collections package dependency is on the version specified by entities. You can't use the latest collections package
@unborn totem theres a StopConvertToEntity component that afaik should do that but Ive never actually used it
what's those for ?
what does synchronous compilation would it reduce compilation times ?
(late reply but) in editor by default burst compiles in the background and the code just runs in mono until its finished compiling then swaps to using burst
synchronous compilation means burst must finish compiling the job before it can be called, stalling unity until its finished compiling and can continue
in general you're better off marking it on a per job basis, and there are very legitimate reasons for this
i have a job that takes no joke, 3 minutes to execute under mono but only 1 second under burst
so i never want to run this without burst so i have it tagged as synchronously compiling via the burst attribute
A 1 fps game?
What is the proper way to condense this down to an array-like structure? (To be able to read/write elements by index.)
And I'd like to avoid pointers/NativeArray inside this struct since I want many of these structs in an array and all of it to be 1 continuous piece of data in memory. Also, note that this is not meant to be attached to an Entity, so DynamicBuffer wont be an option.
Hmm, something that comes to mind is using a pointer to the first field and then offsetting it by (index * sizeof(half))... But perhaps there is a better way?
I guess I'll go with this for now. Seems reasonably sensible
Nevermind someone told me about fixed array or something
crazy this syntax even compiles
damn..
Can I get Random to work in my .ForEach? seems to produce always same numbers
how are you using it?
In case you are only seeding it once and then throwing it away make sure to use rather big numbers as the seed
I had the same problem ages ago
use float4x4
sorry, double4x4!
You'll likely need more than one, but less than 4 of them to do it. Then you'll get an array-like access and value type behaviour of your structs.
@visual tundra thats quite a creative workaround
I still got my thing to work though. Seems to work fine with "Pack=1" argument removed from StructLayout attribute
can I store a material in the blob asset?
no, blobs can only store blittable data/primitives
so shared component is the only way to have such data?
seems a bit outdated. but i guess you can get the general gist of how to work with random
Does anyone know if there is a built in way to do runtime conversion of GameObjects to entities or is this a strictly manual process?
that's possible
I was under the impression that conversion only occurred when a scene was first loaded, is that not the case?
Doesn't seem like I understood it correctly..
wonder why it says this in the docs then "The conversion process is a succession of component systems that update only once each."
https://docs.unity3d.com/Packages/com.unity.entities@0.17/manual/component_data.html?q=managed component there is also managed IComponentData if that fits your needs
bit of a silly little question - if i do say for example a raycast and debug.log the entities it hits, it'll print the entity ID's ( for example 324:1 or whatever ) - however, in the Entities inspector if i search for this ID it doesn't come up - assuming the entity has an actual name as well as an ID, but searching only looks for the name..
is there any way around this?
You can see here i'm searching for entity 15:1, but it's just coming up with a bunch of 'named' entities
My hit log is just giving me the ID:
Obviously this isn't specific to raycast hits, i've encountered this a few times, wondering if there's a way to search for the ID regardless of the entity name
Not sure about that... but you might be able to do the reverse, i.e. print out the name
Just to clarify a bit - you can see here entity 15:1 has the name TerrainECS:
Yeah i'm using ECB which doesn't have GetName, frustrating
I've always struggled with the entity search, feels like it never works
i could convert the job to not-parallel and use EntityManager, bit of a pain though just for debugging
I think no dice on that one sadly cow https://forum.unity.com/threads/dots-editor-0-12-0-preview-release-the-new-way-to-inspect-entities.1045306/page-2
Someone asked about it on page 1 but never got a response
Ahh that's annoying, seems so obvious.. thanks for checking..
I also seem to always forget the way to search for entities with specific components, i thought it was t:componentname but that doesn't seem to work
there definitely is a way though
I think actually there is no way even for that, it sometimes just works by coincidence or some obscure string match
I can't seem to find NativeHashMap in Unity 2021.2.3f1???
I've included Unity.Collections and I am so confused as to why NativeHashMap isn't a thing
Add the com.unity.collections package
Thank you much, I wonder why it's just not included with jobs or easily visible
I added it, but NativeHashMap is still missing...?
It seems it's a visual studio intellisense issue. Alright, thanks, I'm going to figure this out
When installing packages i usually go to project settings / packages and then check 2 check boxes i think add dependencies is one and other is view or use preview packages or something like that and then when u download entities at the same time all other dependent packages are downloaded as well except hybrid renderer which you add separately
Dependencies are always downloaded. Even with 'show dependencies' off
Can I safely reinterpret float4x4 as Matrix4x4?
yes
Alright, thanks
Iโm trying to find the best way to reused dots code for a large code base. Do we set up packages or ddls or anything else that works ?
Can we even do ddls w dots ?
ive packaged a decent amount of stuff for my project
I used to have separate C# projects that sent the .dll files to my unity project upon build completion.
This was a nightmare. If you would like to know what sorts of things went wrong or became a pain then you can ask me about it.
I switched to Unity's assembly definitions and it has been a much, much more pleasant experience since.
The only thing I havent solved yet is if there are 2 different Unity projects are being worked on simultaneously that share a common code base.
But since I only work in 1 Unity project this has not been a problem for me yet.
If you wish to reuse code between Unity projects, you should probably look into what the package manager and related things can offer for you in this regard.
There might already be standard Unity-way of hosting/deploying packages and such.
So that exactly the issues Iโm facing different project sharing code base
Maybe local packages is the way forward here idk
I just took a look at what local packages are and they seem to be a good fit for this. The only thing I'm wondering about is the ease with which applied code changes (in the to-be-packaged code base) are propagated to your Unity projects... Wouldn't be very pleasant if you had to re-import your own packages every time you changed them.
@light mason
Perhaps its best to just try them out and see what you get
https://docs.unity3d.com/Manual/upm-api.html There is also specific scripting API for packages. Perhaps you can set up some automated way in which the Unity projects are given the updated packages upon code changes.
Ty this is helpful
As long as they are in the Packages folder they compile just fine when doing changes to them
No idea if it also works with packages outside of it but I would expect it to
How do u rotate in job?
Seems like a noobish question..
I'm trying to do this in unity API:
Vector3 pos = Quaternion.Euler(someVector3Euler) * pointInSpace;
But i can't do
float3 pos = quat * somePos;
DOTS is all about SIMD instructions. there are no operator overloads. you must use math.mul(quat, somepos) like in a shader
Huh. How about float3 * float3 then. Or is that okay because that fits into a SIMD vector thingy?
Hmm actually quaternions is also just 4x float
you're multiplying SAME values here
oh right
structurally
although
operator overload is just syntax stuff :/
not sure why a compiler would care much about that at all
Maybe its more for possible ambiguity when multiplying matrices in a row
like mat1 * mat2 * mat3
Order of multiplication can be deceiving here
meh / kinda true. shaders are designed in a data oriented way. and simd is the thing for data oriented. so since dots is data oriented too, that's the reason
and with matrices this is actually important
Maybe they saw an opportunity with DOTS to right their earlier wrongs
and remove the operator overloads
also operators are overloads. == more cpu cycles
idk it probably compiles to just another method
like SomeProperty { get; set; } becomes get_SomeProperty() and set_SomeProperty()
true for IL but not for machine code
anything that's inherited and overloaded / overridden, etc... is a non zero cost
Come to think of it..
I remember a Unity blog post/talk that mentioning something about like writing literal shaders in c#
I wonder where that went
or if i even remember correctly at all lol
Cant find it atm but it was (as far as i remember) worded as the partial reason for the mul()-style
you're probably thinking about compute shaders
no this was a DOTS talk
An early one. 2018-ish
Compute shaders are still hlsl or whatever
i doubt that 'true' 'c# shaders' will be something we'll see anytime soon though. although i really would enjoy that
I hope searching for words in a video will become a thing one day lol
Yea or maybe you write c# and it just compiles to shader code or something
but of course a very small subset of C#
even less than we get to use for Burst
nah, probably about the same
are ref structs supported as IComponentData anyway?
although... writing to arbitrary collections... this im not sure about
pointers to stuff in RAM... etc.
GPU is not just another CPU...
I think the closest would be how stride's shading language does that
Its a superset of hlsl that's closer to c#
shader languages are just so terrible because they don't have syntax highlighting or intellisense or ....etc
pay for Rider lol. Totally worth it
15 bucks a month
Well "worth it" is relative of course
but for me it definitely is
not even. i'd get it for free from my company and i don't even use it.
if the software would be nice then yes. unfortunately it's not
I still miss Visual Studio Enterprise from my (now expired) student licence
code dependency graph generation was the shit
(other than that, Rider is still better)
meh. 2022 beats rider by miles imo
the only thing 'better' with rider is resharper. which isn't too useful if you write good code in the first place
One thing that drove me crazy about VS was that it could not automatically update a class' namespace to reflect the directory it was moved to.
Can VS 2022 do this?
no idea. never had namespaces named after directories. ESPECIALLY not in unity projects
uhh ok
Aah I see. Kind of like what TypeScript is
(javascript superset that looks more like c#)
typescript still looks more like javascript than c#
maybe typescript was supposed to mimic some other language that c#, i forgot
(i dont use it)
I have prefabs that are DeclareReferencedPrefab converted into Entities on ECS side. Some of those prefabs have authoring components attached to them that, well, slap some IComponentDatas on them. This causes a little problem for me apparently.
The actual Entity that is Prefab tagged and holds the Linked Entity Group to the components that were converted via DeclareReferencePrefab will actually contain that authored component added via IConvertGameObjectToEntity, BUT, when I EntityManager.Instantiate(referencedPrefabEntity) it will only contain the default components from Linked Entity Group and does NOT include ones that were added via authoring components.
How can I "inject" all authored components into the "prefab blueprint" if you will?
Ah, I was calling some static code in another "Convert" method that was doing EntityManager.Instantiate before the prefab went to the "end conversion" stage, which is where the actual snapshot will occur for it to copy itself to others.
I added a Task.Yield to that part in code, and now it all works great ๐
F DOTS viewer on 2022.1 Alpha. UI Element rename causes the DOTS viewer to throw errors.
You misread what the size designator is. It's total struct size, not component.
[StructLayout(LayoutKind.Sequential, Size = 16)]
public unsafe struct Shares : IComponentData
{
[HideInInspector] private fixed byte elements[16];
public ref byte this[int index] => ref elements[index];
}```
That works and burst compiles properly
Im pretty sure this doesn't even need the sequential struct layout now that I think about it
What are you referring to? The "Pack = 1" bit?
Yep
wait, pack
I misread that as size. Well, if the components of the struct are all of the same type, you dont need to worry about packing as the default... should... go to the smallest value. I think
But you're reinterpreting ushort as half. That should be fine. Just change the pack to 2 and it should work.
Thing is, "Pack" is apparently not supported for burst
or at least "Pack = 1"
anyway I removed the Pack argument and all was fine
size was what i hoped it to be
(2 bytes per number)
Also on 2022.1 a16, they seem to have fixed the issue with the non-refreshing 1.7 Burst inspector, which is really nice.
Hi, just starting out with ECS. I am trying to get the world position of a child entity. I saw the LocalToWorld component but I'm not sure I understand how it all works. Someone able to explain how to get this position?
I also found that in order to get data from an entity, there is a lot of syntax.
ComponentDataFromEntity<Translation> allTranslations = GetComponentDataFromEntity<Translation>(true);
if (!allTranslations.HasComponent(turretData.firePoint))
return;
Translation firePoint = allTranslations[turretData.firePoint];
That's 4 lines of code to get the Translation for my Entity. Is there a better way? Is it okay to get rid of the safety check?
Anyway, as you can see I'm trying to get the position of my firePoint, which is a child object, to spawn my projectile at that point.
Looks like you're getting the data manually. Which is bad. Have you tried out the Entities.ForEach lambdas?
Well, ForEach is great to get my TurretEntity, so I can know if the enemy is in range and wether the cooldown is ready to shoot again. But when I finally want to shoot, I need the bullet to spawn at the Turret's FirePoint. And I'm not sure how I'd be able to get this specific firepoint for this specific turret using Entities.ForEach
Is there a way to do that?
Give me a sec, im debugging some burst shit right now.
Now the FirePoint is known by the TurretDataComponent, so I get the Entity FirePoint from the TurretData
Alright, so what's going on here. You want a bullet to spawn at entity "turret" and move towards entity "target"?
Almost, I want the bullet to spawn at entity "firePoint" which is a child of "turret"
Oh no no no. Children bad. Children means inheritance which means object oriented programming. This is DOTS, aka Data Oriented programming style.
Alright, so what would be the better way to do this?
Is there a reason why you can not combine "firePoint" and "turret"?
As in, at the same position? No, but perhaps that with some rotations and stuff I might be able to calculate where the "firePoint" should be
Without it actually being an enity
No, combine the entities "firePoint" and "turret". Just move all the components associated with "firePoint" onto the "turret" entity.
That way you can remove the random access to obtain the translation.
Well firepoint is just a Transform really that get's converted to an entity in the SubScene. So all that matters is the position
Turret contains all the data
What is "firePoint"? What is it's relation to "turret". What is it doing / what information does it contain.
it is the point at which the bullet should instantiate, fire.
Imagine a player, player has gun, bullet should spawn at gun position, not at player head
Right. So it's a specific offset from the centerpoint of a "turret" sprite indicating where the bullet entity should orginate?
Yes! ๐
Alright. Yes. You do not need a separate entity for that.
You can just make "firePoint" a IComponentData (component) containing the required info located on the "turret" entity.
Alright, I stand by my opinion that Unity game object conversion workflow was a complete mistake and confuses newbies far more than it actually helps.
Yes, that's what my code is so far. But instead of it being a float3 value, it's an Entity with a Translation. 3D space rotations and calculations are complicated, but this way it's automatically in the right place no matter how the Turret rotates
Perhaps would you know how the LocalToWorld Component works?
firePoint can just be a float3 but you will need to calculate the offset in respect to the "turret" entity's 3D rotations manually. This will be a lot better for performance.
I believe that is the matrix multiplication required for children to convert their "local" translation float 3 into global position float3.
It is a identity matrix for top level parent entities (no inheritance) and it is calculated individually for every child. Which massacres performance.
As for your second question "safety checks". That is not necessary. All "firePoints" will have a translation if you're converting from a GO so that check is redundant.
Also just use Translation firePoint = GetComponentData<Translation>(turretData.firePoint). No need for manually storing GetComponentDataFromEntity. That's for more advanced DOTS methods.
Oh! That's very useful to know. Thank you for all the help, really appreciate it
I just noticed that all entities in subscenes get this LocalToWorld matrix, but indeed the children get an extra one called LocalToParent. So that doubles the calculations.
I'm building on IL2CPP for 2022.1 A16 right now and it works perfectly fine. Low stripping though because medium removes a HDRP light shader for some reason.
Spent all day getting it to finally build along with some custom Burst code. Finally works. The performance though is something I need to work on. 6.5 ms for adding a single v256 onto another v256 on the same entity for 2.5M entities is bad.
public unsafe void Execute(ArchetypeChunk batchInChunk, int batchIndex)
{
// Single -> Mean: 11.667ms. SD: 0.246ms.
// Multi -> Mean: 6.601ms. SD: 0.124ms.
// Build IL2CPP Multi -> Mean: 6.222ms. SD: 0.197ms.
// Not good, not good at all.
var deltaPtr = (v256*) batchInChunk.GetNativeArray(Deltas).GetUnsafeReadOnlyPtr();
var inventoryPtr = (v256*) batchInChunk.GetNativeArray(Inventories).GetUnsafePtr();
// Length is determined by size of structs (which is 8). Thus one v256 per entity.
ManualVectorizedAddition(deltaPtr, inventoryPtr, batchInChunk.Count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static unsafe void ManualVectorizedAddition(v256* deltas, v256* inventories,
[AssumeRange(1, int.MaxValue)] int length)
{
if (!X86.Avx2.IsAvx2Supported)
return;
for (var i = 0; i < length; i++)
inventories[i] = X86.Avx2.mm256_add_epi32(deltas[i], inventories[i]);
}```
public unsafe struct Deltas : IComponentData
{
public const int Length = 8;
private fixed int _elements[Length];
[CreateProperty]
private int[] Elements => new []{_elements[0], _elements[1], _elements[2], _elements[3], _elements[4],
_elements[5], _elements[6], _elements[7]};
public ref int this[int index] => ref _elements[index];
}```
Inventories is of course identical to Deltas
If anyone has any suggestions on how to improve this very simple addition, I'm open to testing them out. Because 6.5ms is nearly half the allotted time budget to maintaining a 60 FPS.
And this code is basically doing this:
[MethodImpl(MethodImplOptions.NoInlining)]
private void AutomaticVectorizedAddition(NativeArray<Deltas> deltaArray, NativeArray<Inventories> inventories)
{
// This is BAD. Unmeasurable amount of bad. Dropped FPS to 3.
for (var i = 0; i < deltaArray.Length; i++)
for (var j = 0; j < Deltas.Length; j++)
inventories[i][j] = deltaArray[i][j];
}```
How do you do RayCasting and SphereCasting with pure ECS? All the examples I can find seem to use MonoBehaviours to call Unity.Physics.
There is some explanation here https://docs.unity3d.com/Packages/com.unity.physics@0.6/manual/collision_queries.html
But it doesn't show how to call these functions (for example the first example under the subject Ray casts) from a ForEach lampda function. Which seems to not allow the use of the CollisionWorld as it is a reference type and thus gives an error in the inspector.
What I'm eventually trying to do is to have a Turret detect if enemies are within a certain radius, and if so, assign one of the enemies as its target.
Just in case it's useful - my friend made a game that may provide a reference point - sounds like there are similarities. Code here: https://github.com/ElliotB256/ECSCombat
Also fwiw... I don't agree with some of the categorical statements that have been posted here of late.
Just a note that although this is the official unity dots channel - there largely aren't official answers or 'official opinions' here.
More, opinionated opinions ๐ .
You need to save CollisionWorld in a local variable outside the ForEach which you then use inside the ForEach function. Also use something like .WithReadOnly(collisionWorld) or it will complain when raycasting in multiple jobs.
:D yep. And the drama in the forums is delicious.
That one guy is hoping dots is cancelled just so he can prove a point ๐ค
I'd just like to read some patch notes. It's annoying, not knowing what kind of problems Unity is solving.
If they manage to get adding/removing into a fast enough state I have to rewrite a lot
but I'm pretty sure that's not happening
other than that, Entities is in a pretty complete state for me.
I modified so much of Entities, Netcode, Physics and Transport that I don't think I'll ever update them again for my current project
But seeing some progress from the DOTS teams would be nice nonetheless
As I said on the forums, all Entities really need now is dynamically sized chunks. I might spend some time digging through the source to make that happen but that will require days of work. If not weeks
Imo the repercussions of ISystemBase are huge - they're essential for performance but an absolute pain to work with. I'm quite concerned how that's going to pan-out.
@viral sonnet same, I really need animation and they were on the cusp of visual editor, events and statemachines. I just dont fancy scripting a statemachine with dataflowgraph
I wouldnt say so. Bursting the initialization code for jobs on the main thread barely improves performance, if at all.
If all you have is heavy jobs, that's true. Once you are using many systems with low numbers of entities it makes a huge difference.
I get my fix reading the Burst changelogs. DOTS is built upon Burst so anything Burst does, DOTS follows.
that really doesnt give you a sense for dots as a whole though
I pretty much only use Entities so it tracks fairly well with base Burst. Hybrid renderer (Unitys big mistake) and all the other packages are locked in purgatory though
I agree completely with that guy on the forums, Hybrid Renderer is the cause of this half a year long and counting mess.
Exactly, when running four prediction loops I save around 0.1-0.15ms main thread time on each system just by using ISystemBase
well it suits you, but theres still a huge amount in entities that burst changes doesnt really affect
What do you mean? Data acquisition from the entity collection produces native arrays. From there, data processing is governed entirely by Burst which is improving every update.
Plus the slow scheduling & dependency chain handling - will be nice when those optimisations drop ๐ค .
My sense of scale in optimization must be really off. I see 0.1ms improvement and that's within 1/2 SD of my usual execution times.
It sounds like you have a very specific situation / problem that you're solving. I imagine burst is fantastic for it from what I've seen of your comments. It's very different if you're making a game or something more complex (complex in the sense of interacting with many types of inputs & assets).
whatever changes in burst will have zero bearing on say gameobject conversion -> entities, how transforms are handled, even basic api stuff in systems. you are so deep into optimization that of course these things dont seem to matter to you but there are tons of other things that burst changes just wont be a factor for
True but I would argue that those mechanics are instead part of Hybrid Renderer. Entities is the base data management system whereas HR is Unitys attempt to connect everything to the engine. And HR in its current state does not work well.
Yea. I'm looking at my timings and I dont think I'm building a game at this point. I cant even manage to add one struct to another rapidly.
well those mechanics if you mean gameobject/transform handling & conversion are primarily a part of the entities package
Is it? I only included entities in my package list and sub scenes are not included.
There is that old method of script based conversion but I thought that was deprecated in 0.15 last year.
Then again, I have not touched GO, graphics, or anything on my hierarchy tree in over 6 months.
And theres livelink. Ewww, disgusting.
im not entirely enamoured with HR but in my use its not holding me back
Not using HR allows me to follow the latest HDRP releases. And I need that for built in virtual texturing and some other graphics magic I threw together half asleep.
I really hope Unity is building upon the job based structs. The lambda I dont believe are vectorized beyond the most simplified loops.
IMO lambda is a failed endeavour
100%. But getting people to understand the stuct based jobs is an absolute pain.
It's a bit weird right? Wasn't the reasoning behind combining the JobComponentSystem and ComponentSystemBase that it created too much complexity to have both of them in place?
After trying bevy out I started to really like the function=system approach ๐คทโโ๏ธ
teaches the wrong stuff, barely improves anything and is limited beyond belief. not worth the dev time IMO
I think code generation is the answer. write a lambda, translate into a struct job and systembase
That's what they started working on with source generators or do you mean something else?
should have kept IJobForEach
i'm not up-to-date on the latest stuff about source generators. the currently generated source is terrible. i mean, people cry about IJobChunk, etc... is too verbose so they use lambda. it would be a good way to get the source generated so you don't have write so much. (not that I care, it's just the general feedback I read)
after some experience, I write IJobChunk just as quick as any lambda
I dont believe they've started work on it. If you look at the training github using the latest 0.23 entities, the lambda they're using isnt in the general pattern that could easily be translated to a vectorized job in the manner of manually writing out chunk based executions would.
When you know what's going on, hammering out struct jobs is incredibly simple and versatile. But getting to that point took me years of trial and error.
They 100% started working on them, the entry to the source gen code could very well still go through IL weaving
_CCCCB<,,,,,> Yea, I can see why they abandoned that path.
"If you look at the training github using the latest 0.23 entities" - where can I find this?
it was a great middle ground between the current lambda and chunk, even if it looked a bit odd with the variants
Go to the Forks / branches the select the most recently updated one. They're using internal 0.23 entities and HR builds.
cool thanks
You can even check the WIP code out right now if you'd like, com.unity.entities\Unity.Entities\SourceGenerators\Source~
You cant see the package itself but the code they're using requires the most up to date entities. Kinda.
Huh. I've not dug that deep but I remember reading somewhere that all the lambda translate to IJobChunks.
Yep in the current entities version Entities.ForEach does translate to IJobChunk
Their excessive use of structural changes and ECB callbacks make me cry. None of what they're doing can be effectively burst compiled and autovectorized.
yeah, I've said as much that this is a terrible practice and should not be taught ...
but it's just so convenient ...
And yet according to Brian in one of this talks earlier this year, this training and style is being mandated Unity company wide. Absolutely disgusting
I don't get it, they want to make scalable code but then use practices that are obviously not scalable for anyone who uses Entities for a few days. Either they will solve this problem or they don't give a fk
Deducting from how archetypes are working, I just don't think it's solveable
It's a really easy conversion between OOS and DOS. But it takes the worst of both worlds to produce something even less optimized.
I'd be be pretty amazed if more than 0.1% is actually vectorized code in Entities. I've not seen one code example that goes beyond adding a velocity or something that is vectorized
or goes into detail how to achieve it
The path to understand DOTS should be: simple OOS code but replace all arrays with NativeArray (understand manual deallocation/.Dispose) -> moving code off to an IJob (understand how to pass data between the job and main thread barrier) -> understanding IJobFor / IJobParallelFor (understanding multithreading and race conditions) -> Bursting that IJobFor (requiring blittable types) -> now installing entities and so on.
often the methods in Entities itself break vectorization
I've been begging Jackson so make an article or a series on Burst autovectorization and he's said he'll consider it. But yea, entity vectorization is completely undocumented.
{
private bool m_CaptureMatrices = true;
protected override void OnUpdate(EntityCommandBuffer _)
{
if (!m_CaptureMatrices)
return;
m_CaptureMatrices = false;
var matrices = m_Matrices;
Entities.WithoutBurst().ForEach((ref Beam beam) =>
{
var batch = matrices[beam.m1i];
unsafe
{
fixed (Matrix4x4* p = &batch[beam.m2i])
beam.matrix = p;
}
}).Run();
}
} ```
wow, terrible code ... ๐
WithoutBurst, Run, why even bother
Oh god.
Idk why you guys are so harsh, those are training samples for people that most likely never touched entities..
Yea. But they're being taught by Unity themselves. The guys who made this system.
theres a whole bunch of monocle popping going on
You have to start learning somewhere. Showing how to translate a game object project into entities is a decent start. Then you can at least start to grasp the concepts of ECS
Is it too much to expect the same people who employ the the geniuses who made Burst and Entities to properly educate those around them the proper methods and methodology of using their methods...
Are they? I think the sample is empty before the trainee commits anything.
They have the traditional OOS implementation, they're just translating it to DOTS code.
not much of a training sample when the trainees have hardly any grasp how to use entities efficiently.
Yea exactly so the ECS code is written by the trainee
By average programmers that never touched DOTS
what's the point?
Part of the learning process involves stumbling your way through practical application of the ideas you've been taught
An experienced person can then review what you've done and give you pointers
The point is that you guys keep complaining about people that are learning a new system
This is not for the public to learn from
ok, I can respect that
My point is that if Unity is accepting the implementation of this sort of unoptimized methodology, they'll be attempting to optimize for that method and thus do some really strange decisions like the horrible memcopy around GetComponenyDataFromEntity
It seems like you're assuming an awful lot from just a github repo
You have no idea how or what these were used for
A github repo from Unity themselves. Sure, it's not the DOTS team but I highly doubt they're not using the information gained from teaching experienced programmers found in this repo to inform themselves on what decisions they will be making for Entities moving forward.
It doesnt take being the CTO himself to infer some key decision making from the code provided in the sample to know where Unity is headed.
maybe I'm just salty that they have access to entities 0.20 and I don't ๐
Like the emphasis on structural changes and ECBs everywhere. ECBs and especially structural changes should not be accepted as proper DOTS coding. It should be taught proper component and entity design such that structural changes are minimized from the very beginning.
And Unity will be looking at this and thinking, yes more structural changes. That's what coders want.
this is a poor take dude
what is a poor take? that structural changes are terrible?
You're still assuming anything is "accepted" from just a github repo and going from there. We have no idea what they're used for. It seems more likely to me that a teacher could review these and help an author move forward with more expected dots code
I'd hate to be your guys' student, you seem pretty critical of what's obviously someone's first crack in a new system they're unfamiliar with
@viral sonnet that the result of these programming excercises will result in a shift of attitude by mike acton on the direction of dots to encompass less optimized approaches because newbie programmers dont get it right in the first pass
completely laughable
That is just my opinion from months of DOTS work. If I was teaching DOTS officially at Unity instead of stumbling around in the dark, I would hammer the fundamentals of ECS structure first and foremost. Understanding how the lambda are formatted and functioning doesnt work when the produced code is less optimized than OOS. And then they'll lead to programmers thinking that DOTS is a waste of time since they were given an improper foundation.
I really wish that they had just 1 project which is kept up to date, portraying the most recent advances / best practices of dots. Just 1. And not that big.
guess I found one of the worst samples, there are much better ones of the same tornado project
@safe lintel then a tornado sample from acton would be great ๐
Best practices from Unity code example would be so nice. There is that thread and article which was enlightening but completely unusable if one did not understand what DOTS and ECS structure is intended to be.
The ECS samples are updated with every release
But not necessarily rewritten with new best practices
best practices are the packages themselves
But it doesnt contain any of the actual questions a coder might face during DOTS development. Like should I split up this component. What should be it's own entity or be combined with another. What multithreading patterns are required to maximize performance and minimize runtime?
Agreed
Not really helpful
Well there is https://forum.unity.com/threads/introducing-the-dots-best-practices-guide.1054991/ but I think it's already a bit out of date at this point
Out if date. Exactly. That's my point
How can I utilize shared component data and chunk component data to minimize random access and maximize Burst compilation for performance. Nowhere in the documentation is that mentioned.
It contains concepts that are still applicable but the problem is it's not specific to Unity's DOTS. It's like a general best practice for ECS. But we want actionable DOTS best practices.
+1
the ECSSamples are too basic, only boids is good to learn from and has interesting concepts applied
I mean that would be great. Seems like an insane amount of work for something that's supposedly as actively developed as dots is
When I realized that deliberate chunk fragmentation via shared component data improved performance rather than that very scary warning in the documentation that initially put me off, my entire perception of DOTS changed.
Man someone in that thread is using comic sans as their ide font
What in the world
but even boids is far from optimized, hardly anything runs in parallel
Well based on a talk I saw it seemed like that was made by acton. Could have misinterpreted him though
No font shaming
Monolisa is the best one by the way ๐
Yea know, maybe this is what my professor thinks when she sees my shit reports and presentations on a topic she spent 20 years working on.... hrm
any input to make this faster?
Very generic problem to calculate distances and angles between targets. I'm looking for the fastest way to tackle this random access problem
Oof, those if statements are bad.
I'm not at a computer right now but I have some ideas. Give me a sec to fully understand what is going on
yeah, no doubt about that. it profiles faster with those when nothing is moving. sadly can't utilize chunk changes. an entity has another entity as target and copies the foreign LocalToWorld matrix to its local TargetMatrix
I've unrolled the loop but it doesn't make much difference honestly
Yea. Unrolling the loop into batch 4s won't help when you're just doing an assignment of a matrix.
Theres no packed vectorized version of a 3x3 float (9 floats). The v256 packed vectors at 8 floats wide.
All CPU vectorized operations rely on v256. Matrix optimizations are GPU side. They have those vectorized matrix multiplication.
So the only thing you can do is just collapse all that code into a single for loop. Theres nothing I can see that you can do.
Is there any way you can reverse that lookup? Have the target contain the reference to the source entity and then you can use chunk based change filters?
I wonder I'd you could just store the pointers rather than the matrix itself... I will need to do some testing for that.
Question of the day, are entity component arrays unmanaged or are they fixed before entering a job?
I've thought about just storing the pointer. Could be a hassle though when an entity gets removed. Data wise it could be reduced to a float3 and float4 (position, rotation)
like, chunk.GetNativeArray?
Yea. You'll need to keep track of those that store the pointer but itll be a lot better for performance.
Yea. Are those native arrays the same every time they're acquired (unmanaged) or are they mapped to a regular array that require pinning before conversion and thus use.
same every time
at least I got that from reading the source
but maybe I wasn't deep enough ๐
Then yes, just store the pointers. Those are just int sized and then you can have burst autovectorize assignment.
that's also an interesting idea
And inline the if statement. Just set it to itself if the source did not change.
I'm still unsure about the chunk.DidChange<T>. AFAIK there's a version number for every comp but when another IComp in the same archetype changes it triggers a change(?)
That wouldnt make sense. Or else you can just use a general bool that anything can toggle true.
entities should embrace pointers more ๐
I haven't used change filters, everything either changes or remains constant in my code, but do some tests.
And yea. Everything is unmanaged. Largely. That means pointer magic can happen
Not in the same archetype, but in the same chunk
So I guess in the archetype, too. But yeah, specifically it triggers a change in the entire chunk
so let's say, archetype X/Y, IComp X changes, DidChange<Y> will be true?
Lets say you have multiple chunks, meaning you have enough components of an archetype to cross chunks. If any component in chunk 1 changes, then that chunk will be marked as changed. Other chunks will not.
that's so weird, why have a ComponentTypeHandle then for DidChange?
or a version number for that comp
Where is the version number for that component stored anyways? Entity version is its created and destroyed quantity. Not component change.
The DidChange you're referring to is a method on ArchetypeChunkHandle right? So i guess it's referring only to that chunk
yeah, got the wrong impression about a version for each IComp in a chunk
that's the most low level method for DidChange and that's too crude to make any observation about which IComp changed and which did not
You might have to implement a method to track changed yourself maybe a chunk component?
Yeah you're not meant to afaik. You just design your systems with the idea that if any component changes then it re-writes the whole chunk
IChunkComponent would work for that
At least that's how I've always thought about it. This is why I like bevy, it does change detection on a per component basis
bevy sounds cool, I think that's a pretty hefty design flaw honestly
it goes into the concept of splitting components which doesn't make any sense
and if you don't split you have several system working on the same archetype but not every system would need to run when only a few comps change
I can only assume for them to make it work on a per component basis they would have to sacrifice a lot of performance for one reason or another. I was very annoyed too when I realized you couldn't do it per component
You would need am extra int per component if you were tracking change
not a big deal imo but with 10+ comps in an archetype I see the problem creeping up
a method of being able to track a comp with more details would be nice
we don't need a generic solution for every problem, often just a few comps can be enough to determine a good DidChange state
i forget does bevy use archetype chunks internally or sparse set?
It has both. It defaults to archetypes but you can use sparse sets if you want
o ok - cool
Depending on what you need for an archetype
how many people wrote bevy?
This is definitely worth reading through https://bevyengine.org/news/bevy-0-5/#ecs-core-rewrite
It has a ton of contributors at this point. Afaik it was started by one dude, Cart
They got some help from the flecs dev (for the ECS)
He has total creative control until it reaches a certain point
having these 2 types is really cool
Yeah I doubt bevy will ever reach the performance limits of dots, burst is just too crazy. But it's still very very awesome and is so promising
uhm, I thought Unity Entities is using sparse sets? no?
And most importantly open source
burst is killer, yes
Has anyone tried benchmarking bevy code? I know theres an official Burst benchmark out there but it compares against basic C code. Isnt bevy in C?
Bevy is rust
Which is better C? Or was that c++?
I have no idea what that means
Burst bring C# to the level of C++ compiled code. If bevy is in rust which has equivalent performance with C++, is burst necessary?
Where is that github of benchmarks...
rust uses the msvc C++ toolchain on windows*
Well I'm not an expert on the subject, but it seems to me burst allows you micro-optimize in a way that you can't with rust or C++. At least not as easily
i think one of the core devs is working more on simd integration for rustc
When dealing with hundreds of thousands of entities that micro optimization can make a huge difference
The amazing network programmer nxrighthere made a benchmark https://github.com/nxrighthere/BurstBenchmarks
That's the one.
man, Entities documentation is really shitty. I was looking up if they use what bevy calls archetypal or sparse sets and from the documentation it seemed like they use sparse sets...
Unity uses archetypes
Yes unity definitely uses archetypes
They made a whole patent about it
That's what all the chunk business is about, they're chunks of linear data
from chunks alone it wasn't clear to me how the memory layout actually is ๐ one row is the whole entity or one IComp
I think its 1 component. Theres no jumping when processing a single component type.
so it's actually what bevy calls sparse, but chunked up in 16k?
maybe I'm wrong but isn't this the worst of 2 worlds?
No. Its strictly the archetype storage.
then one row must be the whole entity