Trending
Opinion: How will Project 2025 impact game developers?
The Heritage Foundation's manifesto for the possible next administration could do great harm to many, including large portions of the game development community.
Some thoughts about Unity's ECS
public class SomeSystem : ComponentSystem { private struct Group { public int Length; public EntityArray Entities; public ComponentDataArray<SomeComponent> SomeComponents; } [Inject] private Group m_group; // Inject the group entities with given components protected override void OnUpdate() { float dt = Time.deltaTime; // Nice cached deltaTime, we're on main thread, so we can use Unity's API for (int i = 0; i < m_group.Length; i++) { // some operates on data } } // System was enabled (ComponentSystemBase.Enabled = true) protected override void OnStartRunning() { // probably some more caches for optimization, preparation for Updates } // System was disabled (ComponentSystemBase.Enabled = false) protected override void OnStopRunning() { // probably some clean up } }
struct Group { public int Length; public EntityArray Entities; public ComponentDataArray<Foo> Foos; public ComponentDataArray<Bar> Bars; }
Group is filter of all Entities in active world that have Foo and Bar component It's like array of matching entities with references to all specific given components. So, group is like EntityArray but with references to components, EntityArray itself is just array of Entities (and entity is just an index).
Group is constructed with a set of required components, subtractive components. It's also synced.
Yes, you are rigth! They're the same. Length is length of EntityArray, so also Length of Foos and Bars, because each entity has Foo and Bar component
It's more obvious in this case:
for(int i; i < m_group.Length; i++) { // Using m_group.Foos.Length or m_group.Bar.Length would be a bit confusing in this case // because we iterate over all entities and can get access to ANY of their components } To summarize - every array in injected group would have same Length, because it's length of Entities and each entity has every given component. Separation of Length field is just for convenience.
for(int i; i < m_group.Length; i++) // iterate over all entities from group { // It's safe to iterate like that, because every array in group has the same length // and indexing is also injected(synced) in that way to use it exactly like this: var actualEntity = m_group.Entities[i]; // Actual iterating Entity var actualFoo = m_group.Foos[i]; // Foo component "attached" to actualEntity var actualBar = m_group.Bards[i]; // Bar component "attached" to actualEntity }
Well, you don't really need to!
Unity takes care about that. Systems track injected groups and will be disabled if there are no matching Entities and will be enabled if there appears one as well. But if you really want to, take a look upwards, see OnStartRunning and OnStopRunning ? I mentioned ComponentSystemBase.Enabled = true which is probably what are you looking for. It's property that allows you to active/disable system manually.
Convenience attributes for rescue! Since all systems are updated on the main thread, you need to think about order of updates, there are some attributes to help you with it: [UpdateAfter(typeof(OtherSystem))], [UpdateBefore(typeof(OtherSystem))] and also [UpdateInGroup(typeof(UpdateGroup))], where UpdateGroup is empty class. You can even control update before/after Unity's phases by typeof(UnityEngine.Experimental.PlayerLoop.FixedUpdate) or other phases in same namespace.
You can just inject it just like [Inject] private YourSystem yourSystem; easy as that. You can also use World.Active.GetExistingManager<YourSystem>() or if you're not sure if it exists but it should, use World.Active.GetOrCreateManager<YourSystem>()
Since systems most often operates on components, not directly on entities, it raises question "Why do I even need this index". Saying "it's just and index" doesn't mean that is not usable at all. It's very important integer. If you haven't tried Unity's ECS implementation, you probably don't know where is it needed. It's needed among others for functionality from EntityManager that holds EntityData and controls adding/removing (and much more) components from a given entity. But actually you don't want to add/remove components via EntityManager. You'd rather do it after update to not break the group (you'll get error about accessing deallocated nativearray), so you want to use PostUpdateCommands (EntityCommandBuffer). More about that in one of futures part of article.
EntityManager is not weird, magic class, it's ScriptBehaviourManager and "merges" entities and their components. In ECS we have a lot of managers. ComponentSystem is also ScriptBehaviourManager ! World holds all managers in one piece. We could colloquially say it manages the managers. I know what's your question - yes, we can create multiple worlds, sounds interesting, isn't it? Maybe we'll take a look at this in future.
The difference is trivial, ComponentData is just a component, SharedComponentData is as it says, component shared between different Entities. Very good explanation you can read in docs:
IComponentData is appropriate for data that varies between Entities, such as storing a world position. ISharedComponentData is useful when many Entities have something in common, for example in the boid demo we instantiate many Entities from the same Prefab and thus the MeshInstanceRenderer between many boid Entities is exactly the same
So, with same IComponentData (eg. Position) changes from Entity0 won't change Position from Entity1, but with same SharedComponent (eg. Renderer) if you change material from Entity0, it'll change also material from Entity1. However you don't really want to change SharedComponents a lot, actually very rarely. More details THERE. Well, there is one more difference - ComponentData have to be blittable.
Give me some feedback in comment section, don't worry I won't hate you if you show me some "anomaly" in my article. If you enjoy my article - like it and follow me. It'll motivate me to write more articles. See you.
Originally published at: https://connect.unity.com/p/part-1-unity-ecs-briefly-about-ecs
Read more about:
BlogsYou May Also Like