Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Entity Component Systems

Yos Riady
September 16, 2016

Entity Component Systems

Entity-Component-System (ECS) is a distributed and compositional architectural design pattern that is mostly used in game development. Elixir is a dynamic, functional language built on top of the Erlang VM designed for building scalable and maintainable applications. In this talk, discover how we can use both ECS and Elixir in a novel approach to structure our programs beyond the traditional OO/inheritance paradigm.

https://goo.gl/ECeFOI

Yos Riady

September 16, 2016
Tweet

More Decks by Yos Riady

Other Decks in Programming

Transcript

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

    View Slide

  2. 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

    View Slide

  3. 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

    View Slide

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

    View Slide

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

    View Slide

  6. 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

    View Slide

  7. 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

    View Slide

  8. 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

    View Slide

  9. Entity Component Systems

    View Slide

  10. 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

    View Slide

  11. What qualities might a bunny have?

    View Slide

  12. 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

    View Slide

  13. 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

    View Slide

  14. The bunny entity

    View Slide

  15. 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

    View Slide

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

    View Slide

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

    View Slide

  18. 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

    View Slide

  19. 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”

    View Slide

  20. 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

    View Slide

  21. 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

    View Slide

  22. 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

    View Slide

  23. The spreadsheet analogy for ECS

    View Slide

  24. The spreadsheet analogy for ECS

    View Slide

  25. ● 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

    View Slide

  26. ● 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

    View Slide

  27. 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

    View Slide

  28. ECS in the Real World

    View Slide

  29. View Slide

  30. 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

    View Slide

  31. Entity Component Systems
    in Elixir

    View Slide

  32. 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

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide

  35. Demo

    View Slide

  36. 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

    View Slide

  37. 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.

    View Slide

  38. View Slide


  39. 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

    View Slide

  40. Thanks
    Yos Riady
    yos.io

    View Slide