Slide 1

Slide 1 text

Entity Component Systems Yos Riady yos.io goo.gl/ECeFOI

Slide 2

Slide 2 text

A walkthrough of an ECS implementation in Elixir A high-level overview of Entity Component Systems Background Drawbacks of traditional OOP / inheritance style code ECS Examples Code Next Steps Real life applications and examples of ECS in action Further learning, future improvements, and conclusion

Slide 3

Slide 3 text

A walkthrough of an ECS implementation in Elixir A high-level overview of Entity Component Systems Background Drawbacks of traditional OOP / inheritance style code ECS Examples Code Next Steps Real life applications and examples of ECS in action Further learning, future improvements, and conclusion

Slide 4

Slide 4 text

Animal hop() Bunny swim() Whale GameObject kill() Killer Whale

Slide 5

Slide 5 text

Animal hop() Bunny swim() Whale hop() kill() Killer Bunny GameObject kill() Killer Whale

Slide 6

Slide 6 text

The challenges with inheritance The Blob Antipattern A huge single root class with a large amount of functionality. Subclasses become overburdened with unneeded functionality. Deep Rigid Hierarchies The Diamond Problem

Slide 7

Slide 7 text

A walkthrough of an ECS implementation in Elixir A high-level overview of Entity Component Systems Background Drawbacks of traditional OOP / inheritance style code ECS Examples Code Next Steps Real life applications and examples of ECS in action Further learning, future improvements, and conclusion

Slide 8

Slide 8 text

Entity Component Systems ● Originally used in game development ○ Tendency to end up with very complex / monolithic classes when using inheritance ○ Thief, Dungeon Siege, Caves of Qud, roguelikes ● Attempts to solve issues due to deep hierarchies ○ Composition over inheritance ● Based on three key abstractions ○ Entity ○ Component ○ System

Slide 9

Slide 9 text

Entity Component Systems

Slide 10

Slide 10 text

Component Components are minimal, reusable data objects that are plugged into entities to support some behaviour. A Component itself has no behaviour. A Components tags an entity with a single quality. Typically a struct or dictionary. The “qualities” or “aspects”of a thing

Slide 11

Slide 11 text

What qualities might a bunny have?

Slide 12

Slide 12 text

What components might a bunny have? Placeable - int x - int y - int z Huggable - int fluffiness Consumable - float calories Seeing - int sight_radius - boolean night_vision? Living - float health - float age Hopping - int hop_distance Physical - int height - int width - int length

Slide 13

Slide 13 text

Entities are very simple. Entities are globally unique IDs. Entities has no actual data or behaviour. Entity are solely the sum of its components. A Component gives an Entity its data. Entity An aggregation of Components

Slide 14

Slide 14 text

The bunny entity

Slide 15

Slide 15 text

The bunny entity Placeable - int x - int y - int z Huggable - int fluffiness Consumable - float calories Seeing - int sight_radius - boolean night_vision? Living - float health - float age Hopping - int hop_distance Physical - int height - int width - int length

Slide 16

Slide 16 text

The carrot entity Placeable - int x - int y - int z Consumable - float calories Physical - int height - int width - int length

Slide 17

Slide 17 text

The ghost entity Placeable - int x - int y - int z Spooky - int spookiness Seeing - int sight_radius - boolean night_vision?

Slide 18

Slide 18 text

Systems run continuously and iterate over all Components of its type. Systems read and write the state of Components, resulting in behaviour. By transitive property, Systems give Entities behaviour. Could be a distributed worker pool. System Brings entities and components to life

Slide 19

Slide 19 text

How does a bunny behave? Placeable - x 5 - y -2 - z 10 Living - age 2.00 Placeable - x 5 - y -2 - z 0 Living - age 2.01 “Fall” “Age”

Slide 20

Slide 20 text

How does a bunny behave? Placeable - x 5 - y -2 - z 10 Living - age 2.00 Placeable - x 5 - y -2 - z 0 Living - age 2.01 “Fall” “Age” Gravity System Time System

Slide 21

Slide 21 text

Data flow in ECS Gravity System Placeable - x - y - z Placeable - x - y - z Placeable - x - y - z Placeable - x - y - z Placeable - x - y - z External Event Stream i.e. Time, Player Input

Slide 22

Slide 22 text

Acquires behaviour through changes in component states. Reads the continuously changing state of its components. Listens to system events, updates its state. Stores data, which gets updated in response to events from systems. Listens to outside events, publishes updates to components Provides the logic that manipulates the data encapsulated in components. Data flow in ECS System Component Entity

Slide 23

Slide 23 text

The spreadsheet analogy for ECS

Slide 24

Slide 24 text

The spreadsheet analogy for ECS

Slide 25

Slide 25 text

● Good decoupling, helps divide your monolithic classes ● Clear separation of responsibility ○ Encourages small interfaces ○ Entity.build([PlayerInputComponent]) ● Easy reuse and composability ○ Entity.build([FlyingComponent]) ○ Entity.build([FlyingComponent, SeeingComponent]) ● Straightforward unit testing and mocking ○ Substitute components with mocked components at runtime ● Separates data from functions that act on it ● Runtime object definition ● Parallelizable Advantages of ECS

Slide 26

Slide 26 text

● Most people have never even heard of this pattern ● Handling interprocess communication introduces complexity ● Inter-Component communication ○ What happens when a system needs to access multiple components? ● Inter-System communication ○ What happens when two systems need to access the same component? ● Not as concretely defined as other patterns such as MVC ○ There are a multitude of ways to implement ECS ● Instantiation of entities is more involved ○ Who wires up the components? ○ Does the entity itself creates its own components? ○ Does outside code provides the components? Challenges of ECS

Slide 27

Slide 27 text

A walkthrough of an ECS implementation in Elixir A high-level overview of Entity Component Systems Background Drawbacks of traditional OOP / inheritance style code ECS Examples Code Next Steps Real life applications and examples of ECS in action Further learning, future improvements, and conclusion

Slide 28

Slide 28 text

ECS in the Real World

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

A walkthrough of an ECS implementation in Elixir A high-level overview of Entity Component Systems Background Drawbacks of traditional OOP / inheritance style code ECS Examples Code Next Steps Real life applications and examples of ECS in action Further learning, future improvements, and conclusion

Slide 31

Slide 31 text

Entity Component Systems in Elixir

Slide 32

Slide 32 text

What is Elixir? ● Language that compiles to Erlang ● Built on top of the famed Erlang VM (“nine 9s of reliability”) ○ Traditionally used for telecommunications by Ericsson ○ WhatsApp, Facebook Messenger, RabbitMQ, Riak ● Built-in concurrency abstractions (Actor model and OTP) ● A pleasant, modern syntax similar to Ruby ● Immutable and Functional ● Gradual types ● Pattern Matching ● Interop with Erlang ● Metaprogramming through Macros

Slide 33

Slide 33 text

The Actor Model ● Actors are computational entities that can: ○ Send messages ○ Receive messages ○ Create other actors ● Elixir processes ○ The key abstraction of Elixir’s concurrency model (Demo) ● Erlang OTP ○ Battle-tested patterns for building distributed, fault-tolerance applications ○ GenServer

Slide 34

Slide 34 text

Component A struct containing state attributes System A GenServer Entity A struct with string id and a collection of Component PIDs An ECS implementation in Elixir

Slide 35

Slide 35 text

Demo

Slide 36

Slide 36 text

A walkthrough of an ECS implementation in Elixir A high-level overview of Entity Component Systems Background Drawbacks of traditional OOP / inheritance style code ECS Examples Code Next Steps Real life applications and examples of ECS in action Further learning, future improvements, and conclusion

Slide 37

Slide 37 text

Next Steps ECS is an overlooked architectural pattern that overcomes some of the drawbacks of OOP-style inheritance, and is a great fit for distributed systems. Branching out into unfamiliar domains is a fruitful source of new ideas and patterns to write better software.

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

“ The worst case: The next generation of programmers grows up only being shown one way of thinking about programming. So they kind of work on that way of programming—they flesh out all the details, they, you know, kind of solve that particular model of programming. They’ve figured it all out. And then they teach that to the next generation. So that second generation then grows up thinking: “Oh, it’s all been figured out. We know what programming is. We know what we’re doing.” So the most dangerous thought that you can have as a creative person is to think that you know what you’re doing. Because once you think you know what you’re doing, you stop looking around for other ways of doing things. If you want to be open or receptive to new ways of thinking, to invent new ways of thinking, I think the first step is you have to say to yourself, “I don’t know what I’m doing. We as a field don’t know what we’re doing.” ” Bret Victor, on the Future of Programming https://vimeo.com/71278954 Next Steps

Slide 40

Slide 40 text

Thanks Yos Riady yos.io