Table of Contents

Collision triggers

This C# intermediate tutorial covers the use of collision triggers. It teaches about rigid bodies and how to set those up in the editor.

Explanation

Rigid bodies determine how entities in our scene behave on gravity, whether they collide with other objects or in the case of this tutorial": trigger collision events in our code. We do this by setting up a collider box in our scene and letting a sphere roll through this object. The events that are triggered are then processed by the script that we will make for it.

Rigidbodies and collisions

The code below looks for the rigidbody component that is attached to our entity. The rigidbody component contains all information we need for setting up triggers. The IsTrigger property determines that our collider doesn't stop other physics objects, but that it does trigger events in code (if they are set up at least).

We spawn a sphere which also has a rigidbody. This sphere has a mass and is affected by gravity. The sphere will fall down and eventually roll through our collider box. In our update loop we check if there are collisions happening. If there are collisions, we get the colliding object and print out some text on screen. Once the sphere leaves the trigger box, our update loop sees that we no longer have collisions.

Instead of using our update loop, we can also use collision events.

// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System.Collections.Specialized;
using Stride.Core.Collections;
using Stride.Core.Mathematics;
using Stride.Engine;
using Stride.Physics;

namespace CSharpIntermediate.Code
{
    public class CollisionTriggerDemo : SyncScript
    {
        StaticColliderComponent staticCollider;
        string collisionStatus = "";

        public override void Start()
        {
            // Retrieve the Physics component of the current entity
            staticCollider = Entity.Get<StaticColliderComponent>();

            // When the 'CollectionChanged' event occurs, execute the CollisionsChanged method
            staticCollider.Collisions.CollectionChanged += CollisionsChanged;
        }

        private void CollisionsChanged(object sender, TrackingCollectionChangedEventArgs args)
        {
            // Cast the argument 'item' to a collision object
            var collision = (Collision)args.Item;

            // We need to make sure which collision object is not the Trigger collider
            // We perform a little check to find the ballCollider 
            var ballCollider = staticCollider == collision.ColliderA ? collision.ColliderB : collision.ColliderA;

            if (args.Action == NotifyCollectionChangedAction.Add)
            {
                // When a collision has been added to the collision collection, we know an object has 'entered' our trigger
                collisionStatus = ballCollider.Entity.Name + " entered " + staticCollider.Entity.Name;
            }
            else if (args.Action == NotifyCollectionChangedAction.Remove)
            {
                // When a collision has been removed from the collision collection, we know an object 'left' our trigger
                collisionStatus = ballCollider.Entity.Name + " left " + staticCollider.Entity.Name;
            }
        }

        public override void Update()
        {
            // The trigger collider can have 0, 1, or multiple collision going on in a single frame
            int drawX = 500, drawY = 300;
            foreach (var collision in staticCollider.Collisions)
            {
                DebugText.Print("ColliderA: " + collision.ColliderA.Entity.Name, new Int2(drawX, drawY += 20));
                DebugText.Print("ColliderB: " + collision.ColliderB.Entity.Name, new Int2(drawX, drawY += 20));
            }

            DebugText.Print(collisionStatus, new Int2(500, 400));
        }
    }
}