I have been using Entities for a while now and there’s one recurring pattern that I do not really know how to gracefully handle in DOTS: The management of dependencies / need / requests.
Simple Scenario: Many systems require the game to be paused. At the moment, I would add a PauseNeed to the entity that needs it and as long as there are needs, the PauseNeedSystem would act as a gate keeper to keep the game paused until the count of needs fall to zero (then it would unpause). There are downsides to handling things like that:
For all Entities with dependance, this require a “need” component tag for each usage. Here there is Pause, but on a big game you may have hundreds of tags for dealing with that. For instance, showing up an Health bar, shaking the camera, rumbling the controller, dimming the screen or anything bound to gameplay events.
The System that check the count of needs run every frame.
I wonder if there should be a some type of component / interface that handle that. For instance, for the above scenario, I could retrieve the Pause component and do something like: pause.AddNeed() when I need it, pause.RemoveNeed() when I don’t. Adding would in the background increment an int. At 0, Pause would Disable, at >0, Pause would Enable. Enable and Disable coule be tags or filters.
In a ForEach, that would look like: Entities.WithEnabledComponent. Even better if I can filter things that were just enabled or just disabled.
How do you all deal with this kind of use case? We are doing it many ways for user interace, time scale, post processing, so I really wonder if there should be a built-in, or at least suggest approach for dealing with dependencies.
They have been working on adding an enabled state to components for quite some time, although I’m not sure when it will make it into a release:
For your use case, I would consider creating a singleton entity with a DynamicBuffer where each PauseNeed component has an entity reference. Then your pause system can just check if the buffer is empty or not before doing any work.
If you need run some systems when the game on pause and opposite when the game not paused why not have just singleton GameOnPause and use it in RequireSingletonForUpdate in systems which should run on pause and early out on HasSingleton? Or it can be processed not like singleton but like EntityQuery for combining EntityQueryDesc.
I used the pause as a simple example. I could use the health bar which is a bit more complex. It must be displayed if:
Under 25% of Health
The player receives damage
The player heals
The game is paused
So when over 25% of Health, I may call “Hide” on its Ui, but that doesn’t mean others don’t need it displayed. At the moment, this require a gatekeeper that handles requests to show and hide. That kind of pattern is recurring and I therefore believe it should be simpler to do than:
HealthBarRequest with a stored entity
Dynamic buffer of HealthBarRequesters
HealthBarRequestSystem that hides the ui when when the buffer become empty
That pattern is generic enough to me to maybe become its own kind of component data. Some kind of ForEach could only be run if one component “needs” another, if that makes sense?
If you need per entity basis, and states don’t change often, then use components tags, to filter entities out. (i.e. is alive tag, is returning home tag, is refueling tag )
If changing frequently, you can just use bool, while iterating though entities.
(i.e. is shooting, is turning jumping, is turning )