David Ross's Blog Random thoughts of a coder

Entity-Component-System Part 1

13. October 2018 11:07 by David in

The Entity-Component-System pattern is utilised in many modern computer game engines so that game entities such a players, enemies, weapons, buildings, etc. are not built from specific classes within an inheritance hierarchy but are implemented as a collection of pluggable behaviours and state that can be added and removed at runtime.

Dynamic behaviour is hard

Dynamic languages like JavaScript are able to modify their class definition at runtime. Methods and fields can be added or removed with ease. By replacing, a method with a wrapper that calls the original method it is trivial to implement cross cutting concerns such as logging or firing data changed events. In contrast, statically typed languages objects are constrained by their compile time type.

I have used the complexity of modelling Bank Accounts in a number of posts over the years.  They are complex as Banks often market a diverse set of interest bearing accounts to their customers.  As part of the product definition the interest calculations can be defined based on on a large number of variables such as account type, the customer type, number of deposits or withdrawals during the month, the balance, fixed or variable terms and whether the account is linked to a credit card or mortgage.  Assuming that you model each type of Bank account as a separate class a factory is needed to choose the correct instance type by first looking up the customer’s configuration and account transactions change over time the type of class that should be instantiated can only be determined at run time.

Extensions points for Dynamic behaviour

Choosing the correct class at runtime using a Factory or Abstract Factory  is not a scalable solution as the process to “lookup” the the correct class can lead to scans of dozens of different tables.

A better approach is to have a single slimmed down generic Bank Account that has been built with a suite of extensions points where capabilities such as interest calculations are plugged into it at runtime.

Similarly, there can be a huge amount of variability in computer games with players, enemies, weapons, buildings, trees, potions all sharing common characteristics but each ultimately being unique.

Decomposing an Game Entity

Imagine a 80s style top down scroller where the player either runs on the ground or flies a helicopter. In the game you move around picking up power ups, replenishing ammunition and gaining different weapons. Trees block the player when they are on the ground but they can be flown over in the helicopter. Similarly, buildings are can only be entered when the player is on the ground.

Here is a table of Game Entities with some common attributes.

Environment Position

Velocity/Movement

Life points

Damage Points

Can open building

Can fly

Player

Y

Y

Y

Y

Y

N

Player Helicopter

Y

Y

Y

Y

N

Y

Tree, Building

Y

N

N

N

N

N

Ground Power Up

Y

N

N

N

N

N

Flying Power Up

Y

N

N

N

N

Y

Player Machine Gun

N

N

N

Y

N

N

Head Up Display

N

N

N

N

N

N

By going through the table it’s clear that there aren’t ANY attributes that are shared by all elements but it may be possible to create two or three groups of similar entities and each group could have its own base class. Problems also arise from when entities go through state changes such as a player moving from walking to flying or when a player gains a power up. These transitions change the behaviour and state of the entity.

The Entity-Component-System pattern takes a very different approach. The Entity is reduced to a single identity field with a dynamic collection of attributes and behaviours (called components) logically attached to it. When the player walks up to the helicopter the visual and behavioural components for a walking person are replaced with the helicopter. The damage and hit points are similarly modified with ease. The last role in the pattern is called the System, which are the algorithms that span across entities and provide collision detection, rendering etc.

Comments are closed