top of page
Richard Bradley

ECS - Component System (Part 4)

Updated: Sep 18, 2019

Component System


A Component System runs on Unity's main thread and therefore does not take advantage of multiple CPU cores. It generally performs operations on relevant entities and can not contain any instanced data, only methods.

Below is a template of a Component System, including all life cycle methods.

As you can see, to create a Component System you simply create a class and inherit from ComponentSystem. By doing this you gain access to life cycle methods and a few other goodies such as Entities.ForEach functionality.


Lets delve a little bit deeper and see what VS Code does when asked to implement the ComponentSystem's abstract class.

Well, it's clear as day that VS Code has only implemented the OnUpdate method, but why hasn't the other life cycle methods also been implemented?


To answer this we need to first look at the ComponentSystem class in detail, as shown below.

As you can see, VS Code is doing exactly what it should be doing by implementing all the abstract members, which in this case is just the OnUpdate method. It's also worth noting (while we are here) both the Entities and PostUpdateCommands members, as we will be utilising them later on in this tutorial.


So where are the other life cycle methods?


Deja vu is beautiful thing, with that in mind, lets take a look at the ComponentSystemBase class (which the ComponentSystem inherits from) and see if it can help with this conundrum.

Well this explains it, the remaining life cycle methods (highlighted above) are found in the ComponentSystemBase class and as they are virtual, can be optionally overridden. Because none of these members are abstract VS Code is not required to implement them.


So now we understand a little bit more about the behind the scene workings of a ComponentSystem, lets create a MoverSystem to see how to interact with entities.

Entities.ForEach


In the following example, imagine that we have already created and configured a set of entities with Translation, LocalToWorld, RenderMesh and MoveSpeedComponents attached.


Lets break this down.


The Entities member (gained from the ComponentSystem) exposes ForEach functionality which simplifies the task of iterating over a set of entities. The ForEach method takes a lambda function which takes up to six components as parameters with its main body performing any work required.


In the lambda function you will see that we are inputting two components, Translation and MoveSpeedComponent. ECS will feed any entities that 'contain' these components into this function and operate on them.


When the relevant entities get passed in, the body of the lambda multiplies the moveSpeedComponent value by Time.deltaTime (proof we are running on the main thread) and adds it to the translation.Value.y. This will have the effect of moving our entities upwards.


And that's it, this is all the system is responsible for doing. It may seem strange but its a good idea to have systems that specialise in one task and one task only as it helps when diagnosing bugs and keep your code nicely isolated and adaptive.


PostUpdateCommands

If you need to make changes to the structure of entities based on 'some logic', then you will need to add an Entity parameter to the ForEach method (as shown in the code snippet below).

If a logic test is true then you may wish to add/remove a component from an entity to signify that 'something' has happened. You should add these commands to the PostUpdateCommands (exposed by ComponentSystem) buffer as they will be executed after the loop has finished. This prevents you from changing data in the arrays you may be iterating over which would create a sync point that effects performance.

In the code below we will remove the MoveSpeedComponent on any entities whose translation.Value.y is greater than 10f. This will mean that this MoverSystem will no longer work on the aforementioned entities, as they would no longer fulfill the component requirements.


In order to achieve this we add our RemoveComponent commands to the PostUpdateCommands buffer as highlighted below.

And that's it, when an entity reaches a y position that is greater than 10f, it will stop moving.

Next up I will discuss the more complex JobComponentSystem and run though a few different jobs that can be used with it.


Until next time.


References

 
247 views0 comments

Recent Posts

See All

Comentários


bottom of page