I've been using ECS for a while, at the moment I'm using my own, but it's pretty standard. Components are data only, Entities pretty much just a Map with some additional metadata and Systems that match combinations of components and contain the logic.

You have combinations of components that result in the more general functionality. For example Position + Graphics gives me some nice static background image. Position + Graphics + Physics gives me a entity that can move around etc etc

This question is about the various options for implementing more specific game logic.

But say I want to implement a Door. It has Position, Graphics and a Collidable Hull but it needs 2 states, open and closed. When its open it has texture A and its Collidable Hull is disabled, and when its closed it has texture B and its Collidable Hull is enabled. Lets say the state change should be triggered across some internal channel in the engine.

What are the options for implementing this state change?

Option 1 is to create Door component, with say 2 variables, door state and state change channel. I'd also need a door system that handled the logic to manipulate the components when it receive the open/close message.

Option 2 would be to create a FSM. The FSM is probably also a component with a corresponding FSM System. Logic and state would need to reside somewhere, possibly by sub-classing the FSM or having a generic property map in the FSM and static logic functions for the Door defined elsewhere.

There are more exotic alternatives to FSM's i.e. Actions Lists or Behaviour trees, but they are similar to option 2.

What considerations are there for choosing a full component/system over an more generic FSM type solution? What if I had 100 different game objects with different behaviours? Would you really expect 100 component/system pairs for each one or would you try and create a more generalized solution? Are there any other options?


3 Answers 3


I've tried both pure approaches in the past and, not surprisingly, I've found a hybrid approach is best. I tend to create a lot of custom components for individual entities and use a FSM when I need to change a lot of entities at once.

Almost always, the FSM really only cares about one common aspect of the collection of entities. For example, if the components are locked or not, or if they are in their start position, or some heighten state position. So, mostly, the FSM is implemented by adding an abstraction to each of the custom components that handles that aspect and then using the abstraction in the FSM.

In the door example, I would build a custom component that handles the door logic. Imagine the size of it (tiny), and it will do exactly what you want. Now imagine some generic component that will work for your door as well as a toaster. This case is certainly more complicated than the first component and probably doesn't do what you want and is impossible to change.


I would rather treat the component system a means to invoke logic and nothing more. Instead, you design a generic component that manages a logical boolean state of 0/1. As the component's state transitions to 1, you fire the activated script. As it transitions to 0, you fire the deactivated script.

The benefit here is whatever logic you need is external to the ECS as the component is merely a means to invoking logic, regardless what it may be.

In fact, the component could have a time factor associated to the transition so that it takes X number of frames or nanoseconds to transition and allows for a tri-state like script executor rather than just two.

Now this component can work for doors, switches, vertical/horizontal moving platforms, flashing lights, etc. Basically anything that manages 2 or even 3 states.

  • 1
    \$\begingroup\$ Ok, so you have a totally generic State Component. But where does the Door logic live and how is it associated with that entity? Would you have a generic FSM component to hold the script and an associated system? \$\endgroup\$
    – rje
    Commented Nov 5, 2015 at 8:55
  • \$\begingroup\$ Assuming Lua was your scripting language, the component would harbor two Lua scripts, one to fire when the component is first placed in active state and one when the component is first placed in inactive state. The scripts (open_door.lua, close_door.lua) contain your logic for your door. The component itself is the FSM interface that allows you to toggle between running two scripts to perform whatever activity you need. In other words, think of the scripts as your leaves in a behavior tree and the component as an inner node. \$\endgroup\$
    – Naros
    Commented Nov 5, 2015 at 13:46

So not an answer per se but an insight. Apples GameplayKit has an implementation that allows you to use a component to encapsulate logic and systems to manage the timing of component updates in relation to other systems. The entities themselves are able to update all of their components without the need for a system at all. My personal addition to this kit allows for the concept of systemic components that, if managed by a system, are ignored by entity updates. My editor is able to update components that need to update themselves during editing by declaring systems of that type and avoid all systems and all entity updates in general since we are not running gameplay systems all the time.

If you want to use a system for components that are specifically data structures then the logic can be included in the system like any traditional ECS. Having entity driven component updates may not be the most data efficient method but I find having the option and a precise method of handling components when a system is introduced makes it trivial to build and debug an entity when components run into conflicts. With a system driven system it is harder to manage simple entity driven updates since all each requires a system to run on instead of their own update method.

They provide a generic Entity, Component and ComponentSystem classes that all contain an update(seconds) method. Creating a new system can be as simple as initializing one for a certain type of component subclass and adding the component with a call addComponent(foundIn: Entity). My subclass manages each component’s isSystemic var and allows you to call update on a specific entity or component system if it needs to process changes.

Sometimes data processing requires efficient systems but during prototyping and development flexibility is key to get an idea working. Not saying this is the best approach but it’s very flexible toolset.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .