Search Unity

Feedback Collision Response Handling

Discussion in 'Entity Component System' started by JooleanLogic, Jan 3, 2021.

  1. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    This is an old chestnut but I've been away from ecs for a while and I figured some users on here probably have some good real world experience with this topic by now.

    There's two types of collision handling models (that I know of) which is component based and event based.

    In the component based model, collision data is added to the affected entities and then your systems can iterate by component. E.g.
    BulletCollisionHandler<Bullet, Collision>(..remove bullet)
    CollisionDamageHandler<Health, Collision>(... subtract damage from Health)

    In the event based model, systems iterate the actual collision events and process them that way. E.g.
    if (HasComponent<Bullet>(collisionEvent.EntityA) { etc. }

    Generally speaking, in the component based model, you either add/remove buffers to affected entities each frame (structural change) or you use permanent buffer components which means iterating all entities whether a collision occurred or not.
    In the event model, you end up iterating the events array multiple times but this is cache friendly and can mostly be optimised out. The downside is mostly in asking each entity if it has the components you're interested in though even the component based approach suffers this too to a lesser extent.

    I don't particularly see one better than the other as there's a lot of cons in both approaches. The component model probably makes for cleaner code in the collision handling systems though as half of the filtering is already done.
    PhilSA provided a neat solution here for the component based model which covers that solution nicely but it seems quite heavy to me.
    One issue I have with this approach is the amount of space the collision buffer takes up on each entity. In my own game I have an entity with a trigger zone that can receive 20 collisions in a single frame whereas most other items will only receive 1 to 3. This makes it tricky as to how much space to allocate to the buffer. Either lots of wasted space or some end up on the heap which is possibly worse.

    I'm using the event approach in my own game but most of my collision handling is based on collision mask type as opposed to component type. So my collision handling systems are interested in if maskA collided with maskB (as defined by the collision layer) which has good optimisations for this model.

    So I'm just after feedback on which approaches others have taken and how they've found it works in real world scenarios. Especially for those using the component based approach. What were their pros/cons/optimisations.
    It's not an easy thing to change models part way through development.
     
  2. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,270
    I use a custom collision solution that is event-based but is often able to avoid the component checking. Instead of packing all the data into a single broadphase structure, I can create a broadphase structure out of an EntityQuery or an array of entities. I can then test two broadphase structures against each other (performing both broadphase and narrowphase) and I know precisely what components I can expect on the pairs in advance and no longer have to check for them.
     
  3. JooleanLogic

    JooleanLogic

    Joined:
    Mar 1, 2018
    Posts:
    447
    Thanks for the response Dreaming. I'm not sure if I understand correctly, but are you coming at this from the perspective that instead of having a general collision detection phase which produces all the collision events in the form of generic EntityA:EntityB pairs, you instead start from the sets of entities you're interested in and perform collision checks against those? Thus you already know the components involved in the collision handler?
    For example, give me the set of entities with <Health> and the set of entities with <Damage> and then perform collision checks against those entities?

    If so, that's an interesting angle I hadn't thought of before. I'm using Phys2D so relying on Unity's callbacks but I guess it's akin to me doing my own raycasts for the sets of entities I'm interested in. However in my particular case, I'd just be doubling up collision checks which Unity has already carried out as part of the simulation.
     
  4. DreamingImLatios

    DreamingImLatios

    Joined:
    Jun 3, 2017
    Posts:
    4,270
    Yes. Your understanding is correct. And also yes, it is repetitive when using another physics solution.