14
\$\begingroup\$

More fun with an ES...

Currently, I have a few systems:

  • Renderer (Renderable attribute, Transform attribute)
  • Motion (Movable attribute, Transform attribute, Renderable attribute [for bounding boxes, etc])
  • Input (InputReceiver attribute)
  • etc.

I'm adding collision detection. My first thought was to add a new system that performs collision. It makes sense to me to keep this isolated from the Motion system since not all things that move or are animated necessarily participate in collision detection - cameras, fog, etc. - but it seems that Collision and Motion are interdependent.

When Motion moves an entity, the transformation needs to be validated with Collision, and the movement either cancelled, or adjusted (bouncing, stopping at a wall, etc.).

An alternative would be to create a Collidable attribute that maintains a reference to a collision object - kd-tree, octree, etc. that is shared among entities that can collide with one another. The Motion system would then check for that attribute, and use it to check or adjust movement.

From a code perspective, that's an acceptable solution. However, from an ECS architecture point of view, it seems that it's pushing logic into the Motion system that doesn't apply to all of the entities that have a Movable attribute.

I could also store a motion vector in the Movable attribute, and have the Collider system adjust Transform as needed, but that'll involve duplicating functionality between Motion and Collider, or a callback from Collider to Motion with some data about the collision location and surface data for bounce/reflection, etc.

This may fall under the heading of "special case hack" but I'd like to get some input from those that have handled this before without creating a ton of edge case code.

The Question What's a good way to avoid tight coupling between motion and collision systems when it seems that they require knowledge of each other?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ What is the question? \$\endgroup\$
    – jcora
    Commented Aug 6, 2012 at 22:39
  • \$\begingroup\$ @Bane what's a good place to put collision detection logic, keeping collision + movement as separate as possible, and keeping interdependencies between systems to a minimum. My post was a bit of a ramble... \$\endgroup\$
    – 3Dave
    Commented Aug 6, 2012 at 23:09
  • 1
    \$\begingroup\$ Great, now put that in your question, bolded. :) \$\endgroup\$
    – jcora
    Commented Aug 6, 2012 at 23:20

2 Answers 2

7
\$\begingroup\$

You're overthinking it. In my engine, which also uses an entity-component system, every GameObject can have a pointer to a ModuleCollision.

What happens when the game updates:

  • Scene updates all objects it holds. It calls the Update function for each GameObject.
  • Inside the Update function, each GameObject only updates its speed and direction, not its position.
  • GameObject uploads its current position, speed and direction to its ModuleCollision, if one is available.
  • Scene does collision checking on a ModuleCollision basis.
  • Scene calls the UpdatePost function on each GameObject. If the object has a collision module, it fetches the updated position, speed and direction from the collision module. The position is updated with the speed and direction.
  • The GameObject constructs a final 3x3 matrix out of its position and heading.

Yes, there is some duplication of state, but that's okay. Doing collision handling on a ModuleCollision is the best way to go about it, because otherwise you would have to check each GameObject to see if it has a ModuleCollision handle.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ So rather than worrying about backtracking position in case of a collision, you're splitting velocity/acceleration from translation, altering those based on any collisions that are detected, and then those changes are propagated in a second specialized update within the same frame? Seems pretty clean. Thanks. \$\endgroup\$
    – 3Dave
    Commented Aug 7, 2012 at 15:40
3
\$\begingroup\$

I would do it like this...

Have three systems:

  1. Movement system
  2. Acceleration system
  3. Collision system

The movement system applies velocities to positions. The acceleration system applies forces to velocities. The collision system detects collisions and applies the forces in the right directions, or, if you want crude collisions, directly alters the velocities.

For example, you could calculate the angle between the collisions using atan2, and then use that to apply the correct forces/velocities the bodies.

Have the collision detection system broadcast messages if needed too.

\$\endgroup\$

You must log in to answer this question.

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