#archived-dots
1 messages ยท Page 84 of 1
However, I've noticed that the main thread system is painfully slow. It does nothing but retrieve the SharedComponentData, retrieve the usual components and just write to SharedComponentData's lists (which are reference types, hence no penalty for rebuilding).
I use Entities.ForEach and I suspect that the retrieval of the SCD is what causes an overhead. Hence, I want to ask this: how can I iterate over my entities and components under the same chunk sequentially chunk by chunk?
E.G. I want to get all entities and components that are chunked by their SCD and then iterate over every chunk and their components
perhaps you could use IJobChunk in combination with SetFilter for specific SCD values? SetFilter pretty much just does (if scd == value hash) so there's a trick @stiff skiff uses to make it a little faster but anyway... not sure how much that helps as I don't think I understand well what's slow atm
You can't use SCD and their values in jobs.
Perhaps that's too little info. I'll elaborate more when I'll get home to my pc
you filter before calling the job, then you know all chunks in that job have that SCD
@amber flicker thanks for the response, childcare duties are limiting my hours at the moment unfortunately but I'll try to get some code up later. I'm currently making the native multi hash map just fine in another class, but I'm not sure how to use the data I get out of it (ie the index corresponding to the entity from its IJobForEachWithEntity) subsequently. In my head it's a method where I give it these ints and the type I want and it gives me back a native array, but I don't think it works like that!
Alright, but as I stated before, I use lists to generate my mesh data. You can't access lists in jobs.
Can I reference to another (gameobject=>entity) within a prefab that will get converted?
You can use NativeList in jobs.
Mesh APIs do not yet support any Native containers and you can't copy nativelist data to list
Using arrays to operate on meshes is also not optional for me
But in the end, let's suppose that we have a chunk with an SCD that contains a nativelist. We inject that list into our jobs (somehow) and we can nicely write to it. However, what if our chunk got too big and it got split into two? Wouldn't that create a race condition where two jobs with their chunks write to the same nativelist?
Or do you say that if a chunk has SCD assigned then that chunk can get as big as it wants to?
Sorry @fringe sinew I can't follow what you're trying to do. An SCD that contains a nativelist? I'm lost.
And no, I searched for quite a bit and once again I don't think you can inject SCD into the jobs without a ton of hacks.
No, it was some other user that suggested using NativeList, but I replied that I can't
what's the canonical way to get the nearest set of components to a given position such that it's not necessary to iterate all of them every frame? I think I'm just getting mixed up because there's no clear examples showing all the different things you can do and the scenarios in which they make most sense.
You can build a spatial map
Okay
Or a tree of sorts and divide the area into regions
So I have currently a nativemultihashmap of a gridID and the entity index
I could switch it around so instead of the entity index, I store the float3 for the translation but I still can't see how to use that data after i've got it ๐ฆ
Well if you know you can get their position or know their positions
you can build some structural representation of how the entities are close together
i think if you're working in the 3D space, you might want to go for a spatial hash algorithm (I think going down the route of trees might be a bit annoying in a 3D space...)
My AtomGridUpdateSystem works a treat:
https://hatebin.com/jqokaofpgg
It's the next stage I'm struggling with:
https://hatebin.com/achcrqrimu
I put in the positions and scale as tests, before I only had the hashmap with the entityID as the values
but I'm flailing in the dark here ๐ฆ
how do you want to calculate the desired up axis?
I'll be averaging the vectors between the Translation.Value of interest and the nearest, say 5 atoms, factored by 1/sqDist between them
That bit is easy, it's getting the values in the same place I'm struggling with
@wary anchor at a cursory glance that code looks ok? Do you get errors when you uncomment the NOPE lines?
The values I get from those are NativeMultiHashMap<int3, float>.Enumerator and I have no idea how to get the actual values out
like you want to get the values out of the hashmap?
lemme google the docs on this type. I clearly should have tried that first
thanks for the help!
just try foreach( float3 val in atomPositionsTemp ) {};
can't foreach in a job tho : The try construction is not supported by burst
and I can't do for (int i = 0; i < atomPositionsTemp.Length; i++) because it's an Enumerator type that doesn't have the Length property.
hmm, how about GetKeyArray(Allocator) or GetValueArray(Allocator)?
doesn't that return the whole array instead of just the values for the key (gridID) I'm interested in?
var enumerator = atomPositionsTemp.GetEnumerator();
while (enumerator.MoveNext()) //enumer.Current;
something like that work in a Job? I haven't actually tried
ahha lemme give that a shot ty
there's also this though I havent used it in a job either ๐ค
Okay, I'll have a play around with these later, thanks both very much!
Gotta help kid find lego pieces and then gotta cook now ๐ฆ Booooooo
๐
good luck
on all fronts ๐
indeed
๐
I have this prefab that I spawn in by using the conversionsystem. Is it possible in this prefab beforehand from e.g. a child object reference a parent gameObject and have this reference converted into an entity reference later?
I am having an issue doing a barrel offset (place where bullets spawn) for my weapon entities. I am trying to avoid having a child entity and using its translation. I am trying to use a component instead. I store the offset value (weaponPosition - barrelPosition) and have the world position value for where it should spawn calculated in a job. Which is something like:
value = position.Value + (offset.worldPos * math.forward(rotation.value));
Any suggestions?
Should i be doing a calculation between direction and forward?
i think it should be childWorldPos = parentWorldPos + childLocalOffsetPos * directionNormalized. not sure what math.forward(rot) does, never used that.
Anyone know my question or can send me somewhere I might get an answer?
you mean just store an entity reference to an entity (which is a child gameobject that gets converted to an entity)?
Yeah. One object referencing another, which are both part of a prefab that is converted.
Nevermind, I think I found it. Just need to use GetPrimaryEntity on the reference gameobject
Its weird that there is no built in Random support for jobs
You can use Unity.Mathematics.Random(int) in jobs
I am using @tawdry tree post from May to replicate. I guess I just think it should be simpler. Like they should already do the seed for you, since they should be able to determine everything else
Lol. Unity.Mathematics.Random is essentially xorshift
^That
considering how verbose c#, Unity and ECS are, it's not surprising or inconsistent
@stuck saffron made an experiment that might help you . https://imgur.com/gNXTW65 https://gist.github.com/jeffvella/3d9f8f8982461ce9a47edb07ef7ce6eb
I want to reiterate a question.
Let's suppose that I have a chunk iteration in a jobified system.
I iterate over chunks, their components and chunk SCDs.
SCDs have native arrays on them.
Now here's the question: what will happen if my chunk will become very big? Will it be split up into two separate chunks? If so, wouldn't it cause a race condition because they write to the same native array?
i dont think nativearrays are intended to be used on any components, scd or not
Yes, I know. It's just a hypothetical question.
Hi, I am doing some work based off of the FPS Sample project, which is currently using ECS 0.0.12-preview.24. I was trying to update ECS to the latest version 0.1.1-preview, but I encountered one API changes that I'm unsure how to resolve.
I see that EntityQuery.GetEntityArray is gone and can be replaced with EntityQuery.ToEntityArray. Similarly, EntityQuery.GetComponentDataArray is gone and can be replaced with EntityQuery.ToComponentDataArray.
However, I also see that EntityQuery.GetComponentArray<T> is gone, but the compiler error does not suggest an alternative. Would it be correct/equivalent to replace this with EntityQuery.ToComponentArray<T>?
Also, the way ECS is used in the FPS Sample seems like maybe it is not very efficient compared to what's available in the latest - is anyone aware of learning resources to get up to speed with the latest or migrating from older API versions?
@fringe sinew I know it's hypothetical but just fyi, the idea of putting arrays in SCDs doesn't make much sense - every unique SCD gets a hash and all components with a certain hash will be considered (kind of) a separate archetype. A chunk can only ever have one SCD with a certain value associated with it. Sorry if this is all stuff you know but you might have more luck trying to approach the problem differently. What is the goal? To associate arrays of ? managed meshes? with certain entities?
@slow turret yeah ToComponentDataArray or ToComponentArray should be what you're looking for. i think if you just took a look at the latest samples and maybe breezed through the changelog for entities, you would get a good understanding of whats changed.
The goal of mine is to do mesh building on the fly. I have a set of entities and their components, each generating a quad in the multithreaded ECS space. The problem is that in order to build the mesh, I have to iterate over all the relevant components and write their quad datas in arrays that I'll need to then apply to the mesh object. This iteration needs to happen on the main thread and its cost adds up incredibly quickly as there are more components that contribute to the mesh. @amber flicker
One way that I thought of doing it is to get all the entities and their components in an SCD chunk and schedule a job for each of those chunks. Thus I ask: how do I efficiently get all the entities that are bound by a single SCD chunk?
Couldn't you use IJobForEachWithEntity<ComponentType, OtherComponentType etc > and output the quad info to an array form there?
AFAIK IJobForEachWithEntity also uses chunks under the hood. Same problem: you'll get race conditions if two jobs operate on two entities belonging to a single SCD chunk and hence write to the same nativearray
So to understand something with RenderMesh - because it's ISharedComponentData - if you have 100 entities (say units) - they all have to be the same mesh and material? You can't make each different? Change colors? Change textures?
What do you do if you have 10 units with identical components except you want the meshes + materials to be different?
Yes, exactly. My system understands each SCD as its own batch of quads. If I'll have to change something relevant about it (a different material, for example) it'll be a completely different SCD.
Oh wait.
I'm sorry, I thought you wanted to clarify my question.
No, sorry! It was a strange revelation
But yeah, if you'll need your entity to be represented as a different mesh or with a different material, then it'll need to be a whole other SCD afaik.
That seems.. limiting
How so?
@turbid sundial you can set the mesh and material for those entities individually, they will look identical to the others in EntityQuery (unless you filter the query by scd data), because they have the same component types on. The entities with different SCD data will internally be in separate chunks, though.
Ahh, that makes a lot more sense
I do this with atoms: though I share a sphere mesh, I change the colour based on element and also change the scale to match van de Waals radius
You change the colour via material?
So if RenderMesh struct contains both Mesh and Material, but is also ISharedComponentData, you can't just change the material and expect to get the same performance from the mesh being shared I assume? (Maybe a weird question)
I have different materials set for each element and when I create the entities, I set the scd RenderMesh.material to use each element's material there.
I think that means each element type is in its own chunk regardless of the shared mesh, but I'm sure the gurus here can confirm!
@fringe sinew so I think I'd understand. I'd suggest instead of SCDs (yea, I know, refactoring) I might have a component with an int of the mesh the quad belongs to. Then I'd get a job to fill a nativemultihashmap with that int being the key. That's if you don't care about order of the quads and would be quick. Trying to jobify combining the quads when caring about the order either means calculating the order beforehand or sorting afterwards obviously.
So, a filled nativemultihashmap, that points to individual nativearrays to be filled, is passed to a job, where all the components are processed and where they write
That sounds like a plan
But that'll mean it's just one job, right? How good will it leverage parallelism? And if it will, won't it create race conditions? AFAIK there's no way to easily sort all the components by integers and create individual jobs for them.
you pass a single job the nativemultihashmap .AsParallelWriter() and the all entities with matching components can just write to the hashmap in parallel using their mesh id int from a component attached to that entity
you can then use another job to read all values for a key and fill nativearrays which you can address from your non-ecs code
it should be very fast
I was unaware of that. Thank you, will be experimenting
I want to recap if I didn't miss anything...
no problem - if you find it's a bit slow, post some code and we can take a look but also you would likely get some gain from removing the SCDs
sure
So, I have entities and assigned components. Components have an integer (let's call it a meshID), which shows to which mesh it'll be assigned.
Then I have a nativemultihashmap. Its key is the meshID integer and the value points to nativearray that needs to be filled up by the components.
I schedule a job with that .AsParallelWriter() method where all the components write to their designated nativearrays that we get from the multihashmap.
Is that correct?
I think I'm missing something here
yes pretty much - the hashmap has an enumerator per key rather than a nativearray but it's not all that different - you don't need to allocate it before, you can just .add(meshID, quad) basically
Sounds alright so far, but I still can't really understand how passing the hashmap with that method will allow my job not to create race conditions.
I mean, the archetype of components is passed into the job, I get an array of those components, they are scrambled, how will they safely write to the hashmap?
well.. you can go through Unity's code but that's basically the point of .AsParallelWriter and using a hashmap rather than a multi-dimensional array or something - the whole idea is if you adhere to the syntax, it will be safe - and if you don't, you should get an error
Alright, I will try. Thank you once again
that said, you can circumvent some safety restrictions by using e.g. [NativeDisableParallelWriteRestriction] (or something similar - doing it from memory) if you really do know that the indicies you're writing to across jobs are actually unique - but I don't think you need to worry about that here. Good luck, hope you make some progress.
Hmmm, I have a question
Let's say that I have this hashmap
And the key is this
Will ECS bash me for having a pointer to Texture2D in a struct if I'll be using that hashmap in a job?
I'm surprised it compiles since the key isn't blittable?
Ah its because the key itself is a struct, but it has a reference type inside
Yeah, it's blittable, but that pointer to a texture can ruin quite a bit in jobs
yea, even if it worked you wouldn't want it to as for speed you want linear memory access? The key should ideally just be an int
Huh
Well, taking Timboc's advice, the whole grouping scheme worked for grouping quads in a NativeMultiHashMap. However, it seems that it's not possible to actually use an undefined amount of nativearrays in a job
Guess I'll need to schedule individual jobs myself.
note that the code above is a NativeHashMap not a NativeMutliHashMap so it will only support one entry per key
Yeah, I know, it's a whole other system.
Your previous advice worked fluently. The code nicely batches all the quads by their batch id
This system, on the other hand, takes already batched quads and tries to assemble them into nativearrays, ready to be fed to the mesh APIs. Problem being that I tackled this problem a bit differently then what Unity expected.
so I don't know much about it but I wonder if this is the right time for the deferred job stuff - @stiff skiff may be more helpful
You rang?
See, I have this situation
I have a lot of components. A system takes those components and sorts them into NativeMultiHashMap by one of their values.
Then I want another system to take the nativemultihashmap, create a usual NativeHashMap (where the key is the same thing, but the value holds a set of NativeArrays) and fill those arrays.
Problem being that jobs do not really allow this where you don't know the exact amount of nativearrays.
Hence why Timboc suggested to take a look at IJobParallelForDefer and consult with you
That's about it
these nativearrays you're making are for mono side to stuff into meshes?
Yeah. At one point I'll just copy their data to mesh arrays and dispose of em right after.
So it's slightly clumsy but maybe is what you were getting at earlier - if your meshid is e.g. 0..n then I wonder if you can just create persistent nativelists that you write into. E.g. NativeList<data>[] meshes; then OnUpdate in your system do for(0.. n) new Job() { meshId = i;} and your job writes hasmap 'values for i' to meshes[i] ?
Yeah, that's what I hinted at basically. For each key that the MultiHashMap produced in a previous system I make a new job which writes to the regular HashMap in its own key.
I think that makes sense.. still parallel and scheduling jobs isn't too expensive
Doesn't Unity automatically schedule a bunch of jobs when it thinks is appropriate? Shouldn't be a lot of overhead at all.
yea - I guess all this vague talk of performance/overhead is.. vague haha.. not sure if you're hoping for 1mil quads in 1ms or trying to improve on 1000 quads currently taking 1s haha
The latter
then yup, jobs ahoy (shouldn't be an issue at all)
I don't think I can help with this one
I'm a little confused on what you're trying to accomplish.
going from NativeMultiHashMap<meshID, meshData> to many NativeArray<meshData> essentially
Yes but why? That sounds like a solution to an issue i'm missing here
Building a mesh from default C# arrays (since building meshes out of NativeArray is not yet supported)
Each entity-component is a quad. Quads are grouped together, then translated into raw mesh data, which is then translated into default arrays and applied to the mesh.
out of curiosity, why an entity per quad?
I'm building a lens flare system. Each lens flare part (a single bokeh shape, for example) is its own entity, which may have some modifiers applied to it as components (a directional offset, for example)
How many of these quad entities do you expect to have
500-1000. I was told that it may not be a problem, since early-outing with a bool check is quite fast
Yeah thats totally fine, just making sure you're not trying to do jobs/concurrency for a small amount of entities
If at one point one of the systems will determine that the flare part will not be visible, then it culls it by setting a bool
All the next systems will early-exit and the component will not contribute to the mesh building process
So you just want to grab all vertices, and toss them into a normal C# array in the end right?
Yeah. More precisely would be to grab all the quad data, convert them to verticies-colors-etc, then toss them to arrays and set those arrays to meshes
So the only job bit you should need, is finding all entities that make up a mesh, and copying their vertices over into a NativeArray of the right size, in the right order
then convert it into a normal array outside of a job
Currently I have two separate jobs for that, one for sorting the quads into their own groups and then building the whole mesh data from those quads. I'll refactor it a bit later, I'm still quite new to this whole stuff. I just want to somehow understand all this workflow.
Is the meshID a shared component?
No. A struct containing an enum and a hash
If it was a shared component, you could get all unique values of the meshID. Make a hashmap with meshid -> NativeArray<Vertice>
You can count the entity counts per shared component and get the right size nativearray probably
Though I've found the filtering on SCD's is a bit slow
Ok @fringe sinew knowing better what you're trying to achieve, also worth mentioning is I've seen lots of requests for job mesh modifications for RenderMesh. Keijiro has an older example (https://github.com/keijiro/Firefly/blob/master/Assets/Firefly/Renderer.cs) also tertle from forums made this (https://github.com/tertle/MeshDemo/blob/master/Assets/Scripts/Systems/Mesh/MeshSystem.cs)
Is there a way currently to move the OnUpdate to the FixedUpdate group in the debugger?
Check out the last post here: https://forum.unity.com/threads/update-systems-at-fixedupdate-frequency-with-new-apis.657565/
@coarse turtle but the last post approach thing just doesn't work on Unity Physics 0.2
Ah, ):
and Unity's workaround isn't the same thing at all
it's just a spawner
at fixed intervals
True :/
The only other way I can think of is manually updating the systems yourself in a MonoBehaviour's FixedUpdate call, but I've no idea if it'll work w/ the Physics package tho
@keen forge
@stuck saffron Hi
Is there a way to call the entity's update method in a FixedUpdate?
@coarse turtle
That would seem abit cleaner than the other approaches
Well, there's no update on an entity, that's done on a system and for that you can construct your own systems, store them in a collection of sorts, and then call the system.Update() call manually in FixedUpdate.
Pic is from the same original thread I posted
it's a workaround until they provide better support for FixedUpdate ๐ค I've no idea how it will impact your perf tho...
Neither do I, guess the best way is to test it out ๐ Appreciate the help
Crazy how they haven't added support for FixedUpdate
AFAIK they want to give control on the fixed update step to you as the dev of your game, but i dont remember seeing any update to that lately
was hoping that 4 months would be enough to grant that, but hopefully soon
I need to store a string for an ability's name
The settings file is an IComponentData
I can't save string/char[] in that
What do?
Native string 64, 512
Same message
Maybe it isn't introduced in the ecs I am using..
It's one version of the fps sample that a studio I work with are using
I'm scared to update the entities package o_o'
assuming you don't need to operate on the string inside ECS, you could keep the string stored elsewhere (some Resource/Localization manager for example) and put an index or hash key into the ECS component so that you can retrieve it later where it needs to be used.
Yeah that's how we did it before
The issue is that I need to be able to access the string in an asset file that already exists with all the other values
Dictionary and a hash of the string int
And can be accessed in editor inspector
Doesn't sound like it needs to be in ecs though
Maybe you can think of how you are building it and make it simpler
I've got head to sleep though.
Thanks for helping though
The asset file was made by Unity devs like this:
[Serializable]
public struct Settings : IComponentData
{
public float baseDamage;
[Space(10)]
public float headshotDamage;
public float criticalHeadshotDamage;
public int criticalChanceHeadshot;
[Space(10)]
public float neckDamage;
[Space(10)]
public float cpuDamage;
[Space(10)]
public float torsoDamage;
public float criticalTorsoDamage;
public int criticalChanceTorsoShot;
[Space(10)]
public float upperArmDamage; // ca 80 % of torso damage to simulate bullet penetration of arm into torso.
public float lowerArmDamage; // ca 75 % of torso damage to simulate bullet penetration of arm into torso.
public float handDamage; // ca 60 % of torso damage to simulate bullet penetration of arm into torso.
[Space(10)]
public float upperLegDamage;
public float lowerLegDamage;
public float footDamage;
[Space(10)]
public int damageSpreadMin;
public int damageSpreadMax;
public float damageImpulse;
[Space(10)]
public float roundsPerSecond;
public int clipSize;
public int ammoInventorySize;
public float reloadDuration;
[Space(10)]
public float hitscanRadius;
[Space(10)]
public float minCOF;
public float maxCOF;
public float shotCOFIncrease;
public float COFDecreaseVel;
}```
Inside a class that extends CharBehaviourFactory
So I thought
"Okay, why not just add the name in there?"
Then the designers can adjust the value just like everything else in one place
I worked around that by having my settings in the IConvertGameObjectToEntity monobehavior attached to the prefabs. So they can be configured in the inspector, and have strings, classes, addressable AssetReference etc.
During the conversion, i translate all the things into their ECS version; so that's where i would cache/hash strings that need to be associated or use a NativeString64. It definitely adds extra work to maintain a settings/inspector layer, conversion step and runtime layer though.
Here's the source; might work on older versions i dunno https://gist.githubusercontent.com/jeffvella/155d0a28ecd998a8b6ec476ff1d00135/raw/a0aab423fbb5b5526c26a10339513837834e487b/Words.cs
Thanks will look ๐
Can I find all component types attached to an entity?
Using the EntityManager ?
You can get ComponentCount
But I wanna find all the components associated with an entity
EntityManager.GetComponentTypes()?
I tried that
I am told that no types were found for the entity I pass it
Even though the entity has 17 components attached
And GetComponentCount confirms this
Seems like it works for me tho
Is it because it doesn't work in the immediate window?
Hmm, I'd have to look into the source on what GetComponentTypes(...) is doing, so im not sure how to answer your question
If you're interested in what I called, this is all I did in a ComponentSystem
var components = EntityManager.GetComponentTypes(entity, Allocator.Temp);
foreach (var c in components) {
UnityEngine.Debug.Log(c.GetManagedType().FullName);
}
components.Dispose();
Alright, will try
god i wish unity didnt crash so much with ecs
Is quaternion.LookRotation/LookRotationSafe supposed to take a vector as degrees or radians? and even then with the correct input, should it be outputting the exact same result as Quaternion.LookRotation? or something that is 99% a match?
it should take a forward and up vector, degrees/radians shouldn't have anything to do with the input
Look rotation assumes your inputs are normalized vectors
safe version doesn't
is 0,1,0 not a valid input vector for it? i keep getting quaternion.identity if i use it with the mathematics LookRotationSafe
thats something that works fine with the old UnityEngine LookRotation btw
It says that it assumes that the inputs aren't collinear, so if you are plugging in 0,1,0 for forward and up is 0,1,0 they'd be collinear.
The old Quaternion.LookRotation doesn't assume the same things as the mathematics one https://answers.unity.com/questions/467614/what-is-the-source-code-of-quaternionlookrotation.html
A prototype of a C# math library providing vector types and math functions with a shader like syntax - Unity-Technologies/Unity.Mathematics
that's not the actual source code for Quaternion.LookRotation but i assume it's close enough
If the magnitude of either of the vectors is so extreme that the calculation cannot be carried out reliably or the vectors are collinear, the identity will be returned instead. That is why you are getting quaternion.identity
huh ok thanks for educating me that ๐ , for LookRotationSafe, would 0,1,0 be considered "Unit Length"? Also do you know why these limitations/restrictions are in place? do I just fudge my numbers a bit then? this is just weird to me
yea 0,1,0 is unit length
idk it might be easier to help if you describe the problem you're trying to solve
I would assume that Quaternion.LookRotation also has some sort of similar issue if you plug in 0,1,0 for forward
i've never tried though
Can I check what people are generally doing for player input and movement?
My approach at the minute is this: I've written a movement system that reads IComponentData from an InputComponent and in a jobified way turns this into forces, velocities and ultimately translation and rotation changes. The original idea was that when I come around to writing my AI, I only need to generate the input Component data and it'll just plug into the existing system.
Is this massively overengineered? I'm currently trying to iron out the movement so it's smooth and the camera rotation works as intended, but having a few bugs with my implementation at present and finding it hard to debug well. I just started a test project with nothing at all in to work solely on the movement input so I can better understand what I'm doing.
Just wondering what everyone else does ๐
So far i have an InputEntity with all my input related components on it. If a job needs input, i can GetSingleton<WhateverInputComponent>() and then pass it into the job. Since i'm already passing in DeltaTime and other things this made sense for where i am at. And obviously i have systems that update the Input components as the input changes.
In addition to being able to check the current state of some input, i have some entity events for when input things happen - like mouse pointer pressed/released. Systems that need to do something once when the mouse pointer is pressed can just RequireForUpdate() on the existence of the event component.
e.g.; creating pointer pressed event, https://hatebin.com/qzyrsoehbz
simple capture of current input https://hatebin.com/ptrfuruelq
its been useful so far to be able to see the info together in the EntityDebugger
https://i.imgur.com/98NdRWG.png
or do you mean more like, how people are implementing movement/rotation of game objects?
@vestal hatch fwiw Quaternion.LookRotation doesnt have issues with colinear or unit length inputs. My situation is getting the surface normal of a raycast to draw sprites at(ie bullet holes, scorch marks, damage etc). problem is now solved but i guess im looking for advice on my solution, fudge the numbers ever so slightly(what im doing) or use the old Quaternion method. Neither really seems right with me but mae im ust overthinking this
And you can't use RaycastHit.normal for that?
or do you mean using the normal to draw the sprite in the right direction?
oh nvm misread that i see
I mean if the old Quaternion method works, i'd use that. Maybe figure out what it does and implement it with the mathematics library
if you could get the triangle vertices you might be able to construct the rotation with normal and one of the edge vectors instead of normal and 0,1,0 for up
RaycastHit.triangleIndex maybe? but that sounds like it's overthinking the problem if Quaternion.LookRotation works, unless you're running into performance issues currently
yeah maybe ill try implementing it with the new library or just switch back, working with the triangle verts is an interesting idea tho
i don't know if it's a good idea though because any time you do mesh.vertices it returns a copy of the array
idk how you'd do that without it being slow
@mint iron thanks, yeah that's what I was asking about. Interesting! Thank you
@safe lintel the interesting thing is that the Quaternion.LookRotation docs also state it returns identity if colinear Returns identity if forward or upwards magnitude is zero. Returns identity if forward and upwards are colinear.
I don't really understand why you're seeing a difference between the two implementations if that's true
weird, because ive both used a test script and used it in the actual script with it returning a valid workable Quaternion wheres the mathematics version failed to
Also perhaps you should try the advice of this post https://answers.unity.com/questions/1232279/more-specific-quaternionlookrotation.html
Since you probably don't care about the rotation as long as it's pointing in the same direction as the normal
i was actually looking to do that in the future, thanks for finding that
simple test with the colinear result,
using Unity.Mathematics;
using UnityEngine;
[ExecuteInEditMode]
public class TESTQUATERNION : MonoBehaviour
{
public bool logresult;
void Update()
{
if (logresult)
{
var up = new float3(0,1,0);
logresult = false;
Debug.Log(Quaternion.LookRotation(up, up));
Debug.Log(quaternion.LookRotation(up, up));
Debug.Log(quaternion.LookRotationSafe(up, up));
}
}
}
i cant be the only one getting a non identity result for Quaternion.LookRotation right/
Hmm trying to order my systems properly, but I'm not quite getting it yet. I'm getting errors on my camera as it's complaining about NaN on the translation component of the entity it's set to follow, so clearly I'm doing something at the wrong time. Is there an easy way to debug this?
The error occurred when I added a LocalToWorld reference into an IJobForEach job. I just don't know why
I use some functions that need static field (int2 - size of a map). Burst thrown an error when i try to access that field. I don't want to pass this int2 to every job that use those functions. So what do u use? DOTS Singleton?
re: my post above, I had a LocalToWorld matrix of 0 which was causing the errors. Dumbo me!
@frosty siren they really don't want you to do it, they want you to have to pass all the data used into the job.
@mint iron it cause so many extra arguments in every job ๐ฆ
@mint iron Really wish it was possible to disable all these safety checks...
yeah i don't like it either. I understand that they probably want to limit the number of support requests they get but i personally think its excessively protective.
@frosty siren i just figured out how to use the new SharedStatic<T> https://gist.github.com/jeffvella/e2f61056f64e4c343700c95ba4e39592
The only bad thing is that i need to store it inside some system
no thats just to illustrate / showing how to set the value from outside. You should be able to access it from inside any jobs with just SharedStatic<MyCustomData>.GetOrCreate<T>() where T needs to be some unique type that they can make a hash of. You could probably wrap access in a class to make it nicer.
Ahh, ok) I thought it must be ComponentSystem or JobSystem
Here's a better example https://gist.github.com/jeffvella/30d5b73bcaab840c0b349567fa49378f
or a generic version https://gist.github.com/jeffvella/4c06cf1f2f55fe36fdf7396040071881
Am i missing something or does Unity.Mathematics have no quaternion product implemented yet ?
same question for quaternion conjugation
nvm, those are in Unity.Mathematics.math namespace, i was looking for them in Unity.Mathematics.quaternion
phooey probuilder doesnt work with subscenes
Ok, so back to RenderMesh. I have an identical Mesh across 1000+ entities, but want the material's color to be different per entity. At the moment to get this to go I'm creating a new UnityEngine.Material - but this obviously isn't the right way to go about it as RenderMeshSystemV2 slows to about 90ms. Any reading to help me understand this better?
From the forums it looks like MaterialPropertyBlock also isn't properly supported (yet)
Ok, storing the unique combinations as their own materials in a dictionary and referencing them seems to be better
0.6ms in RenderMeshSystem now, though that seems like it's still doing a lot of work - is it normal?
Coming back here after tinkering with ECS.
1024 flare entities on-screen and only 0.25ms total, including the mesh generation on the main thread. This is quite ridiculous.
I'm very concerned about this. How can it even be so fast?
Burst does some truly remarkable things here, but that's why I'm worried so much.
This entire ecosystem relies on Burst and its ability to compile very nice instruction code, but I fear that it'll be the next IL2CPP, which produced a ton of bugs and took years to arrive on platforms other than mobiles.
Thankfully it's getting way more attention than il2cpp ever got
Like, for example, where is the Switch support for Burst? Don't you think that compiling a subset of C# into processor instructions would be easier than converting your entire C# codebase to C++ and compiling that against platform SDKs? And Switch has the same architecture as mobiles do.
And il2cpp is getting love now as well
Yet mobiles supported burst fine for quite a bit.
That's a big factor why I'm worried so much.
It's too much of a black box.
I've read on the forms that switch support is coming
It's just early on
The whole engine is a black box
At least a lot of the modern package based stuff is now open source on there c# side
0.25ms ๐ - why so slow? jk jk but a lot of that is probably job overhead.. wouldn't be surprised if you could make it 10k and it be under 0.5ms
also, glad you got it working btw
ty
But it's all just very suspicious. ECS is good and all, but burst really makes all the pieces fall together.
And, again, that's why I'm so concerned.
I'm personally much more concerned about other features in Unity (e.g. hdrp/urp etc) than burst.. other than the couple crashes on amd (reported on the forum) it's been pretty bullet proof for me so far? It is annoying that it re-enforces the requirement to build on the same hardware you deliver but a price I'll pay for the performance
Anyone know what the deal is with this 'Develop' button? it shows up for me in2019.3.a08 but its not there in a11
I have this problem where I have to create an entity, and then move the values from one of it's components to another entity. Currently I create it with commandBuffer. Do I need to have a system dealing with this separately or is it possible to record into the commandBuffer?
Am i understanding you right that you use a command buffer to instantiate an entity (from a prefab?) then want to copy from components of the new entity to another entity?
So is unity going to fully implement the entity component system at some point? Or are they simply adding it as a more efficient but more complex alternative?
It'll always be hybrid, from what I can tell
Or for so long that entity becomes second nature and gameobjects can be phased out
Do you recommend trying it out?
I don't think what im currently working on needs it
but maybe its worth doing just for good practice
if you can make the time i think its worth learning, it is the future of Unity. All the old monobehavior stuff you know is going to be obsolete in a few years as they rebuild all systems around burst and ecs. Even UI stuff is changing with the new UIElement system.
@mint iron Yeah, doing Instanciate, and then want to move a Collider component to another entity.
alright im relatively early in the development of that game so I guess I can take the time
do you suggest any resources to learn?
CodeMonkey vids are good https://www.youtube.com/watch?v=ILfUuBLfzGI&t=2s
Learn how to get started using Unity ECS. โ Get the Project files and Utilities at https://unitycodemonkey.com/video.php?v=ILfUuBLfzGI Unity DOTS Explained h...
@mystic mountain If you use Entities.With(query).ForEach() / EntityManager then you can get the component data you need immediately after instantiate. Hard to say without knowing what else is going on and how you've structured it.
You could just instantiate with CommandBuffer and then next frame it would be picked up by a different system that does the collider copy.
@mint iron Don't think you're allowed to use EntityManager within ForEach as you're changing the structure you're iterating over. And the second option is what I'm doing right now, but was wondering if there was some way of simply moving unknown memory later : )
@feral portal check the pinned message on this channel
it has official resources listed
I think you can in the latest version of Entities,; in older versions you'd use PostUpdateCommands
also looking at that video now, it's wrong from beginning
you don't need to install mathematics package manually (or other packages he said you can use) as the rest of the packages are automatically installed as dependencies for the entities and hybrid packages, including math and burst
@mint iron yep, but you can still use the implicit ecb still as well. It's pretty nice for some stuff
Figured out what the the develop button does; still not sure why its there only on some versions of unity. It copies the package from \Library\PackageCache to \Packages which flags it in the package manager as 'In Development' and lets you makes changes without it resetting to the default constantly.
@fringe sinew they can generate faster code with Burst, than if they translated to C++
C++ as a language has some pretty big design issues, and this design issues dont allow optimizers to go 100% ham
Sorry, but I don't think you got the point of my rambling
i actually tested C++ vs burst
@fringe sinew as far as i know it does work on switch
didnt they release it as "stable" already?
No, it does not. Burst does not compile under Switch
Ehhh, I don't think it's that Burst can run faster than C++. I think it's that writing performant C++ is considerably harder
We're on the latest SDKs and the unity version
@turbid sundial i tested by creating my own ECS that follows the same model as unity
can confirm it was slower
So your C++ code was slower, ok
mate, simple loops were faster on burst. The thing is that burst auto-vectorizes everything
while C++ doesnt
in fact, i checked, and there was almost no way of making the compiler vectorize shit (visual studio)
of course, you can do it manually, but its an absolute clusterfuck
The point of my rambling was to express that Burst starts to go the IL2CPP route, where the support for platforms was quite harsh and the porting process becomes a hassle. As an argument why I pointed out that Burst is not compatible with Switch, even though its CPU architecture is the same as in mobile phones, which were supported by Burst God knows how long.
@fringe sinew i wouldnt worry that much yet. Unity plan for burst is much bigger than il2cpp was
they are rewriting the engine to use burst + jobs
That doesn't really excuse the Burst itself on why it doesn't support something as Switch imo
probably just priorities, resources, story backlogs - like any other feature, best you can do is show that its something you care about so that they prioritize it.
well, switch is kinda important for something like burst
allows devs to optimize some stuff
So I wanna do a simulation something similar to the way Dwarf Fortress handles its creatures, in that each creature is a sum of all of its body parts, and every body part is simulated with different materials and functions. If a creature were to get hit in the chest, there's a chance that any of the organs in the chest could get hit, as well as any tissues. If a creature lost an arm, it would lose a hand, fingers, the functions that they provide, etc. I'm wondering how to do this in ECS, I'm having a hard time thinking about how to structure it.
@floral crest child entities. Something like the body is actually pretty complicated, and you likely dont want it in your main "simulation" entity
you would have an entity that is the "main" character. This is the entity that draws a sprite, plays animations, and runs around. For advanced stuff that is only used once in a while (like the detailed model for damage), you store it as another entity
or, as a normal C# class, which might be better
not everything has to be on the ECS
Yea true
the ECS strenght is on simulation-y things. Things that run almost every frame, and update constantly. For stuff that is very hierarchical, and has dynamic memory, and its only used once in a while, you are much better just making it with "normal" C# classes, and point to it from the ECS
Thanks a ton, I think I'll do it that way
ECS' strength is, put simply, the stuff that is easy to do: Spawn many thousands of entities and make them all do something.
Keywords here are 'many' and 'all do'.
in a case like this, you would hold a "BodyComponent", that has an integer. This integer points into the "actual" body which is stored in an array somewhere
Yea I'm really new to ECS, still trying to get my head around it
Will do, thanks
of course, everyone is rolling their own ECS there
but a lot of the knowledge is very useful
the thing is that an ECS of some sort is the only way to make a complex roguelike and not go absolutely insane
personally i think unity ECS goes a bit too far in hardcore-ness
not allowing you to easily put arrays in components, or to just randomly set/unset components from systems
A large part of that is because of the constraints on burst though; TypeManager has been a class with no way to resolve a static value from a generic T within a job so they have to pass the index in etc.
well, those restrictions on burst are specifically what makes burst fast
the thing is that stuff like ComponentSystems on normal C# go through some pretty serious slow paths it seems
it has overhead for days
for a clear comparaison, you can compare unity ECS with Entitas. Entitas might be a lot slower, but its so much easier and smoother to use. It also has editor support
yeah i know what you mean, there's a lot of overhead, the chunks setup, having to scan archetype layout for types to retrieve anything, its very slow compared to something like Entitas and it only works out faster because burst is a beast.
from my C++ experiments, its more that on an archetype ecs (unity) there are some small overheads when you do any query
on my own C++ ecs, i optimized the everloving fk out of it. Much faster than unity until you use burst/jobs
so i wonder what does C# do to have such overheads
marshalling
an IL ๐ in between.
maybe cloning stuff into NativeList and the likes? in my C++ ECS i just yolo-d all the pointers directly
i think because burst gives such an improvement compared to standard C# they're taking some liberty in making things over-engineered (read slower) because its still going to be comparatively way faster.
And part of that is trying to make it simple to write code. Like IJobForEach has some pretty heavy code generation, reflection, creating generic types and whatnot going on under the hood to set up each job. But for the user, its super easy to just write the job and be magically given the components you need.
maybe a part of it is how C# deals with generics
in the C++ ECS EnTT, you have an "each" function that is the same thing as a for-each, and just gets compiled down into hyper-optimized code thanks to template machinery
Now that I think about it, how does exactly ECS calculates job dependencies?
Ah
But it's if we are talking about archetypes only, right? It ain't smart enough to take something external into account, right?
yup
Alright, thanks
this is also why jobs need to be structs
and need to have specific in-out parameters
its actually great honestly. I use Taskflow in C++, which also builds a task-graph, but that one has zero safety whatsoever
it will just run your function
so its on the dev to make absolutely sure their read-write dependencies are correctly set. If they are wrong, the program will just do weird shit
Hm, is it all happening inside "GetEntityQuery" method?
I'm just wondering. It sounds a bit mysterious on where and how ecs knows the dependencies.
that im not sure about
I dont suppose anyone has an idea why this system stops running after 3 loops
public class TimeTickSystem : ComponentSystem
{
private const float TICK_TIMER_MAX = 1.0f;
private int tick;
private float tickTimer;
protected override void OnStartRunning()
{
tick = 0;
}
protected override void OnUpdate()
{
tickTimer += Time.deltaTime;
if (tickTimer >= TICK_TIMER_MAX)
{
tickTimer -= TICK_TIMER_MAX;
tick++;
Debug.Log("tick" + tick);
if (!HasSingleton<TimeTickEvent>())
{
var tempent = EntityManager.CreateEntity(typeof(TimeTickEvent));
var dudwtf = GetSingletonEntity<TimeTickEvent>();
}
else
{
EntityManager.DestroyEntity(GetSingletonEntity<TimeTickEvent>());
}
}
}
}```
In the entity debugger does the system say "Not Run" after 3 loops?
yep
I'm wondering if your system creates a dependency
when you create/destroy the timetickevent entity
its doing it after 2 runs now, I've tried renaming it and commenting out all the internal code and its still does the same
is tickTimer defined (set to initial value) anywhere?
I guess not
the other weird thing to be aware of is that deltaTime can be huge for the second frame in-editor. Usually 0.33ms but can be more if async burst is on
I've set it to a value in OnStartRunning and its still not running
I created a test empty component system just below it and that runs fine
Sounds weird to happen after 3 frames, but sounds a lot like an issue I've had. basically, the system is optimized away (turned off) when none of the entities it operates on exists, if some have existed previously. I'm pretty sure there was an attribute like AlwaysRun or something to stop it from doing that.
that's a good point
yeah it must be something like that
Is it possible to update a BlobAssetReference value?
Possibly, yes
I've linked blob assets to monobehaviours/scriptables with updates which worked fine
I haven't tried yet on BlobPtr<int> and updated it yet
unless you mean you want to repoint the BlobAsset to something else
No, I want to change values of CollisionFilter from PhysicsCollider
It looks like reference, but I can't use as reference?
what I did was encapsulate them in structs
public struct CanvasRefWrapper {
public Canvas WrappedValue;
}
public struct CanvasPtr {
public BlobPtr<CanvasRefWrapper> Ptr;
public BlobPtr<int> IntValue;
}
public struct CanvasBlob : ISystemStateComponentData, System.IDisposable {
public BlobAssetReference<CanvasPtr> BlobAsset;
public Canvas Canvas => BlobAsset.Value.Ptr.Value.WrappedValue;
public void Dispose() {
if (BlobAsset.IsCreated) {
BlobAsset.Dispose();
}
}
}
so something like that
o ic, I haven't used much of the physics package but that's good to know
Hmm, I don't get this. Why is the if statement still triggereing?
https://pastebin.com/wL3YnBpi
if anyone encounters anything similar to the above [AlwaysUpdateSystem] works
@mystic mountain maybe the ==/!= operator is doing a ref compare?
Oh
Is the first value the BelongsTo?
and the second value the filters[0]?
cause those are bit inversion values of each other
the inverse of 1 is 2^32 - 1 for an unsigned int
Hmm, so you mean it would do that on assignment maybe?
possibly
Nope, seems to be original values
var testComparer = new CollisionFilter()
{
BelongsTo = filters[0],
CollidesWith = filters[1],
GroupIndex = 0
};
if (colliderRef.Filter.BelongsTo != testComparer.BelongsTo)
{
Debug.LogError("MEEEP2 ," + colliderRef.Filter.BelongsTo +", " + testComparer.BelongsTo);
}
what's the correct procedure to freeing up component native container members ? do they get disposed of implicitly when RemoveComponent or DestroyEntity is called ? or should the destroying system dispose of them explicitly ?
Generally if you passed Allocator.Something into a constructor then you are responsible for explicitly disposing it, otherwise ECS takes care of everything it allocates when you remove/destroy components, buffers etc.
got it, thanks
Yes SystemStateComponents have a different lifetime compared to IComponents
User them to detect the deletion and dispose there
I'll check them out, thanks
Here's the basic info: https://docs.unity3d.com/Packages/com.unity.entities@0.0/manual/system_state_components.html
the detecting component remove section is what @low tangle 's describing
thanks for the link, I've read up on them, but didn't realize they also suitable for native container members
I have a question about RenderMesh, and the RenderMeshSystemV2 - I have a grid of hexes (4000+) that each have unique data. They currently all have a RenderMesh component, which is obviously pretty taxing on RenderMeshSystemV2. I'm wondering if I should be manually culling these to be ones that are "in view", and if so - should I be
- Adding / Removing the
RenderMeshcomponent to ones in view (orFrozen/Disabled) components - Straight up deleting entities that aren't in view
In general I'm wondering how I can make this even more performant. The scene is very simple but the more entities that run through RenderMeshSystemV2 the more it struggles (obviously) - and they definitely don't all need to be in there, since only 100 or so will ever be on the screen at once.
I'd split them into chunks first and then only keep the visible chunks + chunks that are adjacent to them
haven't yet dug into the ECS render systems though
always culling all invisible tiles would probably be quite expensive
just to confirm i got this right - with SystemStateComponents, i should move all the members that need to be freed (like NativeArray) to a separate component that inherits from ISystemStateComponentData and use them in conjunction in their system, instead of keeping everything on IComponentData component ?
@frigid badge pretty much
@turbid sundial I would try deleting them first
It removes any costs from systems that operate on them which might give you even more savings offsetting the cost of deleting, which might not even be that expensive
Always try the simple option first until performance becomes a problem. Less entities getting work done on them a frame is always a good thing
Yeah, I think you're right
In general, is the RenderMeshSystemV2 pretty heavy? I wanted to see what performance was like with a single hex entity, 6 triangles, and even then it's taking 0.16ms to render
when you say that each have unique data do you mean they all have a different material?
No, just a position, some floats for elevation,temperature,etc.
oh that should be fine then
everything about them exists as entities, and that's really fast. it's just getting into the rendering that I see big hits
not sure why it'd take that much time, that doesn't sound normal
is it better when you turn off the debug stuff?
like leak detection
should be under a dropdown in top bar
Similar, 0.13-0.16ms
Does that sound slow? I really don't have a baseline to compare against - perhaps that's normal speed for the RenderMeshSystemV2
Well that's good to know at least
i guess there's a base cost of running the system even with one entity, scales better than that at least
0.4ms for 100 entities which doesn't sound that fast either but then again it is still hybrid underneath isn't it
Yep, to compare I put a single Sphere as a game object with no entities, and it's about 30% faster in terms of fps to render that, than a Sphere converted to entity object
seems that 0.4ms goes to 0.1ms with burst turned on
Cool, that's good to know - it seems there's a crossover point where the base cost of running the system with X number of rendered entities exceeds the native renderer
I guess I had just assumed that it would be faster in both cases
also going from 100 with 0.10ms to 1221 entities (i'm just duplicating them in hierarchy cuz lazy) is 0.17ms so i suppose the key is enabling burst
So with the Entity Component system, is there no scene usage anymore?
I know you can use the convert to entity stuff
@turbid sundial there's a base cost to running the rendering systems that you pay for with the first mesh
Yeah, that's my understanding ๐
After it's easy to add more, and you can instance render a butt load
Makes sure your material has gpu instancing
It does, for what it's worth it's not actually slow - in build it's actually like 700fps - I'm just trying to see if there's any extra cycles I can squeeze out ๐
It's a great feeling isn't it
(e.g. the question about rendering out of camera / culling)
Yeah, I think over the years - even in my professional work (non game-dev) - I enjoy performance tuning more than anything
There's something so satisfying about gaining a few % more
Yeah you have to fight that when you push for release too which sucks :(
hi, I am trying to start using ecs, and am having some questions about the Transform system
in the old days of monobehaviour, if I wanted to point a transform to something I could just do transform.LookAt and it would solve all the details of the hierarchy
right now, if I just do rotation.Value = quaternion.LookRotation(playerController.lookAt, math.up());
it wont take the hierarchy into account
I could use the LocalToWorld to try to convert the target from world coordinates to a local coordinates, but that localtoworld data is old (from the end of the last frame)
if I changed the Translation in some system before trying to do the Loot At logic, the LocaltoWorld won't be updated yet
@wooden canopy you might have to wait until the TransformGroup has run. So perhaps change the transform before it, and then move your system that needs to use the final values to be run after the TransformGroup, or flag those entities in some way so that they're picked up next frame to be operated on.
@low tangle hey did you ever figure out that how to use NativeStream? i want to setup a queue/stack that can be both written to in parallel jobs and read from a ComponentSystem at the same time.
Looked into it, the networking Lindsey from unity uses it to read and write from a job from a udp socket
Library
I'm not at a computer for a few more days
\
@mint iron being forced to do that feels a bit weird to me to be honest, I am trying to make a shooter so the loop I am trying to do is simply
- Read Input
- Move Player and make it look at the where the mouse is pointing (ideally I would move the player, update the transforms, rotate the player)
- if fire is pressed, spawn a bullet from the gun that is held by the player (so the transform should be updated from the changes in the last step)
- the recently spawned bullet should have its transforms updated so that the render system can show it
if the transforms are only updated once in the loop, then either I have to have this happen over multiple frames, or I need to repeat logic manually (lke set the localtoworld of the bullet manually when created), or in some cases perhaps the off by one frame is no problem and just ignore the issue
the other thing that I am thinking about is having a system that just does World.GetExistingSystem<TransformSystemGroup>().Update(); in as few places in the loop as I can get away with and hope that with the chunk versioning the work of the transformsystemgroup will be as little as possible only in the chunks that have changed between runs
I haven't been through it but what you're doing @wooden canopy sounds not too far off this example project so it may be worth checking out? - https://github.com/lkihk/Unity-Offical-ECS-EntityComponentSystemSamples/blob/master/Documentation/content/two_stick_shooter.md
(sorry, didn't realise it's 2 years old)
yeah, that got removed from the examples
have not been able to find examples of "real" games, the current examples, are more small like testcases of small features, but don't give an idea of how to structure a real game
You don't need to have TRS components by the way
and operate on LocalToWorld LocalToParent, etc
and if you do use TRS and SomethingToWorld, then it's nothing weird to be aware of system update orders and tweaking them manually
@wooden canopy sorry just read about your lookat issue... it's a good point - could be worth posting on forums. I guess ultimately there may be an equivalent of late update for these kinds of problems. You might be able to run your lookat code after the transform system update and before presentation? Kinda waiting to see what they do about the corresponding FixedUpdate issues too.
one thing that I was expecting to have, was a function that given an entity it could run the transform logic on that (even if super slow compared to running the transform system with job and burst and all that)
something that could be called if you know you only will do it for a few entities, and want the transforms to be updated before doing somthing
you have that in LocalToWorld
how do I have that? if I understand correctly, that component gets updated by the transform system, so if I want to get the real world position of an entity I need to either run after the transform system, or do something to manually update the localtoworld if someone else changed something in the hierarchy
or ditch the TRS components and not rely on TransformSystem at all
in my limited experience, TRS components and TransformSystem only cause unnecessary headache
especially the part where it starts acting really weird if you write to LTW without updating TRS and then change entities' archetype
the moment i switched from TRS+LTW to just LTW everything started working in a predictable straightforward and clean manner
so you do only ltw, but still keep a parent relation?
or you work without a hierarchy?
there's no parent in my case, but there's LocalToParent component in ECS, so i guess you need to look into that
I don't see how you have a full game without ending up needing to create some kind of system similar to the Transform system.. manually calculating the full matrix every time you change anything also seems like the kind of perf hit it's trying to avoid too. Just my opinion of course but I'd be much more keen on trying to work with the built-in systems.
I'd guess that conventional TRS is also calculated every frame behind the scenes, and SomethingToWorld is also a Transform system
although I didn't have to deal with hierarchies, so can't comment on how feasible it is to use just SomethingToWorld components in that case
we made a full game (clash of the olympians for mobile) 6 years ago, we used an entity system (with java, based on artemis ECS), and we didn't use a proper transform system
entities had no parents
and it was a reasonably complex game
so I know its possible
but would not want to do that going forward, being able to use the hierarchy for some stuff is way easier, and for more complex stuff is necessary
[LocalToParentSystem] Child: Write LocalToWorld <= LocalToWorld[Parent] * LocalToParent```
it appears to be possible to use hierarchies with no TRS involved
When asking whether it's possible or not I'd start by asking why you need hierarchies, what features/parts/effects do you need?
but yeah, i need to actually get my hands on hierarchies in ECS to see how they operate
To elaborate, I mean things like deleting parent->deleting children, moving/rotating/scaling parent->children, etc
I may need to do some perf tests, but I think being able to execute the transform system not just at the end, but in a few points in the loop, might make it just super reasonable to use
Read Input
change positions, rotate, aim, etc according to input
Update Transforms
React to input by spawning stuff (fire bullet, trigger explosion, etc)
UpdateTransforms
Simulation logic (here bullets fly, explosions explode, enemies die, etc, etc)
UpdateTransforms (this is the current one)
Render everything
if update transforms is making good use of the chunk versioning and you don't change everything in each step, then those extra updatetransforms should not be super costrly
costly
So we're trying out ECS and so far I got a Player archetype with these components:
Translation
Rotation
PhysicsMass
PhysicsCollider
PhysicsVelocity
RenderMesh
LocalToWorld
And a bunch of minecraft like cube making up the ground with these components:
Translation
Rotation
PhysicsCollider
RenderMesh
LocalToWorld
so as you can see the player falls but through the ground
is there any common pitfall i could be falling in ?
that would produce this
So I asked this the other day and got no reply, and I'm hoping to find an answer because I feel its part of what is confusing me
With Entity Component system you make components as structs which are data containers, data which is processed by a system
and you add these components to entities
but you do all of this entirely through code
so is there any interaction with the scene view anymore in a pure ECS project?
I feel like that can't be right, but atm the onyl way I understand to do that is to use classical gameobjects and convert them
In Tiny you used to be able to edit comps in editor
but seems they want to lean to use the hacky conversion thing
so they are abandoning the ecs editor in Tiny,and they still refuse to implement mixed on normal editor
yup
that seems so wierd
I figure they're delaying the editor while things are in flux, until they at least have most core components ready, as not to take focus and dev-time away from that.
Technically you don't need the monobehaviour and converter, but building your scene and prefabs in ECS is pretty hard. Though, I've seen a solution which essentially save ECS 'blueprints' to scriptable objects that can be loaded in pure ECS.
https://forum.unity.com/threads/dynamic-entity-archetypes-using-scriptable-objects.547043/
It's from a year ago, so a bit dated, but the concept should still stand.
Entitas does it better
yeah theres really no support for editing components in the editor at the moment(unless you do it yourself), its definitely kind of a downside to being an early adopter
I'm trying to find information on working with meshes in ECS
is there any source code or documentation about it?
pinned message here has pretty much all the official docs
thnkas
So what I'm doing is probably stupid which is why I just crashed the Unity Editor xD
But here is the basic breakdown...
I'm trying to simulate very basic projectiles without using the physics engine in Unity. It's mostly out of curiosity and to learn than it is practical (I imagine at least). But here is what I did:
- I made three components:
[Serializable]
public struct BasicProjectileComp : IComponentData
{
public float3 Direction;
public float Speed;
}
[Serializable]
public struct GravityComp : IComponentData
{
public float Value;
}
[Serializable]
public struct AirResistanceComp : IComponentData
{
public float Value;
}```
These are simply to try and use ECS and learn how it works. Now, in my Systems I have these two (right now as I haven't made it to Air Resistance yet):
BasicProjectileSystem:
```csharp
protected override void OnUpdate()
{
Entities.ForEach((ref BasicProjectileComp basicProjComp, ref Translation transComp) =>
{
if (transComp.Value.y > 0f)
{
time = Time.fixedDeltaTime;
newX = transComp.Value.x + basicProjComp.Direction.x * basicProjComp.Speed * time;
newZ = transComp.Value.z + basicProjComp.Direction.z * basicProjComp.Speed * time;
transComp.Value.x = newX;
transComp.Value.z = newZ;
}
});
}```
GravitySystem:
```csharp
protected override void OnUpdate()
{
Entities.ForEach((ref GravityComp grav, ref Translation trans) =>
{
if(trans.Value.y > 0.0f)
{
newY -= (trans.Value.y - grav.Value);
if (newY < 0.0f)
{
trans.Value.y = 0.0f;
}
}
});
}```
I am thinking that what goes wrong is that I'm trying to access the Translation component twice in two different systems
(and yes, I know the approach is not considering things like collision and whatnot)
@stable fog in regards to your question about ECS and the editor: you're right, as of now we are focusing on the Conversion workflow as a way to enable usage of many tools in the editor (the Scene, Hierarchy, Prefabs, etc.) until we have a proper ECS equivalent. It's not easy not quick to remake everything from scratch, that's why we went with this hybrid approach.
Okay, thats reasonable
There's also another thing Joachim has touched on recently: the data that is best while editing is not necessarily the one that is best for runtime. As such, maybe the current Conversion workflow will disappear in time but it will always stay a conversion. Maybe a 2-way conversion, like the Subscrnes used in Megacity.
is conversion before runtime?
Generally yes, but honestly I'm not too sure if there's a plan to create a converter back to Gameobjects which works while in Play mode. I will ask next time I have the chance.
oh that wasn't my implication
I just wanted to have a better understanding of what was going on
Yeah, no problem. I was just saying, there are use cases for being able to edit objects at runtime like we can with Gameobjects today, so the Conversion workflow definitely needs to be 2-way in the long term.
@tardy locust does that consistently crash the editor? afaik if something is wrong it should spit out an error, not do a hard crash. might be best to bug report it if its doing it repeatedly. not really sure anything there that looks wrong, i do have a similar system for my own projectiles. i guess its not clear where newX/newY/newZ are being declared
Maybe it's how initialise the objects. Lemme show how I do it.
Here is the script that runs on start
public void Start()
{
m_EntityManager = World.Active.EntityManager;
Random rnd = new Random();
rnd.InitState();
EntityArchetype basicProjArcheType = m_EntityManager.CreateArchetype(CommonArcheTypes.GetBasicProjectile());
NativeArray<Entity> entityArray = new NativeArray<Entity>(NumOfProjectiles, Allocator.Temp);
m_EntityManager.CreateEntity(basicProjArcheType, entityArray);
for (int index = 0; index < entityArray.Length; index++)
{
Entity entity = entityArray[index];
m_EntityManager.SetComponentData(entity, new BasicProjectileComp
{
Direction = new float3(rnd.NextFloat(-10, 10), rnd.NextFloat(1f, 2f), rnd.NextFloat(-10, 10)),
Speed = speed
});
m_EntityManager.SetComponentData(entity, new GravityComp
{
Value = AngularDrag
});
m_EntityManager.SetComponentData(entity, new AirResistanceComp
{
Value = WindResistance
});
m_EntityManager.SetSharedComponentData(entity, new RenderMesh
{
mesh = bulletMesh,
material = bulletMaterial
});
}
entityArray.Dispose();
}```
i meant in the system itself
@safe lintel And the newx and z are values just put in the class. But this worked fine earlier before I tried to split it up into more components
using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using UnityEngine;
public class BasicProjectileSystem : ComponentSystem
{
private float time;
private float newX, newZ;
protected override void OnUpdate()
{
Entities.ForEach((ref BasicProjectileComp basicProjComp, ref Translation transComp) =>
{
if (transComp.Value.y > 0f)
{
time = Time.fixedDeltaTime;
newX = transComp.Value.x + basicProjComp.Direction.x * basicProjComp.Speed * time;
newZ = transComp.Value.z + basicProjComp.Direction.z * basicProjComp.Speed * time;
transComp.Value.x = newX;
transComp.Value.z = newZ;
}
});
}
}
ok, thats clearer, though still dont see anything that should cause such a crash, does it continuously crash if you try to run it?
I can try and run it again. Sec.
Huh. No. This time it runs.
Before the editor just straight up crashed.
ive found the editor is super buggy with ecs, like sometimes ill recompile and it will crash or ill press play and it will crash, but upon restarting and doing the same its fine
Probably something with caching then
but ecs is solid in a build or when im playing it never crashes etc
Though now my entities don't move at all when they are spawned
Lol
Oh I see why
Never mind
Ho boy
Weird problem
When I pause the game before clicking play
The entities still have ForEach() running before the first frame is even supposed to be stepped through
@tardy locust i wrote a quick projectile thing for some guy last week that might be of interest to you. https://gist.github.com/jeffvella/3d9f8f8982461ce9a47edb07ef7ce6eb ignore the TurnToCursorWorldPositionJob part i had other ideas but ended up just making it spin around in a circle.
@mint iron okay thanks for sharing :)
Okay
I have a system for generating parametric models
I'm trying to figure out if it makes sense to use ECS or if I should just be using Jobs
the system is basically a graph based modeling system
@stable fog for meshes you do not need the ECS features, so just Jobs and Burst
Hi is it possible to implement simple 3D physics and collision with pure ECS ?
because every tutorial I find uses either game objects or handmade physics
i published all of my unsafe collections on github finally https://github.com/fholm/UnsafeCollections
@tardy locust physics engine you made yourself?
I suppose. But isn't that what you'd want with a pure ECS approach?
yeah by hand made i mean you don't use any unity component for physics
meaning you have to do all the math yourself
i could but its just tiresome
i saw some components like PhysicsCollider etc but when I assembled them it just didn't work at all
@trail burrow good shit ty
@mighty whale yea you can import ecs physics package from package manager
docs and examples for it are in the pinned post
Hi everyone, I am seeing a bug in unity I think, where sometimes an entity will have something in it that unity doesn 't like and the entity debugger will get truncated when viewing that entity in the inspector, and also fill the console with exceptions
I created a repro case, and reported the bug, but perhaps someone already knows why it happens and what am I doing wrong
here is a repro case with the description of the issue
@mint iron Didn't really get to use what you wrote in the code, though I did read it.
But here is what my current approach produces. It's a very naive and simple approach but it's nice to use as a learning tool for ECS.
The managed function Unity.Entities.DynamicBuffer1<NavPath>.CopyFrom(Unity.Entities.DynamicBuffer1<NavPath>* this, NavPath[] v) is not supported by burst
But why? ๐ฆ
does anyone know if probuilder meshes work with ECS as prefabs?
I had a prefab with a probuilder mesh, but after the conversion it doesn't have any mesh or render data, if I unpack the prefab completely, in the scene, then it gets converted correctly and render perfectly
I then tried to export the probuilder mesh as an .obj asset, and replaced the probuilder mesh with the new .obj asset, in the prefab, and that woks perfectly
@wooden canopy they may not, ive submitted a bug report for their use in subscenes, something in my case was to do with the mesh readwrite attribute
Anyone know if it's possible to have entity physics object a child of a parent if they are kinematic? damned if i can get that to work lol
welp, now I realized that the lwrp doesn't support webgl
if you make your own system to handle transformations, the physics system uses translation exclusively and not the localtoworld which the transformation system uses for hierarchical relationships
why do you hate me unity
well perhaps its supposed to work, not sure, it doesn't for the build I just made, and don't see it in the supported platforms list at least
The LWRP is supported on the following platforms:
Windows and UWP
Mac and iOS
Android
XBox One
PlayStation4
Nintendo Switch
All current VR platforms
@safe lintel - so it's possible if i write my own system to modify the physics transforms after the fact? if im reading that right...,
yeah you can modify translation to your heart's content, but id rather unity did that work for me ๐
ya me too lol
it's possible to move kinematic bodies in a parent child relationship with traditional physics, was hoping that was possible in ECS physics
thanks for the feedback
i may try another approach, i saw the physics demo of the jeep with the banging door, and it's moving around with physics based parts attached to it. there's probably another way to get this to work. I'm going to take that jeep apart down to the last bolt.
Are there good tried and tested ways to handle time with "pure" ECS? For example, if I want to increment a value every second, for 1000 components. The approaches I'm taking at the moment seem very convoluted for what should probably be a simple task
@turbid sundial Convoluted is kinda the current modus operandi for the ECS it feels.
@frosty siren It says you're passing in a normal managed array with that method signature. You can't use managed arrays in burst.
@turbid sundial there are tricks for days
what specifically do you want the time for?
I was just messing around with doing that recently @turbid sundial
I made a time tick system that creates an event entity every second and destroys it otherwise
and then other systems detect that entity to run whatever code at whatever tick rate I want
I can post code if necessary its really basic
public struct TimeTickEvent : IComponentData { }
[AlwaysUpdateSystem]
public class TimeTickSystem : ComponentSystem
{
//1.0f is equal to 1 second 0.5 is half a second
private const float TICK_TIMER_MAX = 1.0f;
private int tick;
private float tickTimer;
protected override void OnStartRunning()
{
tick = 0;
tickTimer = 0.0f;
}
protected override void OnUpdate()
{
if (HasSingleton<TimeTickEvent>())
{
EntityManager.DestroyEntity(GetSingletonEntity<TimeTickEvent>());
}
tickTimer += Time.deltaTime;
if (tickTimer >= TICK_TIMER_MAX)
{
tickTimer -= TICK_TIMER_MAX;
tick++;
Debug.Log("tick" + tick);
if (!HasSingleton<TimeTickEvent>())
{
var tempent = EntityManager.CreateEntity(typeof(TimeTickEvent));
var dudwtf = GetSingletonEntity<TimeTickEvent>();
}
else
{
//EntityManager.DestroyEntity(GetSingletonEntity<TimeTickEvent>());
}
}
}
}
public class CreatePeopleSystem : ComponentSystem
{
public int howmanydudes;
protected override void OnCreate()
{
howmanydudes = 1000;
}
protected override void OnUpdate()
{
if (HasSingleton<TimeTickEvent>())
{
for (int i = 0; i < howmanydudes; i++)
{
var tempent = EntityManager.CreateEntity(typeof(Person));
EntityManager.SetName(tempent, "Abraent" + i);
}
}
}
}```
was just a basic test to see if it would work, not sure about the error prone nature of it
EntityQuery.HasSingleton is probably better to use in a JCS
I'm curious, what does [AlwaysUpdateSystem] do? I always assumed that systems would update every frame unless I used RequireForUpdate
Systems are turned off if the last entity they operate on is destroyed. I think the attribute stops that from happening.
i had to use that decorator before i corrected my system and got rid of it
system won't update if they have no entities to operate on
In my case, the system ran fine to begin with (it both spawned and destroyed entities), but if you spawned any number of entities it would stop working once you destroy the last one
in my case it was the opposite - system was updating its entities and also was spawning them
and first spawn was delayed
so it spawned nothing on first frame and then never got updated because it had zero entities it was depending on
at first i fixed it with that decorator
but then just split it in two
yeah it doesn't work without that basically, hopefully Unity make it clear how ComponentSystems work or fix it somehow
Has anyone know how to solve the issue where entities are not being displayed?
FYI Entity Archetype contains LocalToWorld (which is usually root of issue when it is missing)
do you mean in the editor or the game view?
in the game view
The entities appear in the "entity debugger" window but aren't being rendered
the only I can think of was the localtooworld, so no clue unless you show your code
I cant see anything wrong with the code, sorry, I'm guessing your setting the mesh and material correctly in the editor
@gusty comet (Haven't looked through code) just a quick first check that often comes up - have you added the Hybrid Rendering package? Sorry if that's offensively obvious ๐
@amber flicker Yep I'v got it installed ๐
I had an issue witth probuilder where prefabs with meshes made with probuilder were not being rendered (in the entitydebugger you could see that no component related to rendering was added) but if you unpacked that prefab in the scene then it would render perfectly
@wooden canopy When checking the unity debugger the Render components seem to be present.
do the mesh & material work if you just use them in traditional meshrenderer + meshfilter and convert it to a pure ecs entity?
@safe lintel Yes it works, seems like maybe the Mesh Filter isn't being applied to the entity?
This is my view within the entity debugger window if it helps.
Figured it out! I was adding 'typeof(Parent)' to archetype list in order to parent an entity into another entity which was stupid of me as I thought it would appear in the game view.
Once removed it all worked.
does anyone know if the hybrid renderer is working on webgl?
I am trying to make a webgl build of my game, so I can share it easier for now that the requirements are not high, but the only thing that shows is a traditional gameobject that I have not migrated to ECS yet, all the ecs stuff is invisible
https://forum.unity.com/threads/rendermesh-webgl-support.665731/#post-4455703 this makes me thing that its not supported
@wooden canopy I never got the hybrid renderer working on webgl
I dont think the hybrid render supports webgl yet but idk their plans with webgl anyhow ๐ค
hey guys, im a little confused about what the job system and ecs allows for, does it make your CPU code faster/more efficient? For example, I understand compute shaders, in that u can leverage ur gpu to parallelize calculations, so that ends up being way way faster, so what does ecs/jobs sys provide (DOTS i guess)?
would it be correct to say that DOTS is primarily about leveraging multithreading on the CPU side?
That and enforcing memory layouts that avoid cache misses. Memory access is more sequential, which makes everything faster. Burst also understands the restrictions the subset of the language uses and the libraries Unity provides to compile that code to be even faster.
I have this problem where I can't change a value of the dots PhysicsCollider filter. Anyone who might know if this has something to do with BlobAssetReference or something else?
Entities.With(m_group).ForEach((Entity entity, ref SetExteriorFilterData setExteriorFilterData, ref PhysicsCollider physicsCollider) =>
{
Debug.Log("Belong b4: " + physicsCollider.Value.Value.Filter.BelongsTo); // Shows 0
physicsCollider.Value.Value.Filter = new CollisionFilter() { BelongsTo = 1, CollidesWith = 1, GroupIndex = 0 };
Debug.Log("Belong after: " + physicsCollider.Value.Value.Filter.BelongsTo); // Shows still 0
});
...
public struct PhysicsCollider : IComponentData
{
public BlobAssetReference<Collider> Value;
public bool IsValid { get; }
public Collider* ColliderPtr { get; }
public MassProperties MassProperties { get; }
}
Now I'm lost.. How does BlobAssetReference<T>.Create(void* ptr, int length) work if used on different structs of T and *ptr, but share interface? E.g.
var collider = default(SphereCollider);
...
var sphereCollider = BlobAssetReference<Collider>.Create(&collider, sizeof(SphereCollider));
...
public struct SphereCollider : IConvexCollider
...
public struct Collider : ICompositeCollider, ICollider, ICollidable
...
internal interface IConvexCollider : ICollider
Seems like it works in one system but not in another.
So I think I finally found out that you can't change layers to CompoundCollider/CompositeColliders, I tried changing between having only one boxCollider and them in a multiple children boxColliders, and you can only change the one of the single boxCollider.
curious, what is all this for? also why do you need a Blob thingy if you already have the Collider* ptr?
It's the DOTS PhysicsSystem. And I simply want to change the collision of an object/entity cluster in runtime : )
to change the Filter, get a PhysicsCollider then
colliderHeader->Filter = new CollisionFilter
{
BelongsTo = 1,
CollidesWith = ~0u,
GroupIndex = 0
};```
@mint iron This works fine on single colliders, but if you have multiple colliders as children of an entity which is a PhysicsBody that won't change since
public struct Collider : ICompositeCollider
{
...
public CollisionFilter Filter
{
get => m_Header.Filter;
set
{
// Disallow changing the filter of composite types directly, since that is a combination of its children
if(m_Header.CollisionType == CollisionType.Convex)
{
m_Header.Filter = value;
}
}
}
}
mmmm, well casting directly to the header should let you bypass that property check, but. sounds like they're doing it for a reason and you'd get some unexpected behavior.
Yeah, you are right.
I took a too quick glance of your code. That would work, for the top Compound only, you have to nest iterate the children of it to deal with child CompoundColliders and Collider leafs
anyone updated to 19.3b1?
and using physicsshapes/bodies? when enabling gizmos it appears to be showing what the physics collider will appear as for all colliders, but this absolutely tanks my in editor performance. not sure if this is a feature or a bug
ok blank project doesnt do this, time to nuke the library...
has anyone used the noise class? can I somehow "seed" it to not always deterministically output the exact same thing?
just add prng to the x + y @junior fjord
is this also an appropriate place to talk about Jobs?
I'm looking at converting a custom mult-threaded mesh modeling system I have built which should translate well to jobs overall, but I need to be able to do raycasts
can you conduct raycasts in jobs?
@stable fog if you use built-in physics, there's batched raycasts: https://docs.unity3d.com/ScriptReference/RaycastCommand.html
and ECS physics package is most likely already jobified
wait, like job within job?
that's not possible
you need to schedule from main thread
no no, I mean thats totally what I just said, but its not what I need
https://github.com/keijiro/Voxelman has example of raycastcommand altho it's with ECS
could still help you a bit
I have that updated to 2019.1 here: https://github.com/0lento/Voxelman
well, doesn't matter for the raycastcommand
it's same api
I think the official docs had some sample too
Since i want to stop using newtonsoft json to serialize my data structure, because thats bad, and super brittle
and I'm hoping I can fix my structure with SerializeReference
thanks for the link
you can chain that raycastcommand with your other jobs too
I'm just barely getting into jobs, I'm not sure how much advantage I can take of them just yet
On the one had, all my objects are specific tasks, on the other hand all the properties in those objects are actually references to other objects which define how to get the value for the property (inspired by WPF's Databinding, though more powerful really)
So the question becomes, how much performance do I gain by just scheduling the work from those objects with the realized values
as well as, can i execute that object hierarchy in its entirety before having to return the results from any of the jobs, which is the bigger question
we shall see
How does one do Scale in ECS? Like on Gameobjects it was in the Transform.
How is that handeled in ECS?
In the LocalToWorld or something like that?
@tardy locust NonUniformScale & Scale
They are just components
I'm working through an ECS problem (forgive any nomenclature I'm still on 2018.3) - I wonder if anyone has any input. I have an IBufferElementData that is used to calculate a final value. But the items that might get chosen from that list depend on a Component right now "CalculationRequest" which gathers every index that matches an ID. But I want to do that for more than one ID at a time and I have no idea how I should organize my jobs / data to facilitate that.
If I were able to run the job on every tuple of Entity / IBufferElementData / CalculationRequest it would probably work but you can only have a single ComponentData of any given type as I understand it. Splitting it into shared data might help but I'm still not sure how to organize it and still benefit from chunked data.
So for each entity with a CalculationRequest component, its looking through a buffer on that same entity, and selects only some of the values, then does something with the valid subset of indices. That right?
Yes. So currently the IJobChunk takes in one ArchetypeChunkBufferType<TheList>, one ArchetypeChunkComponentType<TheRequest> and output to a NativeArray<float>
If an item in the list matches TheRequest value then it will be included in this calculation.
Yes, it's very much a thinking problem. I want to maintain the performance of chunked calculations but right now the only thing I can think of is to have entities with a shared list and calculate one request type per entity. But that seems less than ideal.
TheList values are different on every Entity potentially?
what springs to mind is a buffer IJobForEach, but its chunked internally similar to what you're already doing so im not sure if it would be faster.
Correct. They could all be wildly different.
I'm not sure how to set that up and still have them batched. How do you group two different buffers nicely?
I did try making the request a buffer but the only way I could think to put it together was a job per entity but obviously that's not good.
There aren't many good examples for these use cases yet
something like this maybe https://hatebin.com/lmqpcesnya
Same issue of a single request per entity
I've also considered a component type per request type
Which might be more in line with how ECS wants to work
That just requires a bit of reflection in the system to gather all the request types beforehand.
if you're using the request's value in a calculation presumably whatever the request, the data is the same e.g. a single float?
Yes. It's an int. That int is just an id that is a part of each buffer element.
And yes each id can appear more than once in the list
Quick question that I can't seem to get a good result from googling. Within an IJobForEach, I am attempting to read/write to a static dictionary. Is that a nono with ECS?
@untold elbow It will function but will be slow - and possibly crash if you aren't careful about access to it from other threads. You're better off moving that dictionary into a NativeHashMap if you can.
Thanks, ill look into that.
@honest dirge It might help if you could describe your higher level objective? There isn't really anything wrong with creating an entity per request (it's not that heavy, just an index to the data which can be laid out linearly anyway). I'm imagining your buffer is like a column from some financial accounts and your request is wanting to do something like 'sum entries 1-5'?
For the sake of argument let's say yes. And yes I'm being obscure intentionally. Using your example:
Imagine the column contained "amount spent on groceries" "amount spent on rent" etc. There can be multiples of all of those and the component system calculates "sum of x" and also "average of x" or whatever else are my common summation calculations (that part is not being chosen and always happens).
Does that make sense?
๐
I don't feel I've got a good understanding - best I can do is suggest some vague techniques and maybe you can better understand what might apply best? For example, the most common technique when filtering a set of data to operate on is to have a system that pre-populates a nativemultihashmap for example. So, super pseudo code, system1 takes your requestbuffer and CDFE<Data> DataComponents and does Entity e = requestbuffer[i]; if(DataComponents.Exists(e)) hashmap.add(entity, DataComponents[e]) then system2 processes the hashmap. (sorry if this is all very obvious to you and not what you're looking for)
(this is all assuming you have a lot of items and don't want to be doing a lot of add/remove component)
The funny thing is that this would be much more doable if it was possible to nest Native* containers but since they aren't blittable that doesn't work.
So I've been trying to think of how to unroll that dependency
It very well could be something along what you describe. Which I have preciously set up but couldn't quite come up with a solution.
Its possible to write something custom and have an abstraction that just uses the DynamicBuffer ptr. For example, i have a NativeArray3D sitting on top of a dynamic buffer. Its easier in that its just doing spatial indexing on a 1D array but ultimately the dynamic buffer handles the storage mechanism and gives you a ptr to work with. Or have a component with somethign really dirty shoved inside ๐
I don't think I understand here, but it sounds like you're doing something in a fairly generic way, while AFAIK you're supposed to be more concrete with ECS(summing all of some type? Sure, just iterate each component of that type... assuming it's conrete enough).
Also, you said you're on 2018.3, but what ECS version do you use?
2D/3D array generally means you know the stride of each dimension though (doesn't NEED to I suppose)
@tawdry tree that's more or less how my current system works. It works with a single request beautifully.
That's why creating a piece of shared data and an entity per request might actually be the right solution
Except in this case the shared data is a list... hm now that seems like it would break.
So would probably have to create my own indices for sharing
Admittedly creating concrete things is troubling when you've very used to writing OOP and especially writing Generics/Templates
Definitely still trying to think in ECS land
Have you considered normalizing it so what you have stored in the buffer is each its own entity? depending on what components are on those, you could filter by request type with its archetype which is fast
Hm that might be worth looking in to.
In that case it might be just having the request type know what the entity query for that looks like
And that's only because new request types can and will be added in the future. If I can keep some of that out of the system itself it makes managing it easier.
Is there a way to write rendermesh data from within a Job? The issue I am facing is that it is nonblittible so I cannot store the data within a component.
@untold elbow its not easy, but there's a few attempts floating around: eg. https://github.com/tertle/MeshDemo
I appreciate the insights @mint iron @amber flicker . I've got some things to experiment with.
Cool - if you get stuck I suspect we could be of more help if you could create a small example of what you're trying to achieve that you can share but appreciate that can be time consuming.
is there a recommended way to make a system run every x seconds, rather than every frame?
about to try and cheese it with delta time math... XD
@lament orbit not sure about best practices but here's a couple ideas: https://hatebin.com/ovetntqcsv
@mint iron thanks, that's helpful !
is there any small update on where the ecs is standing right now? or especially what has changed with dots in since around june?
hoping for a big update this Unite (sep 23rd)
I recently played with DOTS and its definitely still not production ready
We're rolling Entitas ECS
I'm using it in production - just wouldn't attempt a pure ECS route atm.
For mechanically simpler projects, or just stuff that the current ECS can do very well (a lot of stuff doing simple things), ECS can be used in production, though I would caveat that by saying "As in, you can use parts of DOTS (burst, jobs, simple systems) just fine, but should definitely use hybrid unless your 1.0 isn't until mid to late 2020"
It's definitely good enough for playing around/experimenting for learning and wrapping your head around the pattern and methods
Busy at work because we're wrapping up a project (This friday, in fact. Hard deadline.), but I intend to try to make an actual, complete game (mechanically, probably not polish-wise) primarily using ECS. I'm thinking of a Sokoban since the systems in play are easy to visualize, but also considering a tower defence. In short, something between 'hello ECS x 100k sample'(spawn 100k objects and move them in simple patterns) and the advanced boids sample. If it goes well i'd public it on my Github, as there seems to be a lack of that level of examples.
@amber flicker thanks for the date
ok but when I check the samples repositories it just seems as if in the last months they got a lot of more physics examples and the rest basically stayed the same right
I used ecs last time around the time they had their first physics samples
Hey I have a question: Is there a way to check if an entity has a component from within a Job?
I cant pass the entitymanager because that's a reference type, and the EntityCommandBuffer doesn't have a method for checking whether or not a component is attached
@surreal rune Yes you can pass in a ComponentDataFromEntity<T>();
public class MySystem : JobComponentSystem
{
protected override JobHandle OnUpdate(JobHandle inputDeps)
{
return new MyJob
{
RotationComponent = GetComponentDataFromEntity<Rotation>()
}.Schedule(this, inputDeps);
}
public struct MyJob : IJobForEachWithEntity<Translation>
{
public ComponentDataFromEntity<Rotation> RotationComponent;
public void Execute(Entity entity, int index, ref Translation c0)
{
if (RotationComponent.Exists(entity))
{
var rot = RotationComponent[entity].Value;
}
}
}
}```
or you can use IJobChunk and e.g. chunk.Has(someComponentType)
I have a system that has been troublesome, and my first two attempts were throwing up exceptions for 'Aliasing' on the Translation component. And i'm not sure about what I've come up with. My concern is that the workaround may even be slower than if it was aliasing - it doesn't really make sense to me that we would have to take on the costs of scheduling multiple jobs and add additional complications just to avoid it. The two jobs that didn't work are commented at the end. https://gist.github.com/jeffvella/e60bd4071cef0564e535887517a26c96 Would appreciate your thoughts.
The bigger picture is that i have a main particle being spawned, and a trail of many smaller particles that should follow it. The follow particles have an Entity reference to the target they're supposed to follow and need to know its current position and move based on it (not sure if it will be a physics impulse or manual movement yet, but it will be a complicated movement like a helix or something).
Hello, i've been testing multithreading data assignment for transforms inside "IJobParallelForTransform" jopb versus doing it on the main thread by just iterating through a list, however, I'm getting about the same speeds per amount of transforms. Is the "IJobParallelForTransform" job supposed increase any speed at all?
nevermind, it looks like the speed improvement only comes if you assign more than just one of transform's properties.
@thorny halo how many items do you have in the parallel for?
parallel-fors tend to only be good when you are dealing with the tens of thousands of items, if the loop inside is simple.
@vagrant surge testing with 5000, added the "BurstCompile" tag to the struct as well as made sure the Transforms are unparanted, though not much performance improvement. Most of the lag comes from the scheduling from the looks in the profiler.
The recent blog post seems interesting in terms of a potential ECS editor, particularly this bit, under "What's next"
[...] Workspaces that enable users to easily create and switch between Editor layouts that are optimized for specific tasks, e.g., World Building, Animation, Lighting, etc.
link @tawdry tree ?
@vagrant surge It's the one from #497866432277643275
But for reference: https://blogs.unity3d.com/2019/08/29/evolving-the-unity-editor-ux/
ah
Christ, just found why the multithreading of transforms was taking so long. Always have the desiredJobCount inside TransformAccessArray as -1, just improved the speed 10 fold.
what does a desiredJobCount of -1 mean? Does it try to use as many theads it can to do the job?
no idea, but it makes scheduling jobs take really long if you have it high. -1 is the default value.
Presumably -1 means either infinite(uncapped) or 'figure it out'
very true
anyone able to point me in the right direction for ECS physics, Compound Shapes from code? Docs state to do it in hybrid form... lol, must be some way to do this in code. thx
I've tried using the Parent component approach, but it doesn't seem to effect the translations of the child physics objects. Not sure how else to attempt to describe it to the system.
oh, right in front of my face.. oh wait, i found a lead
-> ECSPhysicsExamples\UnityPhysicsSamples\Assets\Tests\Compound\CompoundDemo.cs . eh. ya. ๐
@mint iron Thanks for the help last night!
Is it ok to pass one queue to different jobs with AsParallelWriter()?
I think as long as the two jobs aren't running in parallel
Anyone found a use for ChunkComponent yet?
I guess chunk components can be like an enhancement to ISharedComponentData. I can imagine let's say you use an ISCD to split chunks into like "level specific chunks" then use a ChunkComponent to have more additional info for specific chunks depending on the level
yeah its interesting, every time i think it might be useful i end up needing more of a per-archetype component rather than chunk. It might be useful for some sort of changed mapping in the chunk for which components have had their values modified.
same here, i end up doing more archetype component than a chunk
Hey, is anyone getting a ambigious type error in collections?
Library\PackageCache\com.unity.collections@0.1.1-preview\Unity.Collections\NativeHashMap.cs(1490,23): error CS0433: The type 'Tuple<T1, T2>' exists in both 'System.Threading.Tasks.NET35, Version=3.0.2.0, Culture=neutral, PublicKeyToken=null' and 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
happened after I merged my project, not sure how to solve it
Is it in your code?
nope, its in nativeHashMap.cs
What .NET equivalent are you using for your project?
didnt have any errors before I merged too, so maybe it is but I dont know how that would work
NET standard 2.0?
Are you still on .NET 3.5?
how can I check?
It's under project settings, somewhere
Project Settings > Configuration > API Compatability Level
Though it could also be what SDKs you have installed, maybe?
You should probably be on the latest version, at any rate
The usual fix for ambiguous type error is to remove unused using statements, or specify which source assembly/type to use, but since it's not in your code...
yeah, kinda lost honestly
Have you tried restarting Unity? it works wonders, sometimes
hehe yeah tried that a few times
looks like it was some amazon gamelift dll that was being hecky
ah yeah, I was going to ask if you have any non-standard dlls in there
Oh yeah, the fun of dependency trees with leaves of same libraries but different versions...
sounds like a nightmare tbh
I've online heard (nightmare) stories
But then again I shy away from Javascript (the more i use it, the more I want to stay away from it) and the mess that NPM creates, and haven't worked on any large monolithic projects, so it might just be a matter of time.
How much should a beginner care about ecs? Could you more efficiently simulate animated wildlife and enviroment like trees foilage etc? Or ignore ecs and just hope the pc can handle game objects.
Or I have so little clue about all of this that I dont even know how wrong I am?
It could be useful to play around with it to learn the paradigm. Especially if you're not already very familiar with the monobehaviour/gameobject way.
well support for animation isnt really there outside of an unofficial gpu shader implementation that joachim put on github
At the very least I would suggest you learn about jobs, as they can be integrated with the traditional model quite seamlessly, and can provide multithreading for certain tasks.
(Jobs being part of DOTS(Data-Oriented tech Stack), and often, but not necessaril, used with ECS)
There is a boids sample, yeah, and ECS is great for that kinda stuff
jobs are for multithreading your code
But that's an advanced.... simulation? thing? game?
If you were to ask "what is ECS (in it's current version/form) good for?" then the answer would be two-fold:
- Making it really easy to write very performant code that affects a lot of things in (individually, per system) ways
- The model makes all logic nicely separated and exceedingly easy to reason about
I would encourage you to take a look at DOTS in general, if only to get somewhat familiar with the base concepts
Alright thanks a lot lot guys ๐ท
I'll get on that
I should probably qualify my previous statements by saying that it doesn't necessarily make it easier to make the code to do a certain thing, especially when you're not used to ECS yet, but you get a lot more 'performance by default', and it's usually easier to improve that even further than if you'd made the same thing in gameobjects.
Yeah I fogured I wouldnt get off easily as far as.conding goes, but the idea of just messing with scale.like spawning few hunders bullets a second and not freezing my pc sound exciting. Hahaha..
I'm trying to generate my terrain with entities instead of gameObjects
right now I'm using Translation, RenderMesh and LocalToWorld in my archetype but i need a collider for my custom mesh and it looks like the MeshCollider is not working with entities
is there something like a MeshCollider for entities?
Physics and ECS is a bit weird right now, and I don't have any experience with it. Depending on what you're trying to accomplish it might be a good idea to use a gameobject-entity-hybrid, I think
and when i create my map with gameobjects it takes ~1.8 Seconds on my test map and i get ~160 FPS while in the game while looking at it
doing the same thing with entities takes only 0.4 seconds but i only get 24 FPS in the game
i expected that my fps would increase with entities
thats why i tried to use them
Sounds like you might be doing something less than ideal with entities.
That said, for procgen with physics objects I'd probably use jobs for the generation and probably just use gameobjects for the result, as they shouldn't really do anything aisde from just... be there.
i only give the entities a custom mesh and render it in the world
You could check the profiler for what takes all that perf, but honestly, if you're running 100+ fps with gameobject you probably don't need to worry about perf. Though, again, using jobs for procgen (sh)could be faster than plain C#.
I've got the weirdest thing, I'm creating entity's and its only creating odd numbered entity's
Hey all, I have a job system than needs to access Unity.Mathematics.Random for thread safety. I am utilizing NativeArray to pass the Random structs to the job, but since this creates a copy of the original the seed will always be the same in the job system. I want the Random to behave like expected, when calling NextValueType it should get a new pseudo random value. Is there a preferred or correct way of doing this with the job system?
@trim trellis That should not happen... Check the ECS debugger profiler thingy to see which systems do all of that if you want to try to keep using ECS. Looks to me like it might be constantly (re)generating or something. But again, with that kinda perf I see no issue with just using gameobjects if that's easier (and it probably is?)
@jade flicker it should work with LWRP and hybrid renderer
I mean, if you want to render with ECS that is
yeah it does
@outer lotus Random is a bit of a pain right now. There is a forum post somewhere discussing the challenges (sorry i cant seem to find it right now) but one solution proposed was to pass in an array of pre-generated randoms (that were given seeds from UnityEngine.Random). So something like this: https://hatebin.com/uggvrqlzob but for me it was still failing miserably because per chunk thread .NextQuaternionRotation() and NextFloat3Direction were not producing a good distribution.
Another option is to just create the Random within the job. You just need to come up with an appropriate seed somehow. I tried a few options and this is what i ended up with: https://hatebin.com/hhtpcafltz var random = new Random(GetRandomSeed(firstEntityIndex, i)); where i is the index while iterating chunk components.
@mint iron Thank you for the suggestions! I have done mine the pre generated seeds way, but it feels a lot of overhead and I was wondering if there's a better solution. I guess it has to do for now ๐ Cheers!
Yup np, im pretty much just throwing out my ideas and hope they help ๐ at the moment it feels like there are very few recommended approaches to anything, we're just figuring it out as we go along.
hi I have a ComponentSystem and I would like update to be called after the physics update
i know it is possible but i cannot seem to find it
UpdateAfterAttribute, aka [UpdateAfter], and/or assign it to an update group, which I don't remember how to. You still need to find out the system to update after and/or group to update in, but you should be able to see those in the entity debugger
Thanks! I didn't know about the entity debugger it helped me big time :D
My ECS physics rigid joint chain freaking out. Should it be able to handle this? maybe my code is just garbage (i hope). joints go from parent -> child -> child x -> child x+n etc...
physics on its own doesnt take any of the transformsystem parent child relationship into account
unless you meant parent child for gameobject authoring
sorry gonna step out soon, but my experience with joints mirrors alot of that gif ๐ฉ
no problem, have a good one
@lament orbit joints in general kind of accumulate error
(in all engines and all physics systems)
so a very long physics chain is... problematic to do with normal physics joints
i tried to do it in unreal a couple days ago, 6 connections, and it was almost the same as that gif
Are there any good existing implementations for Quadtrees or something similar in ECS?
Where I can divide my entities into quadrants so they only have to assess nearby entities instead of all entities in the scene
Maybe it's not quadtrees i'm looking for but something else
@vagrant surge good to know
@surreal rune the boids sample does a hash grid. Faster than quadtree in most of the cases if tuned correctly
And that works for 3d right?
yeah
the concept is simple. You have a hashmap where the key is a "tile coordinate", and the value is an array of what is inside that tile
thats it
yes
Alright I'll give it a shot, thanks!
you divide the space in tiles-quadrants, for example each of them is 1 by 1 by 1 meters
and then you have a hashmap of those, holding an array of items per each tile
by changing the size of the tiles you change the performance significantly
if you want to find what is inside a radius of 10 meters
Yeah
I tried to implement something similar but i think it was pretty inefficient
thats why i'm looking for something with more professional work in it
I get what you mean!
Sick
ive used a variation of the technique to have 400.000 boids on some C++ project. The stuff scales well
its called like that. Its for moving objects that move in a flocking pattern
Ah im looking at the Flocking wiki now
So the algorithm i'm looking for is not called boids, it's just implemented in the boids sample?
yes
Gotcha
Hey, I got a question regarding entity to entity communication. Is there a clean, efficient way without having to resolve to buffers and tag components when transferring int values from entity A to entity B? I am now accessing like 6 components in a system and it feels just wrong...
think of it like a "health leech" system where A has a certain throughput (let's say 10), whereas entity B also has less throughput (e.g. 5). the system should transfer 5 units from A to B for each "tick".