Entity Component System

What is (an) ECS?

  • unnecessary
  • useful
  • not a system

What are entities?

lol1

What are entities?

aoe2

What are entities?

  • Objects in a game (or simulation)
  • Can have different behaviours
  • Basically everything

INHERITANCE

Inheritance

graph TD; Entity-->MoveableEntity; Entity-->PhysicsEntity;

Inheritance

graph TD; Entity-->MoveableEntity; Entity-->PhysicsEntity; MoveableEntity-->Character; PhysicsEntity-->BoxColliderEntity;

Inheritance

graph TD; Entity-->MoveableEntity; Entity-->PhysicsEntity; MoveableEntity-->Character; Character-->Player; Character-->NPC; PhysicsEntity-->BoxColliderEntity;

Godot

GodotInheritance 3

Godot Code

class Node2D : public CanvasItem {
...
}
.
.
.
class PhysicsBody2D : public CollisionObject2D {
...
}
class CharacterBody2D : public PhysicsBody2D {
...
}

4

Inheritance

graph TD; Entity-->MoveableEntity; Entity-->PhysicsEntity; MoveableEntity-->Character; Character-->Player; Character-->NPC; PhysicsEntity-->BoxColliderEntity; MoveableEntity-->Vehicle;

Multiple Inheritance

graph TD; Entity-->MoveableEntity; Entity-->PhysicsEntity; MoveableEntity-->Character; Character-->Player; Character-->NPC; PhysicsEntity-->BoxColliderEntity; MoveableEntity-->Vehicle; BoxColliderEntity-->Vehicle;

Godot

  • uses hierarchy instead
  • child nodes as "components"

What are components?

  • Split entities from behaviour
  • Data associated with a certain "behaviour"

COMPOSITION

Composition

graph LR; EntityA-->BoxColliderComponent; EntityA-->StaticMeshComponent; EntityB-->SphereColliderComponent; EntityB-->DynamicMeshComponent; EntityB-->PlayerControllerComponent; linkStyle default stroke:lime,stroke-width:4px;

Composition

  • Entities have minimal data and behaviour
  • Entities hold their components or references to them
class Component;

class Entity {
//...
private:
    std::unordered_map<std::type_info, Component*> m_components;
}

Unreal

Code in Unreal’s AActor class5:

/**
* All ActorComponents owned by this Actor. Stored as a Set as actors may have a large number of components
* @see GetComponents()
*/
TSet<TObjectPtr<UActorComponent>> OwnedComponents;

/**
* Get all components derived from class 'ComponentType' and fill in the OutComponents array with the result.
* It's recommended to use TArrays with a TInlineAllocator to potentially avoid memory allocation costs.
* TInlineComponentArray is defined to make this easier, for example:
* {
*     TInlineComponentArray<UPrimitiveComponent*> PrimComponents(Actor);
* }
*
* @param bIncludeFromChildActors   If true then recurse in to ChildActor components and find components of the appropriate type in those Actors as well
*/
template<class ComponentType, class AllocatorType>
void GetComponents(TArray<ComponentType, AllocatorType>& OutComponents, bool bIncludeFromChildActors = false) const
{
    typedef TPointedToType<ComponentType> T;

    OutComponents.Reset();
    ForEachComponent_Internal<T>(T::StaticClass(), bIncludeFromChildActors, [&](T* InComp)
    {
        OutComponents.Add(InComp);
    });
}

Unity

6

What are systems?

  • ███████████████████
  • █████████████████
  • ████████████████████

Entity Component System

Entity Component System

  • split components even more from entities
  • entities are minimal data
  • components store data associated with certain behaviours
  • components aren't managed by their entities

What are systems?

  • main way of interacting with components
  • loop over every component of a type
  • e.g. Rendering System, Physics System...

Examples:

One thing known to most is that EnTT is also used in Minecraft. Given that the game is available literally everywhere, I can confidently say that the library has been sufficiently tested on every platform that can come to mind.

Cache

CPU L1 L2 L3
Pentium N4200 96 KiB 128 KiB 2 MiB
i7 14700HX 1800 KB 28 MB 33 MB

How to implement it in C++

Entities:

//one possibility
typedef uint_32t UID;

typedef UID Entity;

How to implement it in C++

Components:

A std::flat_map is a fitting datatype.

GCC libstdc++ Clang libc++ MSVC STL
not implemented partially implemented not implemented

7

How to implement it in C++

Components:

class ComponentManager{
    template<typename comp_type> requires std::is_base_of<Component, comp_type>
    foreachComponent(std::function func){
    //...
    }

    template<typename comp_type> requires std::is_base_of<Component, comp_type>
    addComponentToEntity(Entity entity){
    //...
    }

    //some type of ComponentMap store
}

How to implement it in C++

ComponentMap:

template <typename component_type>
class ComponentMap
    std::vector<component_type> m_values;
    std::unordered_map<Entity, size_type> m_mapping;

  1. https://br.ign.com/league-of-legends-wild-rift/89123/feature/wild-rift-tudo-sobre-o-lol-mobile ; Image: Riot Games ↩︎

  2. https://pressakey.com/gameinfos,4981,screenshots,,,Age-of-Empires-Definitive-Edition,.html ↩︎

  3. Screenshot: Godot Engine ↩︎

  4. https://github.com/godotengine/godot ↩︎

  5. Engine/Source/Runtime/Engine/Classes/GameFramework/Actor.h ↩︎

  6. https://docs.unity3d.com/6000.0/Documentation/Manual/UsingTheInspector.html ↩︎

  7. https://en.cppreference.com/w/cpp/compiler_support/23 ↩︎