Tracking Collisions Using Events and Filters

Summary

Shows how to use event handlers to track entity collision states during the PhysX simulation.

Collision filters

Collision filters allow you to assign entities to one or more collision groups and define how they interact with other groups.

To create a collision filter, right-click in the project browser. Select 'Create->Reactor->Collision Filter'. When you select a collision filter, you will see a table with 3 columns in the inspector: Group, Notify, and Collide. Each row in the table has a name or number and represents a collision group. You can edit the first column to assign names to the collision groups.

The Group column specifies which groups an entity belongs to.

The Collide column specifies which groups you want to physically collide with. In order for two entities to collide, they both must belong to groups that the other collides with. Eg. if you have two collision groups, Player and Enemy, and you have a CharacterEntity which belongs to the Player group and a GhostEntity that belongs to the Enemy group, and the CharacterEntity collides with the Enemy group, but the GhostEntity does not collide with the Player group, the CharacterEntity and GhostEntity will pass through each other.

The Notify column specifies which groups you want to get an event for when a collision or overlap occurs. If you set a filter to notify with a group but NOT collide with that group, you'll get OperlapStart and OverlapEnd events when those entities pass through each other. If you set it to notify AND collide, you will get OnCollision, OnContactUpdate, and OnContactLost events. Only the entity with the collision filter that is set to notify will receive the events.

Once you've created a collision filter, you can assign it to a ksEntityComponent in the inspector. An entity with no collision filer will collide with everything and receive no events.

You can also assign collision filters to colliders. Each collider on a game object with an entity component has a Reactor Collider Data foldout section. Expand this section and assign a collision filter to the filter property to assign a collision filter just to that collider. Colliders with no collision filter will use the entity's collision filter.

If a collider is set to be a trigger, it will ignore the Collide column of its collision filter and collide with nothing. If a trigger has no notify flags set, it will receive events for all groups.

Collision and overlap events

The following events are fired for entities that notify and collide with each other.

The following events fired for entities that notify and do not collide with each other.

The following script shows how you can listen for collision and overlap events.

using KS.Reactor.Server;
using KS.Reactor;

public class sCollisionListener : ksServerEntityScript
{
    public override void Initialize()
    {
        Entity.OnCollision += OnCollision;
        Entity.OnContactUpdate += OnContactUpdate;
        Entity.OnContactLost += OnContactLost;
        Entity.OnOverlapStart += OnOverlapStart;
        Entity.OnOverlapEnd += OnOverlapEnd;
    }

    public override void Detached()
    {
        Entity.OnCollision -= OnCollision;
        Entity.OnContactUpdate -= OnContactUpdate;
        Entity.OnContactLost -= OnContactLost;
        Entity.OnOverlapStart -= OnOverlapStart;
        Entity.OnOverlapEnd -= OnOverlapEnd;
    }

    private void OnCollision(ksContact contact)
    {
        ksLog.Info(this, "collision pos: " + contact.Point + ", impulse: " + contact.Impulse + ", normal: " + contact.Normal);
        ksLog.Info(this, "delta: " + (contact.Point - Transform.Position));
    }

    private void OnContactUpdate(ksContact contact)
    {
        ksLog.Info(this, "contact pos: " + contact.Point + ", impulse: " + contact.Impulse + ", normal: " + contact.Normal);
    }

    private void OnContactLost(ksCollider ourCollider, ksCollider otherCollider)
    {
        ksLog.Info(this, "on contact lost");
    }

    private void OnOverlapStart(ksCollider ourCollider, ksCollider otherCollider)
    {
        ksLog.Info(this, "on overlap start");
    }

    private void OnOverlapEnd(ksCollider ourCollider, ksCollider otherCollider)
    {
        ksLog.Info(this, "on overlap end");
    }
}