Ask the Unity expert: what is the ECS?

In this, the first in a series of posts on the topic, we’ll explain what Unity’s ECS is and what it can do for your game.

The headline benefit of Unity’s ECS is performance-by-default. To achieve this, ECS moves away from traditional object-oriented programming (that is, the GameObject and MonoBehaviour centred workflow that most Unity developers are familiar with), and towards data-oriented design. To demonstrate their differences, let’s compare how you build an object representing the player character with each approach:

A traditional object-oriented workflow.

Using object-oriented programming, you’d create a GameObject to represent the player character, then attach MonoBehaviours to give the GameObject functionality such as a player controller, health and physics attributes. These MonoBehaviours contain both the data (such as hit points) and the code that modifies that data (decrementing hit points when the player takes damage for instance).

Using data-oriented design, you’d create an entity to represent the player character, then attach components to store data. ECS components should not be confused with GameObject components, such as MonoBehaviours. Unlike GameObject components, ECS components don’t contain any logic, they only store data. The code we use to perform operations on entities and their components exist in the form of systems. Systems are scripts. They act, in bulk, on all of the entities and components in the world.

To continue our previous example of decrementing hit points, a system would group all entities that have health and damage components and decrement the affected components accordingly.

What are the benefits of the ECS?

The memory layout of data-oriented design ensures that the code generated by ECS performs significantly fewer jumps between memory addresses than traditional object-oriented programming.

Additionally, the memory layout induced by ECS allows for further code optimisations that leverage cache prefetching, the process your CPU uses to ensure it has the next bit of data already loaded into the cache by the time it needs it. The Unity ECS paradigm does this by using equally sized chunks of components that can be iterated over linearly. Rather than dealing with randomly stored objects of various sizes, the CPU only has to deal with these uniformly sized chunks stored linearly in the same area of memory. This makes the CPU’s job easier, a bit like playing Tetris with 1×1 blocks.

By decoupling data (entities and components) and logic (systems), the ECS also produces more modular, easy-to-read code. This particularly interests me as a developer working on Improbable’s SpatialOS Game Development Kit (GDK) for Unity, which is built on Unity’s ECS. The ECS conceptually mirrors the core concepts of SpatialOS (entities, components, and the workers that operate on them), making it a perfect fit for the SpatialOS GDK.

Why isn’t everyone using the ECS?

With all of these benefits, you might be wondering: why isn’t everyone using ECS? Firstly, ECS isn’t for everyone. At Improbable, we’re excited by it because it suits the massive, richly populated and persistent games that SpatialOS enables, but some games (turn-based strategy games for instance) simply don’t require this level of performance.

Secondly, ECS is still at an experimental stage of development. Most of Unity’s existing tooling and systems are still only designed to be used with GameObjects and MonoBehaviours.

ECS and MonoBehaviour workflows for SpatialOS

To alleviate these pain points, the SpatialOS GDK for Unity offers two workflow options:

  1. A MonoBehaviour-centric workflow that works with Unity’s fully developed MonoBehaviour tooling, workflow and APIs.
  2. An ECS workflow that takes advantage of the ECS development paradigm and associated performance improvements.

Crucially, these workflows are not mutually exclusive. Given the current lack of tooling around ECS, we anticipate that you’ll write most or all of your game using MonoBehaviours. Whichever workflow you choose, your game will still take advantage of the performant GDK core module, which we’ve written using the ECS. Our goal is to bring you the benefits of ECS as early as possible, by means of our own API and abstraction layer. This approach will shelter you from most of the breaking changes that Unity makes to their ECS, so you can focus on writing your game however you’d like to.

In the next post, we’ll explore both workflows in detail, and examine code examples of each. Until then, here are some more resources on Unity’s ECS and Improbable’s SpatialOS GDK for Unity.

ECS resource list

This article was originally published on 24 September 2018 on improbable.io