• 04/02/13 07:37 PM

    Understanding Component-Entity-Systems

    General and Gameplay Programming

    Klutzershy
    The traditional way to implement game entities was to use object-oriented programming. Each entity was an object, which intuitively allowed for an instantiation system based on classes and enabled entities to extend others through polymorphism. This led to large, rigid class hierarchies. As the number of entities grew, it became increasingly difficult to place a new entity in the hierarchy, especially if the entity needed a lot of different types of functionality. Here, you can see a simple class hierarchy. A static enemy does not fit well into the tree. [attachment=14579:classdiagram.png] To solve this, game programmers started to build entities through composition instead of inheritance. An entity is simply an aggregation (technically a composition) of components. This has some major benefits over the object-oriented architecture described above:
    1. It's easy to add new, complex entities
    2. It's easy to define new entities in data
    3. It's more efficient
    Here's how a few of the entities above would be implemented. Notice that the components are all pure data - no methods. This will be explained in detail below. [attachment=14581:compositiondiagram.png]

    The Component

    A component can be likened to a C struct. It has no methods and is only capable of storing data, not acting upon it. In a typical implementation, each different component type will derive from an abstract [tt]Component[/tt] class, which provides facilities for getting a component's type and containing entity at runtime. Each component describes a certain aspect of an entity and its parameters. By themselves, components are practically meaningless, but when used in conjunction with entities and systems, they become extremely powerful. Empty components are useful for tagging entities.

    Examples

    • Position (x, y)
    • Velocity (x, y)
    • Physics (body)
    • Sprite (images, animations)
    • Health (value)
    • Character (name, level)
    • Player (empty)

    The Entity

    An entity is something that exists in your game world. Again, an entity is little more than a list of components. Because they are so simple, most implementations won't define an entity as a concrete piece of data. Instead, an entity is a unique ID, and all components that make up an entity will be tagged with that ID. The entity is an implicit aggregation of the components tagged with its ID. If you want, you can allow components to be dynamically added to and removed from entities. This allows you to "mutate" entities on the fly. For example, you could have a spell that makes its target freeze. To do this, you could simply remove the [tt]Velocity[/tt] component.

    Examples

    • Rock (Position, Sprite)
    • Crate (Position, Sprite, Health)
    • Sign (Position, Sprite, Text)
    • Ball (Position, Velocity, Physics, Sprite)
    • Enemy (Position, Velocity, Sprite, Character, Input, AI)
    • Player (Position, Velocity, Sprite, Character, Input, Player)

    The System

    Notice that I've neglected to mention any form of game logic. This is the job of the systems. A system operates on related groups of components, i.e. components that belong to the same entity. For example, the character movement system might operate on a [tt]Position[/tt], a [tt]Velocity[/tt], a [tt]Collider[/tt], and an [tt]Input[/tt]. Each system will be updated once per frame in a logical order. To make a character jump, first the [tt]keyJump[/tt] field of the Input data is checked. If it is true, the system will look through the contacts contained in the [tt]Collider[/tt] data and check if there is one with the ground. If so, it will set the [tt]Velocity[/tt]'s [tt]y[/tt] field to make the character jump. Because a system only operates on components if the whole group is present, components implicitly define the behaviour an entity will have. For example, an entity with a [tt]Position[/tt] component but not a [tt]Velocity[/tt] component will be static. Since the [tt]Movement[/tt] system uses a [tt]Position[/tt] and a [tt]Velocity[/tt], it won't operate on the [tt]Position[/tt] contained within that entity. Adding a [tt]Velocity[/tt] component will make the [tt]Movement[/tt] system work on that entity, thus making the entity dynamic and affected by gravity. This behaviour can be exploited with "tag components" (explained above) to reuse components in different contexts. For example, the [tt]Input[/tt] component defines generic flags for jumping, moving, and shooting. Adding an empty [tt]Player[/tt] component will tag the entity for the [tt]PlayerControl[/tt] system so that the [tt]Input[/tt] data will be populated based on controller inputs.

    Examples

    • Movement (Position, Velocity) - Adds velocity to position
    • Gravity (Velocity) - Accelerates velocity due to gravity
    • Render (Position, Sprite) - Draws sprites
    • PlayerControl (Input, Player) - Sets the player-controlled entity's input according to a controller
    • BotControl (Input, AI) - Sets a bot-controlled entity's input according to an AI agent

    Conclusion

    To wrap up, OOP-based entity hierarchies need to be left behind in favour of Component-Entity-Systems. Entities are your game objects, which are implicitly defined by a collection of components. These components are pure data and are operated on in functional groups by the systems. I hope I've managed to help you to understand how Component-Entity-Systems work, and to convince you that they are better than traditional OOP. If you have any questions about the article, I'd appreciate a comment or message. A follow-up article has been posted, which provides a sample C implementation and solves some design problems. Implementing Component-Entity-Systems

    [i]Article Update Log[/i]

    [b]1 April 2013 - Initial submission[/b] [b]2 April 2013 - Initial publication; cleaned up formatting[/b] [b]29 September 2013 - Added notice of follow-up article; changed some formatting[/b])


      Report Article


    User Feedback

    Create an account or sign in to leave a review

    You need to be a member in order to leave a review

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now


    j-locke

    Report ·

      

    Share this review


    Link to review
    pizzafan

    Report ·

      

    Share this review


    Link to review
    exOfde

    Report ·

      

    Share this review


    Link to review
    Ectara

    Report ·

      

    Share this review


    Link to review
    Inukai

    Report ·

      

    Share this review


    Link to review
    LTArnas

    Report ·

      

    Share this review


    Link to review
    Weton

    Report ·

      

    Share this review


    Link to review
    landagen

    Report ·

      

    Share this review


    Link to review
    Devisaur

    Report ·

      

    Share this review


    Link to review
    Damian.

    Report ·

      

    Share this review


    Link to review
    wicked357

    Report ·

      

    Share this review


    Link to review
    Zipster

    Report ·

      

    Share this review


    Link to review