How we used Entity Component System (ECS) approach at Gemserk - 2/2

So, after our first attempt on using ECS, when we started to develop mobile games and moved to the LibGDX framework, we decided to abandon our ComponentsEngine and start over.

We were still reading about ECS while we were creating our set of tools and code over LibGDX. At some point in time, some of the Java community developers started Artemis, a lightweight ECS, and we decided to give it a try.

Artemis

This is a simplified core architecture diagram:

Note: we used a modified version of Artemis with some additions like enable/disable an Entity.

In this pure approach, Entities and Components are just data, and they are related by identifiers, like these tables in a relational database:

Where we have two entities, both with a PositionComponent and only one of them with MovementComponent.

An example of this components in code:

public class PositionComponent : Component {
    public float x, y;
}

public class MovementComponent: Component {
    public float speed;
}

EntitySystems perform the game logic. They normally work on a subset of Components from an Entity but they could need it in order to enable/disable/destroy it (if it is part of its logic).

An example of a System is LimitLinearVelocitySystem, used in multiple of our games to limit the physics velocity of an Entity with PhysicsComponent and LimitVelocityLimitComponent:

public void process(Entity e) {
    PhysicsComponent physicsComponent = 
                     Components.getPhysicsComponent(e);
    Body body = physicsComponent.getPhysics().getBody();

    LinearVelocityLimitComponent limitComponent = 
             e.getComponent(LinearVelocityLimitComponent.class);
    Vector2 linearVelocity = body.getLinearVelocity();

    float speed = linearVelocity.len();
    float maxSpeed = limitComponent.getLimit();

    if (speed > maxSpeed) {
        float factor = maxSpeed / speed;
        linearVelocity.mul(factor);
        body.setLinearVelocity(linearVelocity);
    }
}

There are some extra classes like the TagManager which allows assigning a unique string identifier to an Entity in order to find it, and the GroupManager which allows adding entities to groups identified by a name, which is more like how tags are used everywhere else.

Even though it could look similar to our ComponentsEngine where the Properties in that engine correspond to the Components in this one, and Components to Systems, there is an important difference: Systems are not part of an Entity and work horizontally over all entities with specific Components (data). So, in this approach, changing only data from entities indeed change their behaviour in the game, so it is really data driven.

Since Entities and Components are just data, their instances in memory are easier to reuse. An Entity is just an id, so it is obvious. A Component is a set of data that doesn't care too much which Entity it belongs to. So, after the Entity doesn't need it anymore, it could be reused elsewhere, improving a lot memory usage and garbage collection.

Artemis, and other pure ECS implementations, are really lightweight and performant frameworks. The real power comes from the Systems and Components built over them. In our case, we created a lot of Systems that we started to reuse between games, from SuperFlyingThing to VampireRunner and even in Clash of the Olympians.

Scripting

One of the most interesting ones is the Scripting framework we created over Artemis. It was really useful and gave us a lot of power to overcome some of the limitations we were facing with the pure approach when we need to create a specific logic for a specific moment during the game and (probably) never again and we didn't want a System for that.

They work similar to Unity MonoBehaviours and our logic Components from ComponentsEngine, and they also belong to the Entity lifecycle. One difference, however, is that they try to avoid storing data in their instances as much as possible and instead try to store and read data from Components, like Systems do.

Here is an example Script from one of our games:

public class MovementScript extends ScriptJavaImpl {
	
  @Override
  public void update(World world, Entity e) {

    MovementComponent movementComponent = Components.getMovementComponent(e);
    SpatialComponent spatialComponent = Components.getSpatialComponent(e);
    ControllerComponent controllerComponent = Components.getControllerComponent(e);
		
    Controller controller = controllerComponent.controller;
    Movement movement = movementComponent.getMovement();
    Spatial spatial = spatialComponent.getSpatial();
		
    float rotationAngle = controllerComponent.rotationSpeed * GlobalTime.getDelta();
		
    Vector2 linearVelocity = movement.getLinearVelocity();
		
    if (controller.left) {
        spatial.setAngle(spatial.getAngle() + rotationAngle);
        linearVelocity.rotate(rotationAngle);
    } else if (controller.right) {
        spatial.setAngle(spatial.getAngle() - rotationAngle);
        linearVelocity.rotate(-rotationAngle);
    }
		
  }
	
}

Note: GlobalTime.getDelta() is similar to Unity's Time API.

One problem about the Scripting framework is that it is not always clear when some logic should be in a Script or a System, and that made reusability a bit harder. In the case of the example above, it is obvious it should be moved to a System.

Templates

Another useful thing we did over Artemis was using templates to build entities in a specific way, similar to what we had in ComponentsEngine.

We used also a concept of Parameters in templates in order to customize parts of them. Similar to ComponentsEngine, templates could apply other templates and different templates could be applied to the same Entity.

Here is an example of an Entity template:

public void apply(Entity entity) {

    String id = parameters.get("id");
    String targetPortalId = parameters.get("targetPortalId");
    String spriteId = parameters.get("sprite", "PortalSprite");
    Spatial spatial = parameters.get("spatial");
    Script script = parameters.get("script", new PortalScript());

    Sprite sprite = resourceManager.getResourceValue(spriteId);

    entity.addComponent(new TagComponent(id));
    entity.addComponent(new SpriteComponent(sprite, Colors.darkBlue));
    entity.addComponent(new Components.PortalComponent(targetPortalId, spatial.getAngle()));
    entity.addComponent(new RenderableComponent(-5));
    entity.addComponent(new SpatialComponent(spatial));
    entity.addComponent(new ScriptComponent(script));

    Body body = bodyBuilder //
            .fixture(bodyBuilder.fixtureDefBuilder() //
                    .circleShape(spatial.getWidth() * 0.35f) //
                    .categoryBits(CategoryBits.ObstacleCategoryBits) //
                    .maskBits((short) (CategoryBits.AllCategoryBits & ~CategoryBits.ObstacleCategoryBits)) //
                    .sensor()) //
            .position(spatial.getX(), spatial.getY()) //
            .mass(1f) //
            .type(BodyType.StaticBody) //
            .userData(entity) //
            .build();

    entity.addComponent(new PhysicsComponent(new PhysicsImpl(body)));

}

That template configures a Portal entity in SuperFlyingThing which teleports the main ship from one place to another. Click here for the list of templates used in that game.

Interacting with other systems

Sometimes you already have a solution for something, like the physics engine, and you want to integrate it with the ECS. The way we found was to create a way to synchronize data from that system to the ECS and vice versa, sometimes having to replicate a bit of data in order to have it easier for the game to use it.

Finally

Even though we had to do some modifications and we know it could still be improved, we loved using a pure ECS in the way we did.

It was used to build different kind of games/prototypes and even a full game like the Clash of the Olympians for mobile devices, and it worked pretty well.

What about now?

Right now we are not using any of this in Unity. However we never lost interest nor feith in ECS, and there are starting to appear new solutions over Unity in the last years that caught our attention. Entitas is one of them. The Unity team is working towards this path too as shown in this video. Someone who din't want to wait started implementing that solution in his own way. We've also watched some Unite and GDC talks about using this approach in big games and some of them even have a Scripting layer too, which is awesome since, in some way, it validates we weren't so wrong ;).

I am exited to try ECS approach again in the near future. I believe it could be a really good foundation for multiplayer games and that is something I'm really interested in doing at some point in my life.

Thanks for reading.

References

 

 

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

How we used Entity Component System (ECS) approach at Gemserk - 1/2

When we started Gemserk eight years ago, we didn't know which was the best way to make games. So before starting, we did some research. After reading some articles and presentations we were really interested in trying an Entity Component System (ECS) approach for our games. However, since we didn't find a clear guide or implementation at that point we had to create our own solution while exploring and understanding it. We named our engine ComponentsEngine.

Components Engine

The following image shows a simplified core architecture diagram:

Note: part of the design was inspired by a Flash ECS engine named PushButtonEngine.

An Entity is just a holder of state and logic. In an ECS, anything can be an Entity, from an enemy ship to the concept of a player or even a file path to a level definition. It depends a lot on the game you are making and how you want to structure it.

A Property is part of the state of an Entity, like the health or the position in the world, anything that means something for the state of the game. It can be accessed and modified from outside.

Components perform logic updating one or more Properties to change the Entity state. A component could for example change the position of an Entity given a speed and a moving direction.

They normally communicate with each other either by modifying common Properties (when on the same Entity) or by sending and receiving Messages through a MessageDispatcher (when on the same or on different Entities). They just have to register a method to handle a message. In some way, this is pretty similar to using SendMessage() method in Unity and having the proper methods in the MonoBehaviours that need to react to those messages.

EntityTemplates are an easy way to define and build specific game entities, they just add Properties and Components (and more stuff) to make an Entity behave in one way or another.

For example, a ShipTemplate could add position, velocity and health properties and some components to perform movement and to process damage from bullet hits:

public void build() {
        // ... more stuff 
        property("position", new Vector2f(0, 0));
        property("direction", new Vector2f(1, 0));

        property("speed", 5.0f);

        property("currentHealth", 100.0f);
        property("maxHealth", 100.0f);

        component(new MovementComponent());
        component(new HealthComponent());
}

An example of the MovementComponent:

public class MovementComponent() {

   @EntityProperty
   Vector2f position;

   @EntityProperty
   Vector2f direction;

   @EntityProperty
   Float speed;

   @Handles
   public void update(Message message) {
      Property<Float> dt = message.getProperty("deltaTime");
      position += direction * speed * dt.get();
   }

}

In some way, EntityTemplates are similar to Unity Prefabs or Unreal Engine Blueprints, represeting in some way a (not pure) Prototype pattern.

Some interesting stuff of our engine:

  • Since templates are applied to Entities, we can apply multiple templates to the same one. In this way, we could have common templates to add generic features like motion for example. So we could do something like OrcTemplate.apply(e) to add the orc properties and components and then MovableTemplate.apply(e), so now we have an Orc that moves.
  • Templates can apply other templates inside them. So we could do the same as before but inside OrcTemplate, we could apply MovableTemplate there. Or even use this to create specific templates, like OrcBossTemplate which is an Orc with a special ability.
  • Entities have also tags which are defined when applying a template too and are used to quickly identify entities of interest. For example, if we want to identify all bullets in the game, we could add the tag "Bullet" during the Entity creation and then, when processing a special power, we get all the bullets in the scene and make them explode. Note: in some ECS a "flag" component is used for this purpose.
  • The Property abstraction is really powerful, it can be implemented in any way, for example, an expression property like "my current health is my speed * 2". We used that while prototyping.

Some bad stuff:

  • Execution speed wasn't good, we had a lot of layers in the middle, a lot of reflection, send and receive messages (even for the update method), a lot of boxing and unboxing, etc. It worked ok in desktop but wasn't a viable solution for mobile devices.
  • The logic started to be distributed all around and it wasn't easy to reuse, and we started to have tons of special cases, when we couldn't reuse something we simply copy-pasted and changed it.
  • There was a lot of code in the Components to get/set properties instead of just doing the important logic.
  • Indirection in Properties code was powerful but we end up with stuff like this (and we didn't like it since it was too much code overhead):
e.getProperty("key").value = e.getProperty("key").value + 1.
  • We didn't manage to have a good data driven approach which is one of the best points of ECS. In order to have different behaviours we were forced to add both properties, components and even tags instead of just changing data.

Note: Some of these points can be improved but we never worked on that.

Even though we don't think the achitecture is bad, it guided us to do stuff in a way we didn't like it and didn't scale. We feel that Unity does the same thing with its GameObjects and MonoBehaviours, all the examples in their documentation go in that direction.

That was our first try to the ECS approach. In case you are interested, ComponentsEngine and all the games we did with it are on Github and even though they are probably not compiling, they could be used as reference.

This post will continue with how we later transitioned to use a more pure approach with Artemis, when we were more dedicated to mobile games.

References

Evolve your hierarchy - Classic article about Entity Component System.

PushButtonEngine - Flash Entity Component System we used as reference when developing our ComponentsEngine.

Game architecture is different - A quick transformation from normal game architecture to ECS.

Slick2D - The game library we were using during ComponentsEngine development.

 

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

Assigning interface dependencies to MonoBehaviour fields in Unity Editor

In Unity, Object's public fields of type interface are not serialized, so that means it is not possible to configure them using the editor like you do with other stuff like dependencies to MonoBehaviours.

One possible way to deflect this problem is to create an abstract MonoBehaviour and depend on that instead:

 public abstract class ServiceBase : MonoBehaviour
 {
     public abstract void DoStuff();    
 }
 
 public class ServiceUser : MonoBehaviour
 {
     public ServiceBase service;
 
     void Update()
     {
         service.DoStuff ();
     }
 }

This solution has some limitations. One of them is you can't create a sub class of multiple base classes like you do when implementing interfaces. Another limitation is that you can't easily switch between a MonoBehaviour implementation to a ScriptableObject implementation (or any other).

Working on Iron Marines and Dashy Ninja, I normally end up referencing a UnityEngine.Object and then in runtime I try to get the specific interface, like this:

 public interface IService 
 {
      void DoStuff();
 }
 
 public class CharacterExample : MonoBehaviour
 {
     public UnityEngine.Object objectWithInterface;
     IService _service;
 
     void Start ()
     {
         var referenceGameObject = objectWithInterface as GameObject;
         if (referenceGameObject != null) {
             _service = referenceGameObject.GetComponentInChildren<IService> ();
         } else {
             _service = objectWithInterface as IService;
         }
     }

     void Update()
     {
         _service.DoStuff ();
     }
 }
 

Then, in Unity Editor I can assign both GameObjects and ScriptableObjects (or any other Object):

That works pretty well but I end up having the code of how to get the interface duplicated all around.

To avoid that, I made up two helper classes with the code to retrieve the interface from the proper location. These are InterfaceReference and InterfaceObject<T>.

InterfaceReference

 [Serializable]
 public class InterfaceReference
 {
     public UnityEngine.Object _object; 
     object _cachedGameObject;
 
     public T Get<T>() where T : class
     {
         if (_object == null)
             return _cachedGameObject as T;

         var go = _object as GameObject;
 
         if (go != null) {
             _cachedGameObject = go.GetComponentInChildren<T> ();
         } else {
             _cachedGameObject = _object;
         }
 
         return _cachedGameObject as T;
     }

     public void Set<T>(T t) where T : class
     {
         _cachedGameObject = t;
         _object = t as UnityEngine.Object;
     }
 }

Usage example:

 public class CharacterExample : MonoBehaviour
 {
     public InterfaceReference service;
 
     void Update()
     {
         // some logic
         service.Get<IService>().DoStuff();
     }
 }

The advantage of this class is that it could be simply used anywhere and it is already serialized by Unity. But the disadvantage is having to ask for specific interface when calling the Get() method. If that is only in one place, great, but if you have to do it a lot in the code it doesn't look so good. In that case, it could be better to have another field and assign it once in Awake() or Start() methods.

InterfaceObject

 public class InterfaceObject<T> where T : class
 {
     public UnityEngine.Object _object;
     T _instance;
 
     public T Get() {
         if (_instance == null) {
             var go = _object as GameObject;
             if (go != null) {
                 _instance = go.GetComponentInChildren<T> ();
             } else {
                 _instance = _object as T;
             }
         }
         return _instance;
     }
 
     public void Set(T t) {
         _instance = t;
         _object = t as UnityEngine.Object;
     }
 }

Note: the Get() and Set() methods could be a C# Property also, which would be useful to allow the debugger to evaluate the property when inspecting it.

Usage example:

 [Serializable]
 public class IServiceObject : InterfaceObject<IService>
 {
     
 }
 
 public class CharacterExample : MonoBehaviour
 {
     public IServiceObject service;
 
     void Update()
     {
         // some logic
         service.Get().DoStuff();
     }
 }

The advantage of this class is that you can use the Get() method without having to cast to the specific interface. The disadvantage, however, is that it is not serializable because it is a generic class. In order to solve that, an empty implementation with a specific type must be created to allow Unity to serialize it, like it is shown in the previous example. If you don't have a lot of interfaces you want to configure, then I believe this could be a good solution.

All of this is simple but useful code to help configuring stuff in the Unity Editor.

I am working on different experiments on how to improve Unity's usage for me. Here is a link to the project in case you are interested in taking a look.

Thanks for reading

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)

We are working on a new Game for mobile devices named Dashy Ninja

After the last Ludum Dare#38 we were really excited about what we accomplished and decided to work on something together in our spare time. So, we started working on a new Unity game for mobile devices currently named Dashy Ninja.

This game is about a Cat facing the most difficult and challenging trials to achieve the unachievable and go where no other Cat has gone before to become the ultimate Ninja Cat.

The mechanics of the game are simple, by making quick drag gestures the cute cat dashes through the level attaching itself to platforms on the way. If a trap gets the character, it is "magically teleported back" (no animals were harmed in the making this blog post) and starts over again. The player has to feel as Ninja as possible.

We wanted to make a proper introduction of the game so we can start sharing dev stuff of the most awesome Ninja Cat in the Universe.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)