Entity Component System - a
different approach to game /
application development
Maxim Zaks @iceX33
Object Oriented Programming
SOLID Principals
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
}
public class AreaCalculator
{
public double Area(Rectangle[] shapes)
{
double area = 0;
foreach (var shape in shapes)
{
area += shape.Width*shape.Height;
}
return area;
}
}
public double Area(object[] shapes)
{
double area = 0;
foreach (var shape in shapes)
{
if (shape is Rectangle)
{
Rectangle rectangle = (Rectangle) shape;
area += rectangle.Width*rectangle.Height;
}
else
{
Circle circle = (Circle)shape;
area += circle.Radius * circle.Radius * Math.PI;
}
}
return area;
}
public abstract class Shape
{
public abstract double Area();
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public override double Area()
{
return Width*Height;
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public override double Area()
{
return Radius*Radius*Math.PI;
}
}
public double Area(Shape[] shapes)
{
double area = 0;
foreach (var shape in shapes)
{
area += shape.Area();
}
return area;
}
OOP -> Abstraction
Wassily Kandinsky: Komposition VIII, 1923. Öl auf Leinwand
Functional Programming
rectangleArea :: Float -> Float -> Float
rectangleArea a b = a * b
data Shape = Circle Float | Rectangle Float Float
area :: Shape -> Float
area (Circle r) = pi * r * r
area (Rectangle width height) = width * height
sum $ map area [(Circle 5), (Rectangle 2 3), (Circle 7)]
FP -> Function Composition
Entity Component System
struct RadiusComponent {
float value;
}
struct HeightComponent {
float value;
}
struct WidthComponent {
float value;
}
struct AreaComponent {
float value;
}
Compute Circle Area System
• get all entities which have RadiusComponent
• set computed AreaComponent on this entity
Compute Rectangle Area System
• get all entities which have WidthComponent and HeightComponent
• set computed AreaComponent on entity
Compute Sum of Areas System
• get all entities which have AreaComponent
• compute a sum of values
• do something with it
Systems query for data / get data
injected
Systems don't return
They change sate, or perform side effects
Systems don't care about the whole
picture
Elephant and the blind men
https://en.wikipedia.org/wiki/Blindmenandanelephant
Interactive vs. pure computation
Systems are executed periodically
How to implement an early exit?
Define better query
• get all entities which have RadiusComponent and don't have
AreaComponent
What happens when value is changed by
outside interaction?
Solutions
• Introduce special components for outside interactions
• Use an ECS which supports reactive systems
What is a reactive system?
Component events
• Added
• Removed
• Replaced
ECS vs. FP
• ECS is built for interactive computations
• mutation is ok
• side effects are ok
ECS vs. OOP
Data driven vs. Abstraction
Clean architecture
• SOLID in regards to ECS
Single responsibility principle
Open close principle
Liskov substitution principle
Interface segregation principle
Dependency inversion principle
Lets talk about testability
Lets talk about debug-ability
Lets talk about performance
If you want to know more
• Have a look at work Unity3D does https://unity3d.com/unity/
features/job-system-ECS
• Mike Acton @ CppCon 2014 https://www.youtube.com/watch?
v=rX0ItVEVjHc
• Catherine West @ Rust Conf 2018 https://www.youtube.com/
watch?v=aKLntZcp27M
• ECS Lab Discord Server https://discord.gg/eCpyZSg
Thank you!
Maxim Zaks @iceX33
Questions?

Entity Component System - a different approach to game and app development