Entity Component System and Game AI techniques

Maxim Zaks
4 min readSep 23, 2019

--

Over the decades game programmers developed multiple techniques to formalise and help solve the problem of implementing an intelligent and fun NPC. Most known techniques are:

  • (Finite) state machines
  • Behaviour trees

Those techniques help game programmers and game designers to iterate on the implementation of NPC behaviour and also being able to reason about it.

With the growing popularity of ECS (Entity Component System) the question arises: Are those techniques compatible with ECS?

I think they are, even though we need to examine, at what cost.

Lets start with state machines

State machine is a very nice choice if you can identify discrete states of an NPC and if you need to limit the possibility to transition from one state to another. Often we can also define the events / actions which will be responsible for state transformation and events / actions which will trigger when a transformation was performed.

In ECS the state is represented with components, which are associated by an entity. State manipulation is performed by systems, which query entities by component type. In ECS an entity can be associated with only one instance of a certain component type, but as we can have “infinite” amount of component types, the state space becomes infinite as well.

Lets have a look at a more practical example

A traffic light can have 3 states, Red, Yellow, Green. If we define flag components for every state, we can add all three components to the same entity, breaking our logic. In order to put a constraint on the state, we can define just one component: TrafficLightStateComponent, which holds a value of an enum TrafficLightState which have 3 cases red, yellow, green. This way, we can make sure that an entity, which represents a traffic light can be only in one valid state.

What about constraints in regard to state transformation?

Say we want to make sure that red can not change directly to green without being in the yellow state. This is actually much more complicated. What we could do is to implement TrafficLightStateComponent in a way that developers can’t set the value directly, but only use public mutating methods, which will check, if the transition we want to perform, is plausible.

How about performing actions on state change?

A state change in our ECS scenario is a component value update. There is a concept of reactive systems, where a system (or rather a certain code in the system) is executed not on every tick, but only on one tick, after a change in entity state has happened.

Possible implementation in Unity ECS

What I described in the last couple of paragraphs can be implemented in a reasonable amount of time by a skilled programmer, however as I mentioned the AI techniques are build not only to make programmers happy, but also empower game designers and help both parties understand a complex NPC behaviour, by visualising current state in running application.

In order to achieve all this, we need an editor tool, which will let us define states and state transformations. This tool should also provide a possibility to generate component type representing the states and the methods for valid state transformation. This tool could also generate the infrastructure for reactive systems. And last but not least, it should provide a possibility to select an entity with the state type at runtime and see which state it is currently in.

Behaviour trees

In my humble opinion behaviour trees are a great way to make control flow of a complex algorithm, configurable and “express-able” on a certain level of abstraction. Everything we can do with a behaviour tree, can be done with general purpose programming language, but than it is not access-able to game designers and it is harder to evaluate, specifically if you have tools to visualise a behaviour tree state at runtime.

Projecting the idea on ECS, we realise that behaviour tree could represent the internal code of a system. The leaf nodes (Action and Conditions) of the behaviour tree could work directly on the entity world, or a copy of the values from the entity world.

There are lots of interesting question though

  • Should the tree be triggered on every tick?
  • Should we support the running node state and while triggering the tree, it should jump directly to the last running node?
  • Should the nodes operate on a group of entities, or on a single entity?
  • Should we make trees run in parallel for every entity by using tasks?
  • How should the tree be represented (in the editor)?
  • Should the tree nodes have their own parameters / state, or should everything be defined with components and entities?

Those are all excellent questions and IMHO it is really hard to give a definitive answer. I guess, the only sane answer is:

Depends on the Behaviour Tree Tooling you envision.

You need to identify, the actual benefit you want to get by expressing an NPC algorithm with behaviour tree. And than the benefits and pitfalls the restriction of ECS brings to the table. And never forget:

If it doesn’t fit, don’t force it.

--

--

Maxim Zaks

Tells computers how to waste electricity. Hopefully in efficient, or at least useful way.