ECS architecture & the state machine

I’ve recently been learning ECS and getting my head around DoD methodology, one question I have is around a State Machine replacement.


Imagine I have a realtime hack ‘n’ slash with a series of AI-driven monsters all running around independently. Now imagine the player opens up an inventory - with the desired effect of pausing the monsters behaviour. How would one architect this in ECS?


Do we give the monsters behaviour component a “paused” attribute and iterate through all of the monsters in the game setting it? Or…?

@GeorgeDoodlebug You might want to do your own research because I might have misunderstood some of the ECS stuff… but, AFAIK;
_
Archetypes are used to group entities that share the same components. Unity does this automatically (and at runtime) by grouping entities with the same components into an archetype. So, for example:

Fish Archetype
- Renderer Component
- Mesh Component
- Fish Health Component
- Pause Component

Vampire Archetype
- Renderer Component
- Mesh Component
- Vampire Health Component
- Pause Component

_
Although they are different archetypes they share similar components - namely a “pause” component. Now, this component should only hold the pure data needed to pause the monster. For example, an isPaused boolean or something. You might have a Pause Monster System that actually handles the pausing.
_
Now, onto the core of ECS… iteration. The “Pause Monster System” would iterate through each entity that has a “Pause Component” and write to that component (ie - set isPaused to true). It’s basically like saying “find all of the entities with a Pause Component and then do something”.

Unity has been publishing a lot of ECS/DOTS stuff from copenhagen 2019. Their Pong video (Getting started with DOTS: Scripting Pong (Tutorial) - YouTube) is a good place to start if you’re still struggling with the theory/how it works.
_
just as further clarification
_

  • Entities are like gameobjects. They represent “things” in your scene.
  • Components hold pure data.
  • Systems perform some kind of action on component data. For example, writing a new movement speed to an entity’s movement component. In this case, a Movement System would write to a Movement Component of a single or multiple Entities.

The other two answers are right. If you wanna do it in a more structured and manageable way, you can read my recent article that is designed for your exact scenario. In short, you put your systems in a ComponentSystemGroup and then control their execution there.


One approach is to disable every system that is doing runtime stuff (or only movement stuff if you’re lazy like me)

private StepPhysicsWorld stepPhysicsWorld;
private IncreaseVelocityOverTimeSystem increaseVelocityOverTimeSystem;

protected override void OnCreate()
{
    stepPhysicsWorld = World.GetOrCreateSystem<StepPhysicsWorld>();
    increaseVelocityOverTimeSystem = World.GetOrCreateSystem<IncreaseVelocityOverTimeSystem>();
}

protected override void OnUpdate() // From SystemBase
{
    if(Input.GetKeyDown(KeyCode.P))
    {
        stepPhysicsWorld.Enabled = !stepPhysicsWorld.Enabled;
        increaseVelocityOverTimeSystem.Enabled = !increaseVelocityOverTimeSystem.Enabled;
    }
}

But I concur, it is not ideal and if there is a better way I’d gladly hear.

Paused is a game UI state and not a monster state - as opposed to freezed, petrified or unconscious). So it doesn’t belong to IComponentData.

What you can do instead is to make relevant systems stop scheduling jobs while game is paused. This would probably include systems such as: monster locomotion, monster animation, decision making, decision execution (attacking, working etc) and also those changing values over time (health, hunger etc)

  • public class MyPausableSystem : SystemBase {
    protected override void OnUpdate ()
    {
    if( gameUiStateSource.isPaused ) return;

      job1.Schedule();
      job2.Schedule();
    

    }