Skip to main content

Entity / Component Systems

I've been writing a new game recently -- and this time, I decided to use an entity/component system. Boy, does that approach make things easier! In other games I've written, I've struggled to fit new gameplay features into the existing code base. With a entity-component based systems, it's easy to add new features:
  • Need a way to track targetable objects in your game? Add a Targetable component that advertises the unit's position, name for display in the HUD, etc.
  • Need to add some new AI behavior to a unit? Add a component! Update all the AI components once per frame and you're on your way.
  • Does your game need networking? What should you do...? Add a component containing all the info for network serialization!
  • Need to control a unit from user input? Add a joystick component that updates the unit's position component in response to user input.

Basically, any new feature can be folded into a component. The best thing about components is that they are dynamic; you can add and remove components at runtime to change the behavior of a unit. If you think of the entity as a vector, then each component is like a separate "dimension" to your entity. Additionally, each component is a lot like a table in a relational database. The actual "entity" is just the sum of its components; that is, the sum of all its entries in each relational database table. I find this design incredibly elegant.

So, how have I implemented my entity/component system? I have a Table template class, which is basically a wrapper around std::unordered_map, indexed by the entity ID. To look up a component, you simply do a "query" (to borrow from relational database terminology) using the entity's ID and look up the component. For example:

Id id = ... 
// get the entity's ID
Ptr<Table<Position>> table = db->table(); 
// get position table
Position position = table->component(id);
// do something with the position
Say you want iterate over all the targetable enemies and select the closest one. This is really easy with entity/component systems:
Id nearestTargetableEnemy(Vector myPosition) {
    auto nearestId = Id();
    auto nearestDist = std::numeric_limits::max();
    for (auto i: *db->table()) {
        auto target = i.value;
        auto id = i.key;
        auto position = db->table(id);
        auto dist = position.origin.distance(myPosition);
        if (dist < nearestDist) {
            nearestDist = dist;
            nearestId = id;
        }
    }
    return id;
}
Simple! And, this code automatically works for any entity that has a Target and Position component! Pretty cool. The possibilities are pretty much endless. Here are some more things that are easy to implement with entity/component systems:
  • Recharge/powerup stations
  • Pathfinding
  • Serialization/save game
  • Camera tracking
  • Collision detection
  • Damage/hitpoints
  • Rendering effects
Next time you write a game, give the entity/component system approach a try. It's just too much fun not to use.

Comments

  1. Many of the steps can be completed by the machines or robotics controlled by a single operator, reducing labor prices and overhead. The precision machining process can also be|may also be|can be} performed extra shortly and effectively, rising manufacturing output. The high quality indexes revealed on this work all provide a great indication of the injection molding high quality beneath the thought-about processing circumstances.

    ReplyDelete

Post a Comment