Skip to content

Overview

Simon Schmid edited this page Jun 27, 2015 · 20 revisions

Overview

Entitas is fast, light and gets rid of unnecessary complexity. There are less than a handful classes you have to know to rocket start your game or application:

  • Entity
  • Pool
  • Group
  • Group Observer
+------------------+
|       Pool       |
|------------------|
|    e       e     |      +-----------+
|        e     e---|----> |  Entity   |
|  e        e      |      |-----------|
|     e  e       e |      | Component |
| e            e   |      |           |      +-----------+
|    e     e       |      | Component-|----> | Component |
|  e    e     e    |      |           |      |-----------|
|    e      e    e |      | Component |      |   Data    |
+------------------+      +-----------+      +-----------+
  |
  |
  |     +-------------+  Groups:
  |     |      e      |  Subsets of entities in the pool
  |     |   e     e   |  for blazing fast querying
  +---> |        +------------+
        |     e  |    |       |
        |  e     | e  |  e    |
        +--------|----+    e  |
                 |     e      |
                 |  e     e   |
                 +------------+

Entity

An entity is a container holding data to represent certain objects in your application. You can add, replace or remove data from entities in form of IComponent. Entities have corresponding events to let you know if components were added, replaced or removed.

Here's how you can interact with an entity. To enjoy a more natural and more readable API, simply use the code generator that comes with Entitas. In this example you can see some generated methods for PositionComponent, HealthComponent, MovableComponent.

entity.AddPosition(3, 7);
entity.AddHealth(100);
entity.isMovable = true;

entity.ReplacePosition(10, 100);
entity.ReplaceHealth(entity.health.health - 1);
entity.isMovable = false;

entity.RemovePosition();

var hasPos = entity.hasPosition;
var movable = entity.isMovable;

Pool

The Pool is the factory where you create and destroy entities. Use it to filter entities of interest.

// Pools.pool is kindly generated for you by the code generator
var pool = Pools.pool;
var entity = pool.CreateEntity();
entity.isMovable = true;

// Returns all entities having MovableComponent and PositionComponent.
// Matchers are also generated for you.
var entities = pool.GetEntities(Matcher.AllOf(Matcher.Movable, Matcher.Position));
foreach (var e in entities) {
    // do something
}

Group

Groups enable super quick filtering on all the entities in the pool. They are continuously updated when entities change and can return groups of entities instantly. Imagine you have thousands of entities and you only want those who have a PositionComponent - just ask the pool for this group, it already has the result waiting for you in no time.

pool.GetGroup(Matcher.Position).GetEntities();

Both the group and getting the entities is cached, so even calling this method multiple times is super fast. Always try to use goups when possible. pool.GetEntities(Matcher.Movable) internally uses groups, too.

Groups have events for OnEntityAdded, OnEntityWillBeRemoved and OnEntityRemoved to directly react to changes in the group.

pool.GetGroup(Matcher.Position).OnEntityAdded += (group, entity) => {
    // Do something
};

If you want to aggregate and process changes, consider using a Group Observer.

Group Observer

The Group Observer provides an easy way to react to changes in a group. Let's say you want to collect and process all the entities where a PositionComponent was added or replaced.

var group = pool.GetGroup(Matcher.Position);
var observer = group.CreateObserver(GroupEventType.OnEntityAdded);
foreach (var e in observer.collectedEntities) {
    // do something
}
observer.ClearCollectedEntities();

To stop observing, simply deactivate the observer.

observer.Deactivate();

Processing entities with Systems

Implement ISystem to process your entities. I recommend you create systems for each single task or behaviour in your application and execute them in a defined order. This helps to keep your app deterministic.

using Entitas;

public class MoveSystem : IExecuteSystem, ISetPool {
    Group _group;

    public void SetPool(Pool pool) {
        _group = pool.GetGroup(Matcher.AllOf(Matcher.Move, Matcher.Position));
    }

    public void Execute() {
        foreach (var e in _group.GetEntities()) {
            var move = e.move;
            var pos = e.position;
            e.ReplacePosition(pos.x, pos.y + move.speed, pos.z);
        }
    }
}

Entitas also provides a special system called ReactiveSystem, which is using an Group Observer under the hood. It holds changed entities of interest at your fingertips. Be sure to check out the example projects.

using Entitas;
using UnityEngine;

public class RenderPositionSystem : IReactiveSystem {
    public IMatcher GetTriggeringMatcher() {
        return Matcher.AllOf(Matcher.View, Matcher.Position);
    }

    public GroupEventType GetEventType() {
        return GroupEventType.OnEntityAdded;
    }

    public void Execute(Entity[] entities) {
        foreach (var e in entities) {
            var pos = e.position;
            e.view.gameObject.transform.position = new Vector3(pos.x, pos.y, pos.z);
        }
    }
}

Clone this wiki locally