12
\$\begingroup\$

If an Entity has no explicit 'type' (e.g. player) and is simply a collection of components, how do I identify the entities that my systems should and should not be working on? For example, in a game of Pong the paddle and ball both collide with the window boundaries. However, the collision handling systems for each will be different, therefore a system should not handle entities of the wrong type.

void PlayerCollisionSystem::update(std::vector<Entity *> entities) {
  typedef std::vector<Entity *>::iterator EIter;
  for (EIter i = entities.begin(); i != entities.end(); ++i) {
    Entity *player = *i; // How do I verify that the entity is a player?

    // Get relevant components.
    PositionComponent *position = player->getComponent<PositionComponent>();
    VelocityComponent *velocity = player->getComponent<VelocityComponent>();
    SpriteComponent *sprite = player->getComponent<SpriteComponent>();

    // Detect and handle player collisions using the components.
  }
}

Both the player and the ball share the same relevant component types for collision handling yet their system implementations will be different.

If I have a container of all game entities, how do I identify specific types of entity without inheriting Entity or including a member variable such as std::string type, in which case an entity is no longer simply a collection of components?

\$\endgroup\$

4 Answers 4

22
\$\begingroup\$

Nicol Bolas' answer is straight on, but stepping aside and looking at your problem from a distance: you really don't need the type of the entity.

You only need to care whether "does the object have component X" or not and your problem is that you have not properly identified X. If two objects behave differently then give them different components or just put a boolean flag on the component if it to make it behave differently for different object configurations. Use the component system to make decisions about behavior, not the entity "type." That's the whole point of using components.

You are completely allowed to have a PaddlePhysics component/system and a separate BallPhysics component/system if they behave differently. Or you can break down the components into more granular pieces such that you have a Bounce component that only the Ball has and a StopAtBoundary component that both Ball and Paddle have if part of the behavior is complicated enough to justify sharing the code. Or you can just make a PongPhysics component that has a boolean flag Bounces set true for the Ball and false for the Paddle. You could even make a base WallCollision component and then derive that component to get a BallWallCollision that adds the extra behavior needed there.

\$\endgroup\$
1
  • 4
    \$\begingroup\$ I think this should be the accepted answer since there is absolutely no constraint or problem with "vanilla" ECS. Tagging entities can be easily accomplished by creating dedicated components that serve as markers. It also could be just a dummy PlayerTypeComponent that doesn't do anything useful but just serving as a tag. \$\endgroup\$
    – tiguchi
    Feb 22, 2014 at 16:59
21
\$\begingroup\$

A system is only useful if it is useful. If a system where an entity is "simply a collection of components" is less useful than a system where an entity is mostly a "collection of components", then do that.

Stop trying to make "pure" systems and focus on making good ones that do what you need. Use components until components are no longer useful for you. Then use something else.

You've already spent more time thinking about this than it deserves.

\$\endgroup\$
3
  • \$\begingroup\$ very nice +1 "You've already spent more time thinking about this than it deserves" \$\endgroup\$
    – wes
    Aug 5, 2013 at 19:13
  • 10
    \$\begingroup\$ I don't think this is an answer at all, The topic of refining an ECS is one that deserves significant attention, and Garee (when he posted this in 2013) had probably not spent enough time thinking about it. The notion that the topic doesn't deserve more time implies that systems should be simple or trivial and generally undeserving of our time. I would prefer Sean Middleditch's answer as it actually attempts to answer the question instead of dismissing it. \$\endgroup\$ Aug 14, 2015 at 7:28
  • \$\begingroup\$ Great answer. I find myself having to say this to myself occasionally. Focus on moving forward. \$\endgroup\$ Mar 30, 2019 at 23:09
5
\$\begingroup\$

If you want to give entities a explicit type, the easiest way is to define a type variable in the entity class. Only keep to the EC pattern as long as its useful.

Otherwise the type is implied through the component attributes. For example, the physics component would have an attribute for mobile vs stationary. The system then knows when two mobiles collide (ball and paddle). Similarly you can have attributes for how the collision system should respond. Just stop the object or reflect it? Looking at the attributes should give you an idea of what the entity is, but it should be irrelevant. The systems shouldn't need to know what the entity type they're working with is, they should be given enough information using the components provided to them.

Finally, can add an additional component that contains a type, but, as with adding a type to the entity, you'll end up writing a lot of type specific code, defeating the purpose of the EC system.

\$\endgroup\$
0
\$\begingroup\$

An entity is a set of components. You can't assign neat labels to a random set. Giving up type constraints is the price for the great flexibility.

Of course you can have special (typed) entity classes which impose restrictions on the components.

Ideally components are independent. So the solution to your problem would be to call collision handling on each subcomponent, in order. In real applications there are interdependencies and ordering problems. If that's the case you need some 'dispatcher' logic in every method of the Entity class.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .