#archived-dots
1 messages Β· Page 188 of 1
Each compdata of a player has a native array of size 8
Instead of a dynamic buffer
I don't need it to be dynamic
AFAIK, native array is just a struct that points to unmanaged memory
one nativearray of 8 x numb players will be fastest... but.. a dynamic buffer capacity 8 will also be incredibly fast. If you don't exceed the initial capacity, it will all be linear access. Plus there is some code overhead with managing a persistent nativearray, whether you create interdependencies between systems etc.
Yeah I want the fastest option, since I know it access managed memory
When internal buffers are exhausted
And I guess internally it does some checks to see if such an access is needed
when you say [InitialCapacity(8)] public DynamicBuffer<int> or whatever, you're saying an entity reserves capacity for 8 x int (+2 bytes or something) - it's all linear access and unmanaged. Only when you exceed 8 does it then start managing the data on the heap.
There is a good reason to not do the dynamicbuffer route though - that's that the larger your entity, the less you can keep in a chunk/cache while iterating. That's the main reason a persistent nativearray somewhere will win.
Yeah I understand that
So is it better if I use nativearray
With an int
As a "ring buffer"
And since nativearray is essentially just a struct that points to unmanaged memory ( Correct me if I'm wrong ), its size would be the same, regardless of the nativearray's size, right?
And hence you can store the same amount of stuff in a single chunk
erm basically.. but in case it's what you're thinking about, it's not supported to e.g. put a NativeArray (or other native container) inside an IComponentData
Actually, two ints with a native array now that I think about it
Oh
Damn
Why?
:c
well.. that's what a dynamicbuffer is for - and it's very fast
But I don't need the dynamic-ness
then don't exceed its capacity...
Hmmm
I think you should check some of these assumptions you're making about performance.
Oh that's why I'm here haha
if you want to, you can mess around with unsafe and it is possible to use Native containers with ICDs but I'm very dubious it's worth the headache unless you're iterating millions of them every frame.
Oh how tho
there are a few posts on the forum - give it a google
Because the thing is, dynamic buffers somehow have to check if its capacity exceeded its internal ones
I think
Ok I will try thanks
I think they would only check when you add to them or otherwise change their size?
These are not the places you will have bottlenecks.
Are those buffers initialized? Or do you have to add stuff before they do
I'd guess it will more likely be sync points, scheduling, having to touch managed stuff etc
they have a length and a capacity - I don't think it's initialized
It might be though
eh?
Do a test with dynamicbuffers... find out at what point it's "too slow"
https://forum.unity.com/threads/nativearray-icomponentdata-and-blittables.534146/ - first google result for me (unsafe nativearray in icomponentdata) - not sure if it will help
I've decided to just stick to dynamic buffers
Since apparently a fixed array can't use int3
THanks for the help
Speaking of DynamicBuffers, I'm trying to get access to them and edit them on a instantiated Entity in a Parallel Job but it doesn't seem to be possible. I tried this:
Entity e = ecb.Instantiate(entityInQueryIndex, entity);
ecb.SetComponent(entityInQueryIndex, e, new CreatureData() { energy = 1 });
ecb.SetComponent(entityInQueryIndex, e, new Translation() { Value = translation.Value + new float3(random.NextFloat(-5f, 5f), 0, random.NextFloat(-5f, 5f)) });
var inputs = GetBuffer<InputNeuronData>(e);
var hidden = GetBuffer<HiddenNeuronData>(e);
var outputs = GetBuffer<OutputNeuronData>(e);
var synapses = GetBuffer<SynapseData>(e);
However this gives a error saying this InvalidOperationException: <>c__DisplayClass_OnUpdate_LambdaJob0.JobData._BufferFromEntity_InputNeuronData_0 is not declared [ReadOnly] in a IJobParallelFor job. The container does not support parallel writing. Please use a more suitable container type.
can you declare InputNeuronData as ReadOnly? are you tryign to write to the container?
Yeah I need to be able to write to it aswell.
it can still be done, how safe it is to do is another question
you could use an IJobChunk, but thats gonna be one thread per chunk.
I've never used one of those before.
here's an example of dynamic buffer in IJobChunk https://hatebin.com/ukicaqpifs
might be slightly out of date, havent had time for ECS in a while
and if you want to go rogue, here's a DynamicBuffer header you can cast to, https://hatebin.com/lonjhqkvss
var header = *(BufferHeaderProxy**)UnsafeUtility.AddressOf(ref buffer);
var ptr = BufferHeaderProxy.GetElementPointer(header);
then you're just accessing an array var item = ptr[0]
Alright I'll take a look later, It's too late over here so tomorrow :p
Any good tutorials on DOTS and UI? Iβm looking to show an interaction prompt image over an entity when the conditions are valid. I have a system I can trigger this from but on the UI side Iβm confused.
Can I just add a sprite to the entity when conditions are valid and remove it again when theyβre invalid?
Or other similar component?
I'm sure this question gets asked every other day, but what is the preferred method today of adding a string to a component? Or is it just forbidden, and that's all there is to it? I see references to FixedString and NativeString, but these both look deprecated. I'm not sure BlobString will work for my purposes either.
Specifically, when using Netcode, how do I communicate a player's name to another player? Or do I have to roll my own API for that?
AFAIK, UI is not DOTS ready. The way I see it, in this case you would need to go hybrid.
Your system can talk to a MonoBehaviour (and the other way around but it will probably make your job unsafe). Then have your MB enable/disable your Sprite as usual based on the result of the data obtained from the system.
I have no tuts to recommend on that topic, mainly saw forum threads for that one
So I could just use a GO with a child that has a sprite that I enable and disable and the parent would have the entity authoring component as well as the MB?
I think I need to look at some hybrid examples
Yup
It's not well documented yet but you can sure call ECS packages from Monobehaviour
Yeah thanks
I hoped with a block :p
@rare umbra Alright so something like this should work https://hatebin.com/hncawqzlht
ANd on the system side, a public class variable or a getter, updated by the system
(not tested though)
@frigid onyx nativestring is the old one but fixedstring is the current way to put strings on components
haven't used netcode so dunno about that specifically
you could also consider storing strings outside components, e.g. a system that holds a list of playernames, and have the components contain an index for this list instead of the full string
Right, the transmission is the difficult part.
I'll play with fixedstring and see if Netcode will relay it automagically
Thanks for the confirmation, I thought fixedstring was deprecated, I was just looking in the wrong namespace
Excellent, thanks!
You're welcome, happy coding
@mint iron I don't see how a IJobChunk would help.
I'm confused do commandbuffers not require m_EndSimulationEcbSystem.AddJobHandleForProducer(this.Dependency); anymore? π
Yes they do. If you find it working without it it's just a coincidence and you probably have a sync point or structural change between when your job is scheduled and when the command buffer runs
yeah I figured, it's weird it works without it
I also cannot find AddJobHandleForProducer
maybe I'm using a different kind of buffer
What do you mean you can't find it? Are you getting an error of some kind?
no, no errors its just not in the list of methods
Oh, like your IDE is failing to find it? Whenever stuff like that happens for me I just close visual studio and delete all my vsproject files and the ".vs" folder, it always fixes it.
Extremely dumb that I even have to do it, but it works
damn yeah I keep getting quite a few bugs with VS lately
i quite often have to restart rider and clear its cache too π©
i wonder if these issues come up often in non gaming code stuff
I didn't even consider that, I just assumed it was some weird interaction between VS and unity
Good question
Well,, I need some help with finding closest entity from entity again. It's just way too slow with the current method (which is going through every entity for every entity)
@odd cipher you could sort them into seperate buckets/cells so that each entity only has to check its own + surrounding cells, the samples project has a boids example that uses this by sorting by cell into a nativemultihashmap: https://github.com/Unity-Technologies/EntityComponentSystemSamples/blob/master/ECSSamples/Assets/Advanced/Boids/Scripts/BoidSystem.cs
Yeah I know, I've looked at it before but I don't really understand it.
think of the world being divided into a grid
let's say for example sake each cell is 10x10
if an entity is at position (15, 5) you know it's in cell (1, 0) or an entity at (50, 50) is at cell (4, 4)
if you wanna check what other entities are within 10 units you only have to check the entities in the surrounding cells
rather than every entity in the world
Mhm I get that, It's just the code I don't understand much.
Sure there's a lot of boilerplate to make it work with DOTS :/
It doesn't help that the native multi hash map api issomething that no human should ever have to use
nativemultihashmapmergesharedwhatthehellisgoingonhere
Yeah..
Could roll your own spatial hash map - take the position hash it store it into a multi valued hash map (hashmap + unsafelist combination)
I'm not sure how that would work
you pretty much get a region divided into a grid/cube (depending on the # of axis) and each region stores a certain # of entities
so you wouldnt need to iterate through every single entity to determine which is closest
you would just need to search in the region
Ahh, I'll try it and see if I can get something like that working.
@odd cipher That's always the same idea. Be it called a quadrant, an octree, a grid, or the native multi hashmaps of the Boids demo...
Mhm alright
Google spatial hashing, there's plenty of material online you could build from
"Spatial partitioning" or "broad-phase collision detection" too (since the principle doesn't strictly require a hash table). This is one intro https://gameprogrammingpatterns.com/spatial-partition.html
Chapter 7 of the book Real-Time Collision Detection has more details on these methods.
Actually, if it's just finding the closest entity within a certain radius, couldn't you just use the UnityPhysics package and do like a PhysicsCollider distance query?
To obtain the "forward" vector of a transform we do "this.rotation * Vector3.forward"... im using "quaternion" instead of "Quaternion"... and i can multiply that one with a vector3, it says this operation is not supported. So how can i calculate the forward vector in another way ?
@gleaming plank I tried doing that but it never worked
Oh and is there any advantage using "float3" over "Vector3" for dots ?
@stone osprey vector3 is not dots
Yeah i know ^^ but its also a struct storing x,y,z
the BurstCompiler only recognizes the Unity.Mathematics primitives
That means float3 is more performant than using unity-s standard vector3 ?
Yeah, you should use float3 if you're hoping to see SIMD speed-ups from Burst. You can pun/reinterpret Vector3 as float3
Ok, thats great... but i saw that its missing a lot of functions... for example Vector3.RotateTowards(...) is not implemented for float3
I think you're going to have to re-implement those functions (unless somebody's made an asset)
Ok thanks ^^ could anyone here provide a simple example of how we rotate a dots entity ? The new math api is strange... rotate returns float3 instead of another quaternion
Thanks ! Looks a bit... more clunky than the average unity vector3/Quaternion rotation code... hopefully they'll compress this in the future
@zenith wyvern is that .ScheduleParallel required? I think it's parallel by default now right?
No. It used to be that schedule was parallel, but they reversed it after they got rid of IJobParallelFor
Now schedule runs in a single thread
and there's no ScheduleParallel anymore?
Yes there is, like in the code I linked above
If you want to force your job to run in a single thread you use Schedule. For parallel you use ScheduleParallel
When I said they reversed I meant that they used to have "Schedule" (parallel) vs "ScheduleSingle". Now it's "Schedule" vs "ScheduleParallel"
ah okay
Why?
Try messing with the boids sample and you'll see
I still don't get why xd
Because it's awkward to add elements and to access the elements of a key.
Hmmm but I use it when I want to group stuff based on Entity
I didn't say it doesn't work, I said the api is bad
Usability. Although in a lot of cases you can get way better performance if you can use NativeStream instead. Just depends if your problem fits
I need access via keys, in my case Entities
Like to access data specific to an Entity inside Entities.ForEach()
does "Override Property Declaration" replace "Hybrid Instanced (Experimental)" in Shader Graph?
ah nvm
yes it does
Is it possible to change an variable's value in one element of DynamicBuffer throught EntityCommandBuffer?
the three buffer related functions of ECB seems neither works this way.
When I ToComponentDataArray<Translation> and set the values and afterwards copy the values via CopyFromComponentDataArray the entities doesnt render in their new position?
I can see the values of the translation value change in the entity debugger, but the hybrid renderer doesnt render the entities in the new position.
If I set them via a Entities.Foreach it renders correctly. I don't get it
Is it possible to figure out when a Scene is ready to go after loading it with SceneSystem.LoadSceneAsync with the LoadParameter flag DisableAutoLoad?
I want to be able to control a transition between scenes when an event happens and the async loading/streaming progress is done to have the experience be as smooth as possible.
Also, when I want this transition to happen I call SceneSystem.LoadSceneAsync again on the same GUID with flag LoadAdditive, it seems to do the trick but is there a better method to push the scene that was set to DisableAutoLoad to then load?
As command buffers can only be used in a job and the EntityManager cannot be used in ForEach what am I supposed to use for structural changes in a main thread ForEach?
Command buffers can be used on the main thread. And EntityManager can be used in ForEach as long as it's used .WithoutBurst() and .Run()
also WithStructuralChanges() if you are changing stuff
Actually if you're doing strucutral changes you need WithStructuralChanges()
I tried doing this for a quadrant system but it doesn't seem to work correctly. The problem might be how I show the quadrant but the data doesn't correspond to the correct amount of food on the map. https://pastebin.com/dx4g0kPT
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.
How does Unity's ECS determine if a system needs to be called or not?
Systems don't provide any info about which set of archetypes they need to iterate over. Most I saw is that they store created archetypes locally to later query with them, but those are private variables
@fringe sinew if you use Entities.ForEach unity codegen creates an entityquery for it
in systembase update() it checks if its queries have entities and if at least 1 query has at least 1 entity it will run OnUpdate()
@hollow sorrel That is for the default world I assume ?
Ssytems from other worlds wont load automagically ?
no it's world independent
systems from any world will use that to check if they should run
alright nice
But how? The queries are stored locally. How does a system knows if it should call it?
Like, hold on, gimme a moment
it all happens in the systembase itself
world calls system.update() (unity code) -> system checks if its entityqueries have entities -> system calls system.OnUpdate() (user code)
But I don't pass anything into sysytembase. I store the queries locally. It shouldn't even know anything about my systems. So how does it?
How can it check the queries if it doesn't see them?
I'm opening the project, I'll illustrate it to you rn
Unity ECS automatically discovers system classes in your project and instantiates them at runtime
And it puts them in a group
the simulation one by default if I remember well
Yes, I know. That's not the topic of the discussion.
It shouldn't even know anything about my systems
Sorry I didnt understood well then.
my bad
...takes awfully long to open it
Okay, this. The system has an EntityQuery as a private field. It's created in OnCreate.
And I found the answer. It adds the copy of the query to an internal systemstate upon creation.
Yeah, Scorr told you in which order it's discovered
I wanted to know how exactly.
"system checks if its entityqueries have entities"
"How exactly?" was my question.
Yes, by default it adds any queries from the system to a list and checks those, including ForEach queries
You can override that behaviour with RequireForUpdate/RequireSingletonForUpdate
Sounds like an easy recipe for disaster if one were to create queries in OnUpdate. Guess the api is not verbose enough?
As far as I know GetEntityQuery tries to be smart about it and will cache queries if possible. But yeah generally you should be creating your queries in OnCreate and storing them in the system
I'm not sure but I assume they do something like that during codegen for ForEachs
They say so in the docs but I'm not sure if they mean when you use WithStoreEntityQueryInField or always
yeah it always gets cached with entities.foreach
creating entityqueries has some overhead so you don't wanna be doing it in onupdate
whats your usecase for creating queries in onupdate?
I'm trying to figure out how to group my entities
the context is a RTS with a lot of entities
for example, if I press Ctrl+1, I will group all the entities I have selected in Group 1
I only see 2 possible solutions, first is to have a native array of entities, and iterate this array when I have to process only this group
second is to have a Group1 tag, so I can only process this group by querying <Group1>
Just use tag components. It should always be the goto unless you have performance concerns.
what do you mean unless I have performance concerns? is it slow to group by tag components?
Each time you'll move groups, it will move entities to other chunks
It causes structural changes, which can be slow if you're doing it a lot - like many many times per frame. For something related to user input it should be fine.
do you think I will see a speedup with structural changes in release build?
I have hickups in my game and I realize this is probably because of structural changes happening
Don't make any assumptions. Profile it.
can I see structural changes happening in the profiler?
Yes, it will force all your jobs to complete
If you're using ECBs then it should show them as taking up the time. If that's what's slowing you down. Which again, who knows until you profile it
@safe lintel @zenith wyvern sry got distracted. This seems to be the missing piece. Is this also necessary with command buffer?
Sorry, is what neccessary?
WithStructuralChanges()
no
No, command buffers will work in burst. That's their whole purpose, they defer structural changes to later in the frame or the next frame
yeah just wasnt sure if it was recommended to use WithStructuralChanges() still
That disables burst so no, if you can avoid it you should
I see thx
yes I'm using ECB
anyone able to look at my previous question? Haven't found the source of the problem.
is it regular practice to create a new ECB for very job?
You mean using ecbSystem.CreateCommandBuffer().ToConcurrent(); (with or without concurrent) in OnUpdate?
@tawdry tree yes. although I'm doing .AsParallelWriter(), because the docs does it like that
@odd ridge I think you pretty much need to create it in OnUpdate, and even the docs do it, so it shouldn't be bad practice at least. Assuming the docs are not way old and un-updated
when should I use or not use .AsParallelWriter()?
Well if you aren't using multiple threads to write then you wouldnt use asparallelwriter
Is there a way to asynchronously update a texture from the CPU using a job? Updating a texture blocks for a long time and I would rather not do that on the main thread because I need to do it lots of times every frame.
There's https://docs.unity3d.com/ScriptReference/Texture2D.GetRawTextureData.html, but I have no idea if it's safe to use inside a job.
The problem isn't the generation of the pixels, that is very fast. Texture2D.Apply actually writes the data to the GPU, and takes a few milliseconds! Unfortunately, this cannot be done in a job.
Is there a function to batch the Apply method on a collection of textures?
Does EntityManager.RemoveComponent<T> check if components exists ? Or it should be done manually?
After a little glance, not sure about your food count yet, but regarding the cam to get the mouse screen pos, I don't think you can use the Unity Engine cam. Would have to track coords in a component you update yourself probably.
I believe it checks
https://docs.unity3d.com/Packages/com.unity.entities@0.16/api/Unity.Entities.EntityManager.html#Unity_Entities_EntityManager_RemoveComponent__1_Unity_Entities_Entity_
Removes a component from an entity. Returns false if the entity did not have the component.
Is it possible to do Entities.ForEach on another world?
@karmic basin Maybe, I can tell one problem is that the debug area pretty much follows the camera and not the mouse for some reason. Not sure if that's what is causing the other problems. https://gyazo.com/038169fd1e9e58e1b49eddd51f0e9be1
Wait with the code inside the system ? That's great.
Then you would have to Raycast in the physics world, against the ground if you want to follow the mouse hover
Yeah the Debug stuff works but doesn't seem to show the correct information. A raycast could probably work but I've had some problems with doing that as well. Not sure how to do it :/
You're using Camera.ScreenPointToRay with mouse input right ?
RaycastInput.Start is Ray.origin, RaycastInput.End is Ray.GetPoint()
then you can read the RaycastHit.Position
Alright I'll give it a shot
cool
I think that's enough, then of course you feed the position to your quadrant system
quadrant-debugger-method * I meant
Actually, if it works when you move the camera, that should enough to help you debug, no ?
Yes, it would. But it doesn't work. It doesn't say the correct amount of 'food' entities in the quad.
Unity seemingly just failed to "Import" the authoring components on my prefabs. All the values were set to default values. A reimport of the prefabs fixed the issue. Did anybody ever had this happening? Is this a Unity bug?
@karmic basin The raycast mostly works but it refuses to go to the corner for some reason. Not sure if that has anything to do with the problem with the wrong data being given.
https://gyazo.com/8e0ba30f5fcdcc64ab1f43427320e0d8
https://pastebin.com/mWYsG0ba
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.
might be an index 0 vs index 1 issue?
Not sure..
You should floor the position based on cell size no?
Vector3 lowerLeft = new Vector3(Mathf.Floor((int)position.x / cellSize) * cellSize, 0, Mathf.Floor((int)position.z / cellSize) * cellSize); something like that ? (not tested)
because yeah that seems like a one-off error
Nope, didn't make a difference
I'm not 100% sure but it looks like you're drawing based on a world position and expecting it to draw based on the local position of your mesh
If you move your mesh so the bottom left corner is aligned with the world grid does it behave like you expect?
Also you don't need vector3s. You can pass float3 directly to DrawLine and it converts them implicitly
So you can do something like ``` void DebugDrawCell(float3 p)
{
p.xz = math.floor(p.xz / cellSize) * cellSize;
float3 right = new float3(cellSize, 0, 0);
float3 up = new float3(0, 0, cellSize);
Debug.DrawLine(p, p + right);
Debug.DrawLine(p, p + up);
Debug.DrawLine(p + right, p + right + up);
Debug.DrawLine(p + up, p + up + right);
}
Thank you! That fixed all of the problems I had. Now I can move on from this :p
Cooooool
Alright well for the performance, the Quadrant system itself takes ~5ms and the system that read the quadrant data for each entity takes ~0.05ms with 1000 entities that are searching and 500 food entities
I feel like it can be improved
Not sure, but it is definitely better than what I had before. However I will need to search neighboring quadrants if their 'search radius' goes outside of a singular quadrant. Which I am not sure how to do.
Oh oops! The quadrant system was running instead of scheduling. My bad, with scheduling on it runs in just ~0.05ms as well. Way better than I thought.
Yeah also remove Debug for the build, it should get slightly better
Yeah I did.
You're right, you also need to check neighbours for entites overlapping corners
it's similar to how you started to debug draw your quadrant. You go +1 in each direction
Mhm, I'll try getting that to work.
Let's say you are checking Quadrant at index(2, 5), you also check all combinations of -1 and +1 on X axis, and -1 and +1 on Z axis,
Quadrant (1, 4)
Quadrant (1, 5)
Quadrant (1, 6)
Quadrant (2, 4)
Quadrant (2, 5)
Quadrant (2, 6)
Quadrant (3, 4)
Quadrant (3, 5)
Quadrant (3, 6)
Precisely. Though only problem with this is that the radius that a entity could have could be larger than that 3x3 quadrant area
And if that radius is the same as one quadrant I don't need to check the neighboring ones at all.
Totally, as long as you scale everything right you're fine with one
You avoid the hassle π
I'm guessing you mean that I can scale the quadrant to the size of the radius. It won't work like that as each of those entities has their own radius. They don't share the same one.
Set your quadrant system based on the largest radius ? This way you still benefit, unless you have an entity that can see the whole map :p
Anyway you still need to check neighbors in case your entity is too close to the border
Or maybe each Entity can tell how many quadrant offset they are allowed to check, for those who see further
And you dont need to store that data, you have everyhting with radius and cellsize
Man I'm tired
Heh yeah, I just need to figure out the right math for it :p. There are probably some examples on how to do it online that I can take a look at. It'll just take a little bit of time.
Alright good luck
How do i make one "Scheduled()" loop run after another one ?
When you're not messing with jobhandles that's the default behaviour of systembase.
Oh... alright, thanks ^^
One other little question... my server sends every 500 ms a new location to each entity. This way it looks like my entities are teleporting around. Any idea how i could interpolate the movement ? Currently the flow looks like this : New Packet received -> entityTransform.position = packetPosition -> System places entity down... i also have a "Movement" component that interpolates a entity's position, but i have no idea how to use that one properly because the new location gets parsed into the transform instead of the "Movement component"
Sorry I have no idea when it comes to networking stuff
Damn... me neither
Probably some sort of history is required for such a task...
Like always storing the last position, then when a new one comes we use the old one as the position and the new one as the target
@hollow sorrel Thanks π Then the only last problem left is choosing a architecture. My Packet-Receiver simply writes the new position inside my transform component. I want to automate this later, so i cant implement the logic in there. Which means i need to implement it inside the ecs instead :/
And thats my main problem... i have no idea how. Im already tracking the past position by simply writing the last location into another component at the end of the movement system. Now i need some way to use write the new position into "MoveTo" and the last position into the transform
not sure if i understand correctly but i think what you'd want is to seperate the 'networked' position from the 'real' position, and maybe even another seperation with 'interpolated position' and 'real' position
what i do is seperate 'real' position that is used for physics, updates at a fixed rate, and then a 'interpolated position' that is only used for rendering
i don't use networking but if i did i'd prob have another component that keeps track of what the networked position is
So i should basically have a "RealTransform" and a "NetworkTransform" and then i interpolate the realtransform towards the network transform ? ^^ That makes sense... thats actually easier than tracking the last location and also much more flexible
yeah, or RealTransform can just be a copy of NetworkTransform, and then a seperate RenderTransform that has the interpolated version
RealTransform and NetworkTransform are prob pretty similar but i think i'd personally want to have at least a mental seperation of the network version being 'what the server reports' and 'real' as what is running on the local client
Thanks, thats what im gonna do... much more clean that tracking locations ^^ its a pitty that structs cant inherit from each other :p now im forced to write an exact copy of that one
So I wrote a little cellular automata and tried it with burst but its 10 times slower than just using a loop. Anyone got any idea why?
Here is the Job.
https://controlc.com/5b9bb724
public struct BoolCAJob : IJobParallelFor { public NativeArray origi - 5b9bb724
Are you sure it's bursted? You have burst enabled in the editor and you have the [BurstCompile] attribute on the job struct?
yeah i added the attribute and enabled burst but it doesn't work
I can see you have a couple functions taking managed arrays. Just make those static
the burst inspector says something about remark unknown:0:0 loop not vectorized
you mean the get and set map?
Yeah. I'm not sure if that would cause errors unless you're explicitly calling them from inside burst though, not sure
I would try making them static and see if it still errors
using Unity.Burst; using Unity.Collections; using Unity.Jobs; using Utils; namespace - 108e7be0
So I made a new version but it still complains about loop not being vectorized
does it compile static methods to burst too?
Can you post the exact error? And no, it definitely won't compile static functions unless you call them from inside burst
While compiling job: System.Void Unity.Jobs.IJobParallelForExtensions/ParallelForJobStruct - 25182b65
You can surround it in triple backticks with linebreaks between or just some pastebin
Thanks!
///Test
Backtick is `
You have to click after the last backtick and press enter
So one set of 3 backticks, code, then 3 backticks, enter
I did yeah, from what I could see that error can happen if you try to pass in a member variable to a job. Are you doing that? Anything you pass into a job must be assigned to a local variable first
Even if it's just an int
From only what you posted I can't see what would be causing it. Can show the code where you're running the job?
I was
Another quick question... how do we "slerp" or "lerp" a "quaternion" ? I mean that one from the new math library
math.slerp
perfect, thanks ^^
So there's an AddBuffer and GetBuffer, but it looks like GetBuffer creates a buffer if it doesn't exist? Or am I not reading their code correctly?
If that's not the case, how do I check for the existence of a buffer (to know to use AddBuffer)
I can't test a DynamicBuffer<T> != null
EntityManager.GetBuffer<T>(ent).IsCreated , maybe?
EntityManager.HasComponent<BufferType>
So like EntityManager.HasComponent<DyanmicBuffer<T>>(ent)?
No. Just the "T" part
How would it differentiate between T and a DynamicBuffer of T?
It doesn't make sense for it to differentiate. An entity either has a dynamic buffer of your type or it doesn't
So let's say you have MyComponent , which inherits from IComponentData. How would HasComponent distinguish an entity that has a component of MyComponent from a DynamicBuffer<MyComponent>?
You can't have a DynamicBuffer of MyComponent because MyComponent is an IComponentData. The contents of a d DynamicBuffer can only be IBufferElementData
Is it possible to have a NativeArray of NativeArrays? It seems like no... Or should I allocate one big NativeArray and sub-arrays using NativeSlice?
You can't have native arrays inside nativearrays. You need to collapse everything into a 1D array or use NativeMultiHashMap or NativeStream
Is ECS and such good to start learning again or is it constantly changing still? I gave up after learning it two-three times as it kept removing/adding things that changed everything entirely. So I'm hoping it's aged enough to be usable and next week not changing a million things again.
Hi all, need some advice about Worlds.
I'm a fair way through development, but when I started I did everything in one World, including all my physics and movement, so it's all on the same Update() loop. My game is GPU-bound because it's 100% raymarching; on older GPUs, I now realise if the frame rate drops really low, I get problems with the player not colliding properly with the environment because the deltas are too big during a single frame.
I'm not sure how best to tackle this. I could in theory separate all the non-rendering related code out into a different World, but have no idea where to start with this or how the worlds interface with each other. Alternatively, I could try to modify my physics specifically to mitigate the issue, but that does feel a bit of a hacky approach to the problem.
What say you gurus?
I would only consider multiple worlds in situations where i would want to keep iterations over entities small. For example you have 10 game floors and on each you have units searching for valid opponents (assume a pathfinding algorithm like A*), if those floors are never connected, you could keep itterations low by having 10 worlds so that the search for valid opponents ends up beeing 10 small loops (it's basically a pre-filter in a sense).
Otherwise I would suggest to first tackle your frame drops anyways as those are obviously always an issue. Would be interesting to hear different opinions though
I am trying to sync and interpolate rotation with NetCode ghostfields, but if the rotation value goes from 359 to 0 the interpolation makes the object rotate the full 360 degrees back.
In the DOTS Sample the character class has an angle float with a custom [GhostAngleValue] attribute that uses angle lerping instead of normal lerping.
This custom functionality is implemented in a class that's derived from GhostSnapshotValue which doesn't exist in the latest version of NetCode.
How can I implement this behaviour in the latest version?
Woulndt it be easier to have a floor SharedComponent in this case? So the entities are all grouped together by floor?
I think having different tick rates might be a good reason for having multiple worlds. Though I havent thought about the update rate of the physics group yet. I thought it had a custom tick rate even if it is the same world
sure, there are multiple solutions. you could even only calculate for the floor the player is in by adding a component to those units on that specific floor. Using SharedComponent can also work, depends wether you're fine doing chunk itteration
yes a different tick rate within the same world would be ideal, I just came across https://forum.unity.com/threads/fixed-timestep-features-coming-to-entities-dots-physics-packages.899687/ this thread.
obviously I'll be addressing the slow frame rate issue - but this is an edge case for older graphics cards where the settings have been bumped up. I could just say "well don't do that" but in the event someone does buy my game and runs it on slow hardware or on an insanely high res display, I'd like to handle the edge case a bit more gracefully than at present!
was thinking a bit now, i think i would still go with multiple worlds instead of shared component data @pulsar jay (in the example i made). because most probably a lot more is happening per floor than just units searching each other. and having a shared comp on all the entities that are floor specific is not only error prone but also tedious. it's far easier to use a entity transaction and move everything to that world it should participate in. Also you don't have to write chunk itteration or set any filters, but you can use full power ScheduleParallel systems π @wary anchor sorry, didn't mean to give stupid advice of course π The tick argument i would actually agree upon. also nice link, didn't know that. seems worth a try
ScalePivot how do you make them work?
https://docs.unity3d.com/Packages/com.unity.entities@0.16/api/Unity.Transforms.ScalePivot.html
it feels like coming together. I've been working with it proffessionally since it was available and I enjoy working with it
some reading
@visual juniper Thanks mate, I might try to dive into it a bit for my game. Do animated meshes get more performance benefits with it? As we all know skinned mesh renderers kill performance kinda bad (or can at least). So curious if there's performance benefits with ECS and animated meshes.
So far we used a hybrid approach for skinned meshes (but we also don't work on projects that have high numbers of them where it would become relevant).
I think there's somthing on the way though, you might wanna check out forum topics like this : https://forum.unity.com/threads/how-can-i-animate-skinned-meshes-in-ecs.894688/
Hi, I wanted to make an aquarium with lots of fishes so I thought I'd use Hybrid Renderer. My fish models come with an animator and skinned mesh. If I...
I hear ya mate, I've thought about doing hybrid, just seems like it might make things more complex (could be wrong), just seems like it would be an organization mess mixing regular components and ecs logic together. But i'll check it out right now, thanks for the info π
Dang they getting killer performance (the person talking about the cliffs, trees, etc)
17K Skinned Meshes, wow haha. I and here I was thinking 100 players on a map was gonna be hard on skinned meshes, yeah I might try this hybrid approach lol
Keep in mind that a human character has a lot of bones, so the performance impact might be a lot bigger depending on the model and the rig you're using
Since they're using a mesh that only takes up a small part of the screen they can get away with way less detail
less tris and less bones
Most of my rigs will be of animals, so may end up being more bones and such than a person to account for tails, paws and their toes, etc. I guess I can try sticking with normal stuff for as long as I can, no sense in premature optimization lol. If I can get it to work smoothly no sense in using ECS until I need too. I guess I can run a test once I get some animals made and stick as many as I can on the screen doing various things to see the performance impacts.
I'd say each animal will be about 10K Poly's for the animal and 20+K for the haircards (unless I can figure out how to do Fur in HDRP)
with shadergraph
But thanks everyone for helping me get a bit more up-to-date on ECS π
Thanks! Read it a few times now but maybe I'm not getting it. I have this code:
var entity = EntityManager.CreateEntity(typeof(Translation),
typeof(LocalToWorld),
typeof(RenderMesh),
typeof(RenderBounds),
typeof(ScalePivot),
typeof(NonUniformScale),
typeof(CompositeScale));
EntityManager.AddSharedComponentData(entity,
new RenderMesh
{
mesh = CreateMesh(1), // Creates a 1x1 mesh
material = material
});
// omitted other RenderBounds code
EntityManager.AddComponentData(entity, new ScalePivot { Value = new float3(1, 1, 1) });
EntityManager.AddComponentData(entity, new NonUniformScale { Value = new float3(2, 2, 1) });
And in OnUpdate I have this:
var deltaTime = Time.DeltaTime;
Entities.ForEach((ref NonUniformScale scale) =>
{
scale.Value += new float3(0.5f, 0.5f, 0) * deltaTime;
})
.Schedule();
I'm expecting for it to scale from top-right, but I'm getting bottom-left
Hey guys. I've got a massive hierarchy of meshes, which are static. It seems like they don't like being converted (using Convert To Entity). Meshes are spread all over the place (positions are wrong). Not converting works fine. Converting and making them not static works fine as well. Also maybe related, I've got really bad framerate when converted, even worse than not converted + not static. Any idea? I'm using hdrp9, hybrid0.8p19, in unity 2020.1.6
i dont know why but ive had issues with static gameobjects being converted too.
only workaround was to mark them not static so far\
any reason you are relying on it for conversion? i found you can bake navmesh data and then unset static or at least set it to navigation static only and it does convert properly
i just assumed entities + static would be more performant and be a better choice overall. Also we are using dots physics.
I could leave them as not static, but its super slow compared to classic static non converted GO. In the end i had to leave them as static Go, and to create proxy entities just for the physics... which im not super fan of
are you using staticoptimize on your entities? and did you profile exactly what is causing the lesser performance compared to non converted static gameobjects?
hi, Entity index is int, what happen if we create more than int.maxValue entities?
Entity has two ints as identifier, so unless you make 2 billion entities without ever deleting one, I assume it'd just use freed indexes
And if you do make 2 billion entities without ever deleting one, I'm sure the DOTS team would like to learn about your unique use-case
i dunno but also i think there's currently a limit of 128 million entities per world
at the same time
not sure why that number, just saw it come by in changelog
Huh, Unity is now integrating MLAPI. I wonder what that means for dots netcode
Oh I see, from the blog post As we mentioned above, this announcement is focused on developers working with a GameObjects pattern. For developers that are working with, or evaluating, the Entity Component System (ECS) pattern, either because of preference or because their title needs that level of hyper performance, the Unity NetCode package (Preview) continues to be Unityβs first-party framework for the scenario.
Yeah I guess dots networking will still be a thing, looks like it will fight against Mirror
I guess they got tired of people talking mess about their built in solution (for good reason)
havent been paying attention but was mlapi some sort of mirror like project prior to being bought out? havent heard of it before
It's just an open source networking solution, I guess a pretty good one. I hadn't heard of it either until earlier this year
I'm not using staticoptimize. Is that mandatory? what is the effect? (i didn't take the time to profile yet)
it removes unnecessary transform components. might wanna profile though to narrow down your problem
on one traditional game level demo I tried that static optimize and without it, it made a huge difference. also if you have static objects I can't see why you wouldn't use that (altho I somehow wish it would just set that on it's own from the static gameobject flag during conversion or something)
one thing I disliked when using hybrid render was that you couldn't just remove 99% percent of transform components and get a static setup
on my custom engine, the only thing the rendering needs is the L2W plus Bounds for culling
you can cut all components right off (or disable) and it just shaves all the cpu cost away. seems like it should be inclusive instead of exclusive but who knows
also I see a few mentions of fixed update, are people not using fixed update utility?
@wary anchor if you want different fixed rates within a world, just use this and set them to different groups
to interpolate the results between ticks, make a presentation component, put a long tick number on it, along with the current fixed rate length (the delta). inside the group, set the delta time (will be the groups fixed dt) and bump the tick number. on components for interpolation, you bump the last tick value to somewhere (usually just a Current, Last field in the component)
then outside of the fixed group, you take the current tick, your actual frame dt, div the floats into a percent and (s)lerp the values between the two ticks
fixed rate utils also lets you set and unset the fixed rate while running
I did that from network events from the server to sync up the tick rates between server & client
Hey all, whatβs a good design pattern for having global system parameters editable in the editor but not instantiated per entity. I need my system to be able to reference these
Is there a way I can get an Entity to collide with a game object in version 0.0.12? (2018 is the latest version that can run on my computer)
Iβm trying to create a Bullet Hell framework for Unity and I donβt need everything on my game to be an entity.
@deep nymph either use gameobject physics and make entity copies, or use entity physics and make gameobject copies
anyone know what this might be caused by?
Internal: JobTempAlloc has allocations that are more than 4 frames old - this is not allowed and likely a leak
How do I track down said leak?
look for native containers that are allocated using jobtemp alloc
or ctrl f Allocator.TempJob
if it's not your own code, it might also be happening if you're using a commandbuffer and executing it more than 4 frames later
@hollow sorrel ctrl+f didn't find anything in my c# project :/
no commandbuffer either - I literally have 1 dumb system in this project and it's not really doing much yet
Thank you
@rare umbra what entities version? if you only have 1 system could be unity bug
Version 0.16.0-preview.21
huh weird
it was working a few weeks ago when I set it up. Maybe it's because I'm on the latest version of Unity
also my GO's seem to disappear from the scene when I hit play (after conversion - their mesh isn't converted to an entity component).
I step away from ECS for a couple of weeks and I feel like I'm back to square one.
Are you sure you have the hybrid renderer package installed?
Yeah I just updated it actually
Has anyone seen a error log like this before:
Stack Trace
ReadWriteBuffers are restricted to only read & write the element at the job index. You can use double buffering strategies to avoid race conditions due to reading & writing in parallel to the same elements from a job.
Unity.Collections.NativeArray`1[T].FailOutOfRangeError (System.Int32 index) (at /Users/bokken/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:254)
Unity.Collections.NativeArray`1[T].CheckElementWriteAccess (System.Int32 index) (at /Users/bokken/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:142)
Unity.Collections.NativeArray`1[T].set_Item (System.Int32 index, T value) (at /Users/bokken/buildslave/unity/build/Runtime/Export/NativeArray/NativeArray.cs:161)```
Deep inside Unity.Physics.Systems.BuildPhysicsWorld+Jobs+CheckStaticBodyChangesJob
which touches
[ReadOnly] public ComponentTypeHandle<LocalToWorld> LocalToWorldType;
[ReadOnly] public ComponentTypeHandle<Parent> ParentType;
[ReadOnly] public ComponentTypeHandle<Translation> PositionType;
[ReadOnly] public ComponentTypeHandle<Rotation> RotationType;
[ReadOnly] public ComponentTypeHandle<PhysicsCollider> PhysicsColliderType;
@zenith wyvern @hollow sorrel found my issues - both were caused by the netcode package
I think it started happening when upgrading entities or physics package (maybe it got smarter in detecting issues) π€
Did anyone upgrade physics to 0.5.1-preview.2 ? When I tried my entities started disappearing because the physics eventuelly caused my transforms to end up having a bunch of NaNs. no issues on 0.4.1 π¦
havent had any issues and all my packages are the latest
maybe the issues are related, just express themselves differently π€
Really dumb question - if I have a monobehavior on a GO and convert that GO into an entity - how do I reference that entity within the monobehavior?
i would do the painstaking thing of start disabling everything until it doesnt error to narrow it down π’
yeah :/
Finally some free time again and I'm wasting it all (presumably) on fucking package incompatibility π¦
hmm didnt snacktime have some error regarding entities that popped up during animation?
Let me stalk him in the forums π
NetCode question: It looks like you can't have more than one type of DynamicBuffer<ICommandData> at the same time? Is there a reason for this?
Or--has anyone ran into this? If so, what is the workaround? It looks like if I've already established one input buffer, adding another one gets set up fine, but doesn't actually relay the buffer from the client to the server, even if both input buffers are defined on the same command target entity
@safe lintel if I simply comment out the following things: physicsVelocity.ApplyAngularImpulse, physicsVelocity.ApplyLinearImpuls and physicsVelocity.Linear = foo I get no errors π€
makes me wonder if something changed there π€
Lemme undo to 0.4.1 and see if that fixes the issue s well
is that commenting out in your systems or the package itself?
that part of my system
Commenting out futher, ApplyAngularImpulse seems to be the culprit π± Why on earth would that behave differently now...
@rare umbra in the conversion thing just store it in a field in your monobehaviour
Entity myEntity;
void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
{
myEntity = entity;
}
// do stuff with it
void Update(){
World.DefaultGameObjectInjectionWorld.EntityManager.SetComponentData(myEntity, new Translation{Value = transform.position})
}
This sounds good but itβs not this monobehavior that needs to reference it, though they are both on the same GO. E.g. there is one that converts an interaction component and one that manages the icon that should show for the interaction
Iβm probably missing something insanely simple π
first how do you want to interact with your entity?
as i guess i dont understand what youre trying to do
Oh so I have a component that has data like radius, lengthOfPress etc.
I have a system which checks if the player is in radius and sets a bool to true. Iβm reading that bool in a MB for the HUD icon which is on the original GO for the interaction and then if the bool is true Iβm displaying a sprite over the entity
noise functions in Unity.Mathematics seems to go negative, do anyone know what's the range supposed to be? Is it supposed to be [-1,1]
So basically displaying an interaction prompt over an entity if player is in range @safe lintel
ok so in the monobehaviour that converts the component, can you not just use GetComponent to tell the other monobehaviour what the entity is for future reference?
I'm trying to convert my old DOTS Training system (using IJobForEach) to the more modern way (IJobChunk) but the results are far from the same. Can someone tell me what's wrong with my "Chunk conversion"? https://hastebin.com/jejecebuju.csharp
Somehow I have NaNs creep in....
// physicsVelocity.ApplyAngularImpulse(physicsMass, angularImpulse);
physicsVelocity.ApplyAngularImpulse(physicsMass, 1);
making them spin in circles at a fixed rate seems just fine
Okay, I figured it out, the problem was "BoneMatrices boneMatrices = allBoneMatrices[index];"
Logging angularImpulse doesn't seem to have any sort of crazy values
That needs to be: New BoneMatrices() and assign it at the end of the loop: allBoneMatrices[index] = boneMatrices;
For those who find this later on. When writing in IJobChunk, you have to assign it to the array, not a variable.
And here's the kicker... I change it to
physicsVelocity.ApplyAngularImpulse(physicsMass, 0);
and boom, it blows up again...
Oh, back on my point (sorry) boneMatrices is an unsafe array, itself.
I can't help you, I'm just posting so someone else might find my problem later.
Works:
physicsVelocity.ApplyAngularImpulse(physicsMass, 0.00001f);
that's some crazy shit... @safe lintel
hm, so it appears it's something with the inverseinertia settings
this used to be the way to lock rotation for bodies:
public void Convert(Entity entity, EntityManager entityManager, GameObjectConversionSystem gameObjectConversionSystem) {
if (entityManager.HasComponent<PhysicsMass>(entity)) {
var physicsMass = entityManager.GetComponentData<PhysicsMass>(entity);
physicsMass.InverseInertia[0] = LockX ? 0 : physicsMass.InverseInertia[0];
physicsMass.InverseInertia[1] = LockY ? 0 : physicsMass.InverseInertia[1];
physicsMass.InverseInertia[2] = LockZ ? 0 : physicsMass.InverseInertia[2];
entityManager.SetComponentData(entity, physicsMass);
}
}
When I set the "locked" inverse inertia to something small like 0.000001f instead of 0, things work fine again.
public static void ApplyAngularImpulse(ref this PhysicsVelocity velocityData, in PhysicsMass massData, in float3 impulse)
{
velocityData.Angular += impulse * massData.InverseInertia;
}
public float InverseMass; // zero is allowed, for infinite mass
π€·
maybe it also has to do with the fact that physics run on fixed step since 0.5.0... and maybe previously I was lucky to have had the right dependencies that it never was an issue π€
So many questions... so few answers I have π
Makes me wonder if my units will topple over veeeeery slowly π
@spark glade Are you trying to lock the entities rotation? I've been trying to do the same thing but haven't gotten it to work very well.
Above method of setting inverse intertia to 0 worked until 0.4.1, but with 0.5.0 there appear to be some issues π€·
I'll ask around in the forums tomorrow
then if i remove one entity, new entity using free index?
How would I set specific indexes of a buffer in a parallel job? This doesn't work in parallel it seems.
The next index will most likely not use it (think of the overhead of constantly checking for that), but once you fill, or nearly fill the available indexes,I assume it would calculate which indices are free, and make those available.
So keep a public Entity in the mono behaviour and then set it from the conversion mono behaviour. Sounds reasonable
then i should create and delete many entities or not? i want create a server that is up more than one day. i need stable server.
You probably don't need to worry about it, is my point.
But if you want to make super-duper sure, make a script which makes empty entities in parallel, something like 10k each frame, and deletes them all every few frames. Then just let it run for a while and see what happens.
I have a gamemanager singleton which holds a reference to a player entity. What is the appropriate way to get the component data from that entity from within a system. My system is currently running a ForEach and not on entities which have the "player" component
Why does the singleton hold the entity reference? (What is it used for?) (like for example hybrid code)
is this a class, or an singleton Entity/component?
(Protip: You can create singleton components. Protip2: Entity is a struct and works in components)
Currently I have a GameManager class thatβs a singleton which holds reference to key entities so that can be read in mono behaviours and systems.
Entity which has the playerComponent is one such entity that Iβm keeping in there.
Iβm not sure I understand the implication of your pro tips, sorry! (Still a newb when it comes to these patterns)
Given that you're doing hybrid code it's perfectly fine to store the Entity in in a MonoBehavior. The protips are more if you're doing pure ECS (or as pure as in reasonable to do at the moment).
The patterns for that would be:
-If you only need the reference in one system, just use a field on the system (ie. System.PlayerEntity). You could also scale this up for multiple systems(easy and reliable)
-Or you could create a singleton component which holds the player reference, and query for this as needed (a bit more cumbersome, need to decide which system gets to create the singleton, probably want to store it to the system, etc.)
Of those two general methods, #1 is definitely the easiest, but there are use-cases where it is not feasible.
For example, if the player is created "some time" during runtime, and you can't easily query for it (for example if the player archetype("sum" of components) is not unique), you would probably want whatever system spawns the player also create a singleton component with a reference to the new entity.
What are the situations where JOBs + Burst + Mono are greatly out performed by JOBs + Burst + EntitySystem
its not clear to me the expected order of magnitude difference and where this difference becomes most pronounced.
The only case where that would happen is if the overhead of the system and queries is higher than the overhead of the MB stuff.
The systems have a "static" overhead and scales extremely well, where that is not the case with MBs.
If most heavy code is in burst jobs you should have pretty dang good perf either way, though.
Hmm ok, I mean I can layout the relevant MB classes in a data-originated manner to help with this I assume.
If you're not sure whether to go for ECS or MB, I recommend going for MBs, unless you specifically want to learn/experiment with ECS, of course.
The general route I would suggest is:
-Write code as normal in MBs.
-When you have code you think is heavy, profile to verify - you might be wrong. Be sure to profile at a light load, but also at the highest expected normal load (for example max enemies in play at once)
-When you have code you know is heavy, extract it to jobs. The burstify and parallelize as possible/necessary.
understood, for my current project I am thinking of staying away from EntityComp entirely, but using Jobs+Burst where it make sense.
Of course, it heavily depends on the specific use case. If you want a LOT of things, and a lot of stuff happening to those things, ECS should be better
Awesome tips thank you! Given that Iβm going hybrid (because Iβm using a spriteComponent) do you have any tips about how to get the component data from an entity within a system that the component isnβt part of the JobForEach?
I assume I am precluded from doing any Physx related stuff in jobs since its not written for it.
i.e. I cannot accelerate raycasts
What's the general magnitude of "things" (objects/entities) you thing will exist at once?
And generally speaking, how much logic will they have (how many individual mechanics/systems will apply to them) ?
DOTS physics has raycasts, but I doubt you could extract GameObject raycasts for perf, no.
My game is an open world game, with a fair amount of procedural events and a lot of dynamic objects (player building system, large interconnected inventory systems, complex resource / entity spawning system).
So updating world state for a number of these things will be good to get off the main thread.
Buildings will probably be more or less inert, I assume (collision, maybe something like a furnace (level of complexity like minecraft furnace, maybe a bit higher, like MC modded basic tech mods))
Also there will be quite a few entities that need transforms
well buildings do need to update stability states and the buildings structures can be fairly complex, but ya these events wont be often but heavy when they happen.
Pretty much one-off, side-thread jobs, then
Probably wouldn't matter much if they skip a couple frames, too
If you're talking about something like Don't Starve or even 3D like ARK, I seriously doubt you're gonna get perf issues if you build the architecture well and use parallel, bursted, jobs.
also the game will have ALOT of active combat related traps, projectiles, triggers etc... that will need a lot of updates/checking.
Hod ya that is the plan
...are you also planning on multiplayer?
of course π
Brave. I really hope you have a few games under your belt, including at least one (even simple) multiplayer game
brave indeed. Nothing at this scale, pushing personal boundries =). My last project has about 200k users. Supporting 32 simultaneous players controlling up to a few thousand multiplayer objects. Wasn't in unity and I had to write the netcode and physics myself so in someways things are easier =).
This project is not just me tho
If you're familiar with netcode at that level, it sounds like at least networking (probably) won't be a killer in this project
Well, "you" here being the collective team
Ya my plan was to modify MLAPI for my needs. But with the recent announcement I may have less/nothing to modify by the time I release.
jobs/burst also makes things a lot easier as I dont need to do my own low level threading infrastructure.
There's some guidelines for that, I'm sure you can find them, but it boils down to "short term, keep using the existing stuff, but if you're not gonna release in a few years, don't get too fond of the current implementation"
yup thats the thinking. Feature wise I am targeting 2021 LTS most likely.
If I have system A which takes data A and outputs data B and system B which takes in data B and outputs data C does that mean to see the effects of changing A on C I need to wait 2 frames?
dumb question here, entity worlds aren't erased on scene load right?
Is DOTS only suited for games that have a high amount of scripted characters? What about an open world game?
All the examples I'm seeing is "look how many entities I can have doing things on one screen"
well technically dots isnt suited towards much given its current state. dots is really solving the problems of performance and data management, so the easiest things to showcase are instances where there are many things on screen to show the benefits. why bother showcasing something with just a handful of things if gameobjects already covers that? it wouldnt make for a sexy marketing demo.
Right - I'm just trying to figure out if the system is better suited to particular genres or if it's more of a question of your programming skills (indie vs AAA). It would seem to be most beneficial in RTS games for instance but something like a 3d platformerer... the physics and rendering might be a bit faster but is this significant or is it generally not going to do much for 3d platformerer type games.
Basically is it something everyone should be looking into and questioning if it will be useful to them...or only for certain games
I wouldβve thought that itβd be very useful in an Open World game. If you have a big world you have lots of entities.
I highly highly suggest not counting on anything unity is bringing out in the future, build using what you have in your hands now. not what they will have by the time you get to it (like the MLAPI). architecting up front helps keep the project sane and on track, you know this. @valid haven
June I have access to MLAPI, so I am using the open source version for now
make sure you evaluate that its good enough for your needs now is all I'm saying
dont count on future updates to it
alright, just be mindful of that extra burden
understood
experimental / new tools come at a cost to the project, too many and the project wont be finished
having reviewed the various public unity netcode stacks at a source level MLAPI is really the only one I am willing to use
all AAA engines at this point include a task/job system, and unity's job system + burst is quite stable and 100% ready for use. I suggest to most people to just get started with that and not touch UECS yet
ya I am on the same page. Would like to use Jobs/Burst but am saying away from ecs
after using it for two years, Its only just now starting to become possible to finish complex games with it. lots of baggage with that statement though
yup, at this point I think its in a good enough state where its worth not writing my own thread pools and what not =).
that and burst creates some quite good results
if you have questions, sometimes people can help here with it
π
Awesome tips thank you! Given that Iβm going hybrid (because Iβm using a spriteComponent) do you have any tips about how to get the component data from an entity within a system that the component isnβt part of the JobForEach?
@rare umbra
Usually you would get the first entity via a query on the main thread or a separate job then pass it into the foreach
Or that's how I would do it at least
I'm struggling with this a bit - are you able to point me towards a sample?
var tar = new NativeReference<Entity>(Allocator.TempJob);
Entities.ForEach((Entity e, in Whatever whatever)=>{
// Get your entity, assign it to your nativereference
}).Schedule;
// schedule new job, pass in NativeReference ( and remember to dispose it after)
Sorry I'm at work on my phone, best I could do
If you don't need this to be done in jobs you don't even need the nativereference, just use a normal entity and use .Run on your jobs
yeah I just need to grab it before I do Entities.ForEach and pass it in
Then you can just call GetComponent on the entity reference to get your data
Wanted to share how my find nearest algorithm stuff is going, I added some visualization to make it easier to see what's happening. I have yet to implement checking neighboring grids and max radius. ~11000 entities https://gyazo.com/d0c87cd7b0441ad0200f259e84f5a0fa
I still have a problem where the entities are rotating, trying to suppress that but there's no easy way to do so it seems.
it runs at about ~90 fps in editor (although that is with quite a lot of additional systems and the drawing)
Woo nice!
Grr Iβm having a frustrating issue where each second OnUpdate of my system I get a null reference exception when trying to GetComponentData.
No idea why it works half of the time and other half it doesnβt. The entity is cached in a private Entity OnStart and then referenced in each OnUpdate
I think I could probably do a null check but Iβd really like to know why this is happening
Not sure how to debug :/
Ln 25
ok, so it's actually failinng every time methinks.
Translation playerTranslation = EntityManager.GetComponentData<Translation>(playerEntity);
This seems to work!
https://hastebin.com/mahoqowihi.csharp
@rare umbra
Start isn't a thing in systems. You want OnCreate
doh!
even so, if I use this OnUpdate it doesn't work:
manager = World.DefaultGameObjectInjectionWorld.EntityManager;
You should go through the ECS samples from the pinned messages. They are well documented and will help you a lot I think
cool, will do thanks @zenith wyvern It's also been a few years since I've written c# in Unity so I'm all round rusty
ok, perfect - works like a charm now
btw does the new input system play nice with ECS? or are we still waiting on that?
it works fine, but its not ecs native
I guess you have to use MBs with it since itβs invoking messages or callbacks. Wish it was able to create components containing button press event data
you can do just that
monobehaviour setups the input callbacks and stuffs whatever data into a new entity
mine thread access of the entity manager is fine
Yeah makes sense though feels quite long winded. Thinking about just using MBs instead of systems to handle any reactions to input
you can use it directly in a system without monobehaviours
its more elegant than using a monobehaviour imo, theres an example in the physics samples of how its setup
they have integrated a unity'style ECS for animation calculation in Sequencer (cinematic tool)
Interesting
tho what is the funniest is this
recode literally the entire animation runtime into data-oriented ECS paradigm for highly parallel and uberfast
inmediately bottleneck on the crappy OOP overhead of the scenenode system
they could have gotten a better gain if they tried to do delayed-transform or similar to improve SetActorTransform cost
I can't work with subscenes anymore, and have no idea what causes it:
Loading Entity Scene failed because the entity header file couldn't be resolved. This might be caused by a failed import of the entity scene. Please take a look at the SubScene MonoBehaviour that references this scene or at the asset import worker log in C:\Projects\protojovian\Logs. scenePath=Assets/Scenes/Jupiter/FloatingOriginTest.unity guid=d1fcf33267b30a947851aa73f06c77c7
UnityEngine.Debug:LogError (object)
Unity.Debug:LogError (object) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/Stubs/Unity/Debug.cs:13)
Unity.Scenes.ResolveSceneSectionUtility:ResolveSceneSections (Unity.Entities.EntityManager,Unity.Entities.Entity,Unity.Entities.Hash128,Unity.Entities.RequestSceneLoaded,Unity.Entities.Hash128) (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Scenes/ResolveSceneSectionUtility.cs:76)
Unity.Scenes.ResolveSceneReferenceSystem:OnUpdate () (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Scenes/ResolveSceneReferenceSystem.cs:174)
Unity.Entities.SystemBase:Update () (at ... )
Unity.Entities.ComponentSystem:Update () (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ComponentSystem.cs:113)
Unity.Entities.ScriptBehaviourUpdateOrder/DummyDelegateWrapper:TriggerUpdate () (at Library/PackageCache/com.unity.entities@0.16.0-preview.21/Unity.Entities/ScriptBehaviourUpdateOrder.cs:333)
The message also refers me to a log file, the most prominent issue there appears to be this one:
System.IO.FileNotFoundException: Could not load file or assembly 'Unity.Burst.Unsafe, Version=4.0.5.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies.
The error occurs whenever I try to deserialize a subscene, i.e. when unchecking it in the hierarchy (unity 2020.2), or when running the game.
Did you check the import log out?
Yes.
It's the 2nd block.
Could not load file or assembly 'Unity.Burst.Unsafe
I reset all the packages, tried several burst versions, used my own and the original version of unity physics...
Tried it in an empty scene with fresh subscenes... to no avail.
What I am trying now is to somehow stop a lot of my code from compiling (wow I wish there was a checkbox to just remove a file temporarily...) to see whether it's maybe a circular dependency in physics or so, but that usually gets caught.
Ok I gutted my project and took out almost all ECS code. It still doesn't work.
Pretty close to starting from a new template but this is awful.
Well it doesn't occur in unity 2021.1 alpha... ugh.
I really don't want to go there π
In here somewhere? https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/UnityPhysicsSamples/Assets/Demos
Is there something wrong with the Entity Debugger, its showing different numbers of entities?
I did an EntityQuery.CalculateEntityCount() and it says 100 entitys of that type and yet in the debugger it shows 200
Queries will ignore entities with "Prefab" or "Disabled" components unless you explicitly include them, maybe that's why?
yeah I know you can end up with copies with prefabs and things like that
but I have a list of 200 entities which all have the exact same data
well like entity 12 has the same data as 111 and so on
like they've been copied twice
I'm creating the entity's purely in code also
This seems amazingly simple, thank you! Iβll give it a try this evening
So I guess if the βDefaultβ scheme is not active then isTriggered is false, even if that button is pressed?
Correct
I just realised I am copying the data using ToComponentDataArray<CellData>(Allocator.Persistent); in a monobehaviour, would that maybe show up as extra data in the entity debugger π€
I wouldn't think so, I thought that would just create a nativearray of structs, not entities
Could be wrong
yeah maybe its just a weird bug
If I want to find the lowest value of a variable on all components of type T and return the component data for that variable, do I have to do this via looping through a ForEach and caching the lowest one? Or is there a better way?
You have to loop through and assign it to a container. Native containers/NativeReference are the only way to get data out of a job
You can also use entityQuery.ToComponentDataArray<T> to easily get a copy of all your components then pass that into the next job
So would it be recommended to use standard OOP to create Characters, PlayerCharacters, and NPCharacters and then have NPCharacters be converted to Entities as opposed to using ECS for everything?
Because I'm thinking for the player, we don't really need ECS because there's only 1 player so his affect on performance will be minimal
but would it be less confusing to use ECS for everything?
definitely would be less confusing to keep things mostly in one area or the other. if you havent already tried it out id suggest you experiment with a mecanim animated char interacting with a pure entity and see what your tolerance for the back and forth communication that is involved with that.
all of my npcs are hybrid gameobjects with animators and also some pure ecs data, but my player is a pure ecs entity. tbh i cant wait to drop monobehaviour stuff as soon as possible for the majority of things except in cases like ui where its mostly minimal
I never liked the whole monobehavior stuff. Too many different scripts all forcing themselves on one another with complex gameobjects
But ECS is strange - just getting started with it
It definitely seems to be the way to go when you have large amounts of the same thing, but when you have a singleton-style class like the player...its odd
Does anyone know how you would prevent entities from falling over? I've tried doing physicsMass.InverseInertia = float3.zero; every update, it somewhat works but they occasionally still fall over and rotate very slowly.
you can set the velocity
I'm not sure what you mean, the physicsVelocity component?
I'm already doing that for movement but it's not great
or you mean angular velocity?
actually maybe the rotation component makes more sense here?
I guess I could constantly reset that variable to float4.zero?
though I'm not sure what the 4th value in the float4 means
actually new quaternion(0, 0, 0, 1); seems to work better.
yeah that seems to work way better than doing physicsMass.InverseInertia = float3.zero;, I don't see any rotating entities anymore :p
yeah i think float4.zero is an invalid rotation, i remember weird stuff when i was doing that
mhm, it gave some weird errors, that quaternion works though.
So I did this tutorial:
https://www.raywenderlich.com/7630142-entity-component-system-for-unity-getting-started
Granted, it doesn't take advantage of the jobs system OR the burst compiler...
However....
My non-ecs scene took about 80 seconds to reach 60 FPS
My ECS scene took about 45 seconds to reach 60 FPS.
So....the non-ecs was almost twice as efficient. Is this normal? I do have a 32 thread CPU w/ 64GB of RAM so maybe that screws up the performance advantage???
Again, I know the real performance advantage comes w/ burst and jobs but I find it curious that ECS is almost 2x less efficient
if you disable the jobs in Jobs>use job threads, do you get better performance?
scheduling jobs has its own overhead and for low amounts of work you might get worse perf if you are scheduling everything as parallel jobs vs a single job thread or just mainthread.
The tutorial did not include jobs
So all the code is single threaded
Not claiming that DOTS is slower than Monobehvaiors as a whole, but it's interesting to me that on some hardware, ECS (w/o jobs and burst) can be up to twice as slow as a monobehavior approach. So makes me wonder if what you're doing can't really take advantage of the jobs system (say its a singleton and all the behaviors can't be split into a multithreaded workload), it may be more efficient to use the standard monobehavior approach
Though if I had to guess, I would imagine converting gameobjects to entities (Hybrid ECS) which this one does for every "drone enemy" has a performance cost and may be the culprit.
We've been seeing the devs show off DOTS in applications where DOTS is most advantageous over the traditional monobehavior scripts, but I wonder what the performance gain (or potentially, loss) would be in applications where DOTS is least advantageous
Performance isnβt the only reason to use DOTS though. It has some really nice data oriented programming paradigms. As a gameplay systems designer the way DOTS works is how I think about my game entities. Inputs, processes and outputs. Itβs very pure.
For me this is enough reason to use it and also figure out some headaches with hybrid where necessary
Yea - I'm just not sure what the dev's vision for DOTS is. Are they putting up Hybrid ECS as the defacto standard for DOTS or are they going to push along a pure ECS option. Right now, can we even serialize entity data without Hybrid ECS? And I don't believe we are able to place entities directly in the scene
One of the reasons to use ECS is that it better takes advantage of Job system and Burst though
As I see it, most issues of ECS stems from this whole conversion workflow.
Yea - my concern is that it may turn out that ECS is only advantageous in applications that take advantage of the jobs system and burst. And not all applications do. Theoretically, it should be advantageous in all scenarios but if the conversion process is responsible for my decreased performance on that tutorial...programmers may need to sort out which applications are suitable for DOTS and which are suitable for Monobehavior - not use one for everything.
If Unity was to be rebuilt from the ground up (unrealistic) with ECS I don't think things would be nearly as chaotic as they are now.
im skeptical of a 50% reduction in performance even without multithreading
does this have two final projects to compare with? as i cant really be bothered to actually walk through it
I believe it has a final project in the download
also does the tutorial mention that there is a large performance delta between mono/dots and dots being lesser of the two?
And then there's two scenes, one with ECS and one without
The tutorial author responded to another comment of someone else saying they got slower performance with "Well it shouldn't"
So I'm not sure if it depends on the user's hardware or if the tutorial author simply didn't test it and made assumptions that it would be faster
Either way, the author is under the impression that using ECS will result in performance gains, not losses
alright will check it out in a bit
Just gonna point out that ECS does not automagically give you more perf. It's complicated, as always. Any number of hardware, firmware, and even software differences can change up results.
Either way, where DOTS excel is:
-When many things do many things
-And you let it parallelize
If one or none of those fit (you already said no parallelism), you might have better perf using GameObjects and MonoBehaviors.
Of course, a simple project does not give you much meaningful information compared to a real project, with a real, complicated use case.
Burst also gives good performance boost in single thread.
Right, and if it didn't increase performance I wouldn't be concerned. My concern is that it seemed to heavily decrease performance. Thus, I wonder if we should all be steering clear of pure-ECS projects and instead think of ECS as something we should only consider using when we would expect it to have a noticibly positive impact on performance
IE the physics system would benefit heavily from DOTS, a button that opens a door would probably not. Use Unity's new physics DOTS system for the physics but use monobehaviors for the door and button
To be fair, I am not very familiar with the burst compiler so that aspect of DOTS is not something I've really explored in detail
My argument for ECS is that, projects that are big enough to worry about performance are usually the ones that fit the "many things do many things" point and can gain significant performance, and the others shouldn't have performance issue to begin with, even if ECS did have a performance penalty (who cares if your cookie clicker game runs at 300 FPS instead of 400)
If you have an existing project, or even if you're making a new one, my recommendation at the current time is not to go for the full DOTS and ECS, but rather to jobify and burstify particularly heavy code.
That should give you a decent chunk of the potential performance gains while being familiar(assuming you already know your way with GameObjects), and also not having the gaping holes for certain features like ECS does.
The exceptions are if you want to learn/play around with ECS, or if the paradigms/design patterns sound themselves sound useful to you.
That seems to be my thinking at this time @tawdry tree.
Is it true that ECS canβt serialize component data? Given that theyβre just structs?
What do you mean ECS can't serialize component data?
Well if you're using hybrid ECS you can serialize the data on the gameobject before runtime and at runtime it is converted into an entity. I'm not seeing a way to serialize data on a pure entity that was never a gameobject
I was just quoting what @gusty comet said
You can totally get all the components on an entity and serialize that. Or for that matter, I'm pretty sure there are some way to basically serialize an entire World to save it.
Easily though? I'm not talking about serializing data on a [GenerateAuthoringComponent] that is then added to a gameobject. Of course that can be easily serialized
You're gonna need to write some infrastructure code to do it, but entities are just containers of components, so it stands to reason you could grab all components an an entity and serialize that.
The harder/more complex part would likely be deserialization and spawning them back in...
Right - I just meant there was no equivalent to [SerializeField] for a PURE entity
So if you have serialized fields and don't want to write custom serialize functionality, you kinda have to use hybrid ecs over pure ecs
As long as they're properties you can just use standard .NET features, can't you? [Serializable] on the struct itself, and all data as properties with public { get; set; }
I suppose - to be honest I'm not too familiar with .NET - I'm more of a C++ guy
C# comes pretty easy from a syntax standpoint from C++
The C family of languages are all fairly similar
My point is more that components are just structs.
And structs can be serialized.
Does the convert and inject gameobject make a reference to the gameobject property in the entity?
The GO keeps a ref to the Entity, but i don't think the opposite is true
I know you can get the Go from an entity, though
Interesting - that seems like that may be what I need. I could make enemy entities but also have the player be both an entity and a player so I can run code that is common between enemies and the player through ECS but still be able to throw on monobehaviors to the player for player-specific tasks, correct?
Sounds like it might be easier to just have the player logic in ECS, but yes, that should be possible.
(assuming I understand correctly - you want player to be hybrid to let common Player/Enemy logic apply to it, but primarily be a GO for MB)
well so basically, I'm thinking that things like raycasting to check whether characters are on the ground or not could be done through a System on the player and NPCs. This could be split off into several threads to improve performance if I have thousands of characters constantly raycasting to update their distance to a floor. Things like health regeneration (assuming all my characters regenerate health over time), could also be done through ECS w/ multithreading. However, things like the player picking up an item, wouldn't necessarily benefit from multitasking so why run that through a system
Short answer: Because it's easier to keep things pure ECS.
Longer answer: if you did that you'd make it singlethreaded and the system would be very basic, doing none of the +perf things
With easier I here mean easier to understand the logic, keep track of things, etc, and you don't have the mental overhead of the GO side of things. Potentially less code, and what code you have is more similar.
Thinking about it further....my lack of performance on that tutorial cannot be blamed on Hybrid ECS converting gameobjects to entities. Because #1 this is only done once on the prefab and then it spawns entities from an entityprefab so there's only one conversion per wave spawned and #2 the performance drop is based on the number of entities performing tasks vs the number of gameobjects performing the same tasks (though written through monobehaviors). It's not like I'm getting lagspikes on new waves
So, I have no idea why I would get less performance with a large set of entities vs a large set of gameobjects, when not using burst and jobs
@gusty comet youβre working on an open world game, right? Best optimization would be to use a loading ring π
π
All I can think of is that looping through all of your entities searching for ones that contain certain parameters and/or tags on several different systems is just not efficient in a singlethreaded scenario. The alternative, monobehavior, way simply calls the update() function on every game object every frame - there's no conditional check to see what it's parameters are and you're not performing this check multiple times per frame for each implementation
I know the developer of Factorio tried to convert his project to use ECS entities one time and did not see a positive performance impact
ok some things
first of all, i commented out the FXManager createexplosion code for both ecs and non ecs and just did a quick build of each scene, both pretty much the same fps in a build. entities has overhead in the editor that you cant disable so checking perf in a build is the best way to measure performance(not sure if you did that).
second, that version of entities is pretty old and using ComponentSystem which is deprecated now. theres no burst usage at all in the project(but it is used by hybridrenderer and inside the project) which is really like the second part of the wombo combo of what gives dots its performance(the third being jobs).
Any guess when the next entities version will drop? I'm really looking forward to burstable systems. Did any of you already try the itnernal ISystemState out? I ported one of my systems that runs in client prediction to it and the performance gains were crazy (from 0.5ms to 0.06ms)
seems like they release something every 2ish months? iirc joachim mentioned q4 for next release
burstable systems? π€
@safe lintel Interesting - I would update the discord's wiki then to not recommend this tutorial if ComponentSystem is depreciated
Whoever is in charge of that π
What's a space efficient "bit flag" data type i can use in IComponentData? Basically want a couple bools, like "attacking", "idle", "death", "charge" and not use 6 actual bools.
I could roll my own ofc, but wondering if there's something off the shelf
@gusty comet i think the two guys who wrote the majority up stopped working with dots π there are some bits of that wiki that i disagree with but im a bit too lazy/passive to bother changing. you are free to edit it though, should be open to changes
Yeah that wiki is a bit weird. Strange tone for a wiki. The best resource for learning by far imo it the ECS samples and manual
agreed, it can be self loathing and a bit adversarial lol
(though those things do kind of go hand in hand with my experiences)
Fair
@spark glade use an enum with bit values and a int64 ?
wikis are meant to be written neutral without agenda
What's the difference between AddInputDependency and AddInputDependencyToComplete in BuildPhysicsWorld (DOTS Physics 0.51-2)?
I have a set of systems that must run before or after Physics, but not during.
I thought I do it as follows:
protected override void OnUpdate()
{
Dependency = Entities.ForEach((ref Translation translation, in FloatingPosition floating) =>
{
translation.Value = (float3) (floating.position / Scale);
}
).ScheduleParallel(Dependency);
buildPhysicsWorldSystem.AddInputDependency(Dependency);
}
But that throws:
(also, is this the old problem of dependencies, even in fixed time step simuulation system group, overlapping frame boundaries if you don't also build a dependency from the end back to the BuildPhysicsWorld?)
I really, REALLY struggle to understand this dependency management. I really want to run a system after another system is finished, and only then. (and I guess I don't want that first system to not start again before the other is finished)
protected override void OnUpdate()
{
Dependency = JobHandle.CombineDependencies(endFramePhysicsSystem.GetOutputDependency(), Dependency);
Dependency = Entities.ForEach((ref Translation translation, in FloatingPosition floating) =>
{
translation.Value = (float3) (floating.position / Scale);
}
).ScheduleParallel(Dependency);
buildPhysicsWorldSystem.AddInputDependency(Dependency);
}
This doesn't solve my problem at all though.
A possibility is - I'd say they should run between EndFramePhysicsSystem and EndFixedStepSimulationEntityCommandBufferSystem but I have not the slightest idea how to do this. (a good primer on the way these magical dependencies are supposed to work would be really helpful - I can't glimpse it one bit from the documentation, which is odd, what am I missing here?) Also, the ECBS doesn't even have input dependencies... how does THAT know when it can run and when it cannot?
(between ExportPhysicsWorldSystem and EndFramePhysicsSystem is also an option)
But... that gives me, with this code:
protected override void OnUpdate()
{
Dependency = JobHandle.CombineDependencies(exportPhysicsWorldSystem.GetOutputDependency(), Dependency);
Dependency = Entities.ForEach((ref Translation translation, in FloatingPosition floating) =>
{
translation.Value = (float3) (floating.position / Scale);
}
).ScheduleParallel(Dependency);
endFramePhysicsSystem.AddInputDependency(Dependency);
}
What am I getting wrong, I read this code as:
- this system's job has a dependency on the output of
ExportPhysicsWorldSystem, meaning it will run not before Export Physics World is complete. EndFramePhysicsSystemis dependent on the output of this system's job, meaning it won't run before that's completed.EndFramePhysicsSysteminforms (in its own OnUpdate) BuildPhysicsWorld that it can't start before it is completed.
So where's the gap in my logic?
[UpdateAfter(typeof(ExportPhysicsWorld))]
...
[UpdateBefore(typeof(BuildPhysicsWorld))]
So I guess we still need those, regardless of job dependencies? Why? And why can't this system express the dependencies that are needed, then? What does it actually express?
The Attributes are used to manage the order that OnUpdate gets called, the dependency stuff is to manage, well, the dependency
They are separated things, but yeah, in case of physics they usually are needed together
That stuff needs a visual editor. π
For sure haha
So when do I use BuildPhysicsWorld.AddInputDependencyToComplete() vs. the other one?
hey guys, i have an AI that uses raycasts to see. each AI does 5 raycasts. My project would slow down when i added alot of AI, so i decided to try out the jobs system to handle the raycasts. when i implimented it, it didnt improve my FPS at all, even though its using the new raycastcommand and job scheduler. any idea whats going wrong? (posting code soon)
its worth noting that the slowdown goes away when i comment out
JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
handle.Complete();
meaning the slowdown isnt coming from the data collection functions, just the raycasts themselves
You sure you want to complete right away ?
JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
handle.Complete();
that doesnt make sense to me, you're losing the batch scheduling
handle.complete() just waits until all the commands are done, no?
you're telling the job to execute immediately in this thread, thoug you asked for multithreading the line above.
Basically you're creating a sync point, the script will stop there and wait for the job to complete before executing the next line
well i want the job to finish before attempting to read the result array
You might want to have 2 systems maybe (didnt really read all the code because the textfile), one that's cast rays, another one that have a dep and reads results later
by later do you mean on a later frame?
i call the sight function every server tick
each ai does 5 raycasts to each of the players on the enemy team
so if there are 3 enemies, he will do 15 raycasts
I meant 2 jobs, not 2 systems sorry
the code tells each of the ai to do the first of the raycasts to each enemy. if the ai spots the enemy, it doesnt do the second raycast to that enemy and so on
let's say "CastVisionRaysJob", scheduled in parrallel, then a for example a "ReadVisionHits" Job, that have the first one as e dependency
so it would run async with the rest of the code?
i dont think i want to do that cause i need to call the sight function every tick
is the way im setting it up not using extra cpu threads?
with 20 AIs its doing about 1100 rays per tick
and 60 ticks per second
Hi guys, question with DOTS and camera's.
I'm working on a spaceship battle project, but I cant seem to implement a good chase camera without jitter.
I have tried to work with a ECS camera and run all movement system before the camera and a gameobject camera in late update, but I seem to have a constant jitter also when creating a build.
Does anyone have an idea of how to resolve jitter with a chasing camera in Dots?
How are you rotating the camera currently?
Like this:
Quaternion targetRot = entityManager.GetComponentData<Rotation>(entityTarget).Value;
transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, rotateSpeed * Time.deltaTime);
Try replacing Quaternion.Slerp with Quaternion.RotateTowards.
The third argument to slerp is "what percentage to move from current to target", not a rate.
The camera rotates a lot different, but the jitter still is just as present.
I did leave the third parameter the same as I also saw it being used like this in the Unity Documentation
Oh, that's weird. Is targetRot what you want the camera rotation to be or is it the rotation of some target entity that you want the camera to look at?
Yes, its the rotation of the target entity
Okay, so the transform here belongs to the camera and you're having it change its rotation to match the target entity's. Is that right?
Yes that is correct
Hmm, is the target entity's rotation jittery? The camera rotation could be jittery by proxy if the target entity isn't smoothly rotating.
So calling Complete() doesn't make the job run faster, like you've noticed it just stalls the thread until the job is finished. I think the issue is that you've buried this raycasting job inside a loop, so you're stalling the thread every iteration. What you want is to collect all RaycastCommands for all the AIs and then ScheduleBatch once. Ideally, you also jobify and schedule the entire dependency chain and defer calling complete on the final job until you need it (like Mr.K was saying).
How could i validate this?
It could indeed be that the problem lays there
I'd look at the profiler timeline view since it provides a rough idea of when the threads are executing, are the jobs running/completing while the main thread is idling?
@solar turret you're updating the cam rotation to match the entity rotation, but because you're updating the entity rotation value, the wanted rotation for the cam keeps getting changed. I would try to cache the targetRotation value in another var instead of being read directly from the component Value. maybe have the cam job updateAfter the entity one.
Are you able to place a camera on the target (or is the target the ship)? That'd probably be the easiest way to see it, but you could also try logging how much the target rotates every frame and check if that delta fluctuates unexpectedly.
If the target doesn't change and targetRot itself is being smoothly rotated by Slerp or RotateTowards, and you just want the camera to always match it perfectly, you could just set the camera rotation equal to that rotation.
Just tested it and yes, the target entity(in my case the spaceship) does jitter
turns out, the slowdown was from calling getcomponent() for every result
trygetcomponent(out c) fixed it
So if the camera never changes its target from the ship, one thing you could do is fix jitter on the ship (might be as simple as changing Slerp to RotateTowards) and then either 1) Set the camera's transform.rotation = targetRot (or vice-versa) or 2) Give the same target rotation to both the ship and the camera and have them independently rotate towards it (useful if you want them to rotate at different speeds).
Thanks that does seem like a good solution π I'll try them out!
I've asked this before but haven't found a solution yet, How would I access specific indexes of a buffer in a parallel job? Burst doesn't like it.
Yeah should only be able to write to Native Containers
But still you should be able to read
You tried to access index like an array ?
yeah like this buffer[0]
and how do you assign your DynamicBuffer ?
I do a loop on every entity in onstartrunning to add some to the buffer
arlight and at this point you set by index and tht works I assume
it's a IJobParallelFor ?
that's what doesn't work. But I've encountered a different problem. The loop I mentioned doesn't seem to work anymore..
hehe you might have tried tweaks and mixed things up
Maybe, adding a EntityCommandBuffer ParallelWriter to my update loop breaks the onstartrunning loop.
not sure how
you tried to add to the buffer after adding it to the ECB ?
I meant in another job, not after
You cant reach it in this case I think
until ECB executes
COuld be wrong I still get confused by those, not used them enough
Hm, I'll try a different way to do the loop. I imagine I can remove it and instead just use a Authoring Component.
Native Containers might be easier
just a little bit higher level
that might be easy enough :p
No, they have to be buffers.
what are you storing ? You said entities ?
I'm attempting to create a neural network, so I'm storing neurons in buffers.
inputs and outputs ? 0s and 1s ?
It's a bit more than that since each element in the buffer has an activation function and so on. Plus it's 3 buffers, one for inputs neurons, one for hidden neurons and one for output neurons.
It's quite complicated but it seems to work fine right now.
Dont know what type your T would be but do you Reinterpret<T>() to access your buffer ?
No
But I think I realized something. I'm pretty sure I'm not doing the correct entitycommandbuffer method to set a certain buffer element in a buffer.
I'm not sure what the correct one is, there might not be one?
ecb.AddBuffer<T>()
oh no thats not what you mean
let me re-read your sentence
xD
Im not even sure I understand what you're trying to achieve
but you should be able to .Add to your DynamicBuffer after .Reinterpret<T>()
and for IJobChunk it's different because you get all buffers (from all entities)
I guess I would be able to avoid using a commandbuffer then? I thought I'd have to use it.
Yes you have
?
that's true you add your buffer to the ecb
I'm not sure how that would work, Adding a buffer is not the same thing as changing a specific entry in a buffer. Not sure if we are on the same page or not lol.
its like asking the ecb to add/set/remove components on entities
you add your buffer to the ecb, then add to it or update it, then it will be resolved when the ecb executes
and I think you cant touch it anymore until that point
but you can copy values to a native container and use them in another job for example
but I dont know what's your use case is really
I hope I'm not confusing you :/
Hm, I'm not sure if we are talking about the same thing, if we are then I just don't understand. Are you talking about the start loop or the loop I have in update?
I figured out why the buffer was set to 0 because of the commandbuffer, I thought calling SetBuffer on it would somehow change it but it just sets it to a buffer with zero things in it, thats why I need to know a different way to set a specific entry in the buffer with a commandbuffer. If you understand what i mean.
Yeah SetBuffer is like a Clear() for lists
Mhm, for some reason I thought it wasn't. That was the problem I had but now it works fine except I need a different way to do what I want to do :p
That would still clear the buffer no?
One moment
It looks like this ```csharp
InputNeuronData data = inputNeuronData[0];
data.neuron.value = healthData.energy;
// update buffer?
I'm pretty sure I need to update the buffer atleast, lol.
the InputNeuronData buffercomponent consists of a Neuron struct.
public struct InputNeuronData : IBufferElementData
{
public float neuron;
}
Like that ?
Yes except that the neuron variable is not a float, rather a struct. Which is why the buffer itself needs to be updated.
I think... lol
I've had problems with me wanting to change the buffer and that creates problems because that foreach loop constantly edits it aswell. So I thought a commandbuffer would fix that.
but you can't write in parallel
only with .Run()
otherwise use a Job
yeah should be a referenec so you mutate values yeah
SOrry I really dont understand what you want to do. Not your fault. Mine. I slept only 5hours.
lol well, I'm not exactly sure on how to explain it further, I'm changing every entry in the buffer in my update method. And occasionally I want to edit that buffer from a different system as well, but that clashes with the other system.
make sure the second system executes after the first ?
and after the ecb
in the other job you use BufferFromEntity<T>() ?
Oh yeah, that makes sense, however I'm still not sure how to set one entry in a buffer in a ecb.
No it's a ForEach aswell.
with E.ForEach it's more simple, you can access the DynamicBuffer like a component, in your query, if the queried entities have the buffer on them
but yeah, only .Run()
with the ecb you can do it in parallel but you have to do it immediately
I would like to do it parallel, if possible.
Entities.ForEach( () => {
DynamicBuffer<InputNeuronData> buffer = yourECB.AddBuffer<InputNeuronData>(yourEntity);
DynamicBuffer<T> neurons = buffer.Reinterpret<T>();
neurons.Add(new ([...]));
}).ScheduleParallel(); // you can do parallel here
I would try smthg like this
Don't know if you can use struct for T, will there be a circular reference because it's a struct of struct ? Never tried π€·
Ah so you create a new buffer every update?
I dont know what you need but you can query .WithNone<InputNeuronData>
if you only need to add once
Interesting, I'll try it
Hopefully I understood what you need, sorry if not π
If the Reinterpet thing doesnt work, try to set directly buffer[i].neuron, I dont see why it wouldnt work as long as you do it in this lambda
Yep, it works, not exactly the way I was thinking of doing it but it does work.
Great
DynamicBuffer<InputNeuronData> buffer = ecb.SetBuffer<InputNeuronData>(0, entity);
DynamicBuffer<Neuron> neurons = buffer.Reinterpret<Neuron>();
neurons.Add(new Neuron(0, NeuronType.INPUT, ActivationFunction.LIN) { value = healthData.energy } );
neurons.Add(new Neuron(1, NeuronType.INPUT, ActivationFunction.LIN) { value = closestFoodDistance } );
It does make it so you have to recreate the neuron with the arguments and so on and it would be nice to avoid that but not sure if you can.
You mean yo already created them earlier and don't want to repeat them here ?
(So in the end you keep .SetBuffer to reset it)
Yeah that's what I have to do with how this works.
I only want to change the 'value' variable so recreating the entire thing every time seems like something you should be able to avoid?
I showcased .Add but you should be able to loop and assign a new .value at index i
or neurons.ElementAt(i).value
Ok so I misunderstood you ? I thought we were in the creation phase, the first time :/
Yeah that's what I thought you misunderstood :p
in the update method, but what you just said works great.
DynamicBuffer<Neuron> neurons = inputNeuronData.Reinterpret<Neuron>();
neurons.ElementAt(0).value = healthData.energy;
neurons.ElementAt(1).value = closestFoodDistance;
or the neurons are available in the query ?
This is very much what I was looking for.
ok great. I misunderstood again then, because I thought we were wiping the buffer and that was useless :p
Mhm
sorry to make it difficult :p
Nah it's fine, it took a while but eventually we got there :)
Now I'll just have to convert all my other code to use this instead..
Awesome, happy coding
Only just getting around to looking at this. Canβt find the Controls class. What namespace is it in? My rudimentary search of the docs didnβt find anything.
Yeah Iβm doing this
βusing UnityEngine.InputSystem;β
Finds the rest of the classes in the sample but not Controls
oh π€
Wondering if Controls is a custom class or if itβs part of that system because I canβt find references to it online
looks like a custom class
yeah maybe an helper class haha
could be the codegen class that input system can create from your input mapping
sounds legit
Ok so just need to figure out how to run the code gen for my input data π
when you do the mapping from the editor I assume ?
Aah cool will check it when the little one has gone to bed
I think I did see a project for input in VS
and that file is the actions asset - https://i.imgur.com/PXzTp5n.png
Yeah I have some actions defined, guess Iβm not doing codegen or I need to switch Controls with a class itβs actually generating
This seems incredibly long winded compared to what Sark wrote. Though I guess thatβs just because I donβt understand it π
its not so bad, though the new input system is definitely more complex than the previous one.
it will make sense when you dive into things π
I guess if my understanding is correct itβs registering a bunch of callbacks within the system and then each time a control input is updated it updates a local variable which is then used to set the data on a component?
yeah
Yeah donβt think I need to store that data on a component. I can just grab it each update of the system like in @zenith wyvernβs example
Not doing much yet that needs to simultaneously read that data
Yeah "Controls" is just the codegen class from the Actions asset. There should be some okayish documentation on how to use it
So in my example the "Controls" was the actions asset and "Default" was one of the action maps
@zenith wyvern thank you! turns out I wasn't generating the code - doh!. Seems to be working mostly... translation changes when I do +=1 but not so much when I change that to be a product of movespeed and delta time. Now trying to debug with break points, but they're not being hit. Is it possible that anything in a Entities.ForEach can't be debugged with breakpoints?
I don't think burst can be. If you use WithoutBurst it should work
Guys, i want to use ontriggerenter (player with sphere collider) to many object (dots collider) and destroy it, how to make collider but only a dot ?
@empty reef Don't cross post. I deleted the other one.
Yea sorry, i thought there's no dots channel :)
@zenith wyvern this is what I came to in the end with your help - thanks again!
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.
I guess I could wrap my OnUpdate code in a check of _controls.InGame.enabled
Animations are coming together: https://imgur.com/6zY4Iah
how do you create joints in dots unity physics?
@karmic basin I have a question about what we did yesterday, How would you make this work with monobehaviours? I want to have a button that adds something to a buffer but that clashes with the update loop that constantly changes the buffers. I suppose I could have the monobehaviour add a component to the entity and a system to run after the other system which updates on those components to add a buffer, somewhat like a queue. If you get what I mean.
So the systems never clash with each other.
Yeah you can access entities package from MBs (EntityManager, systems, queries, ...)
Straightest way would be through the EntityManager I guess. Grab a reference to your world's EntityManager + your Entity and then
DynamicBuffer<InputNeuronData> dynamicBuffer = EntityManager.GetBuffer<InputNeuronData>(entity);
But then yeah what about sync points... I never tried to mess with buffers in hybrid. You're right you might fall into race conditions so your idea of a queue component looks good. But I would not run it after the one that adds to the buffer, because between the adding part and the ECB (when it executes) you can't touch it. I would just add the queue component in the query lambda and add the Neurons at the same time you do the others. Or if really want to split to another system, use [UpdateAfter(typeof(yourECBSystem))] and not before
But that's strange you need to add from MBs AND from Systems
so you need to store them in 2 different ways, I don't like that, there might be a better solution I don't see yet
Thinking out loud here, you could also access a native container of your system from the MB instead of components, at least you dont mess with structural changes on your Entities
Got it π I'll try to do something like the queue thing I suggested.
hey guys i was wondering if theres any overhead with using the conversion workflow compared to just using dots normally?
performance overhead? Quite the opposite - conversion is designed to make everything a blob of data that can be loaded pretty much directly into ram
ahh ok thank you
Oh I should say, "conversion workflow" to me means at edit time. Conversion at runtime is generally something to avoid.
what would be better for 100s-1000s of projectiles? or does it not matter? so i could get away with just using conversion instead of using full on ecs/dots?
well if you just convert the projectile once (as it can be marked as a Prefab entity), you can reuse the entity projectile and instantiate 100s to a 1000s depending on your need
There is no conversion "instead" of dots. Setting up your entities in the editor using conversion is a part of dots.
Or a part of ECS I should say
similarly, you may not even need the whole conversion/Entities workflow, setting up a monobehaviour and using DrawMeshInstanced (or DrawMeshInstancedIndirect) to render the thousands of projectiles is also a feasible way too
The same as above put a slightly different way - once you've converted e.g. a bullet prefab, it becomes an optimised binary representation of that bullet - instantiating it is then as simple as a memcpy pretty much (plus consequential chunk activity) so it's pretty optimal.
How would you guys handle mutually exclusive components? E.g. some enemies have a RangedAttack component and some have a MeleeAttack. Is there any way to enforce an enemy to have only one of those or do I have to handle constraints like this through authoring components? In OOP I would have handled this through Polymorphism but this isnt a thing in ECS π€
Just have a Component with an Enum and set the enum (is how I would do it) - tags aren't supposed to be exclusive
yea - also split them into different chunks and have chunk based logic is another approach, so you enforce different enemies to have different archetypes
This could get pretty messy when having a lot of attack types wouldnt it? I feel like it would defeat most of ECSs advantages π€
it depends... π - on the one hand, it's better than tags because it doesn't fragment your entities so much.. on the other, you lose the query syntax and can't use that fragmentation to only iterate those specific entities
this state-machine esque question comes up a lot - there was a recent post on the forums if you want me to find it - there's also the Unity example but it only really applies for very simple states
sounds good. would be really glad if you could find it
its always tricky to decide whether to go for components or enums
