Search code examples
c#xnamonogame

Monogame/C# - Check if collision was present in previous frame


I have a working collision system in place in my Monogame/C# project that uses a quadtree to determine potential collisions, and test them accordingly. My problem is that I want to be able to send out a method to the entity (that has been collided with), either OnCollisionEnter() or OnCollisionStay() depending on if the collision was present in the previous frame.

In the following code, OnCollisionEnter() is never called:

public class Collision : iSystem
{
    private List<Entity> currentCollisions; // Collisions occurring in the current frame
    private List<Entity> previousCollisions; // Collisions from the previous frame

    public override void Initialize(Entity caller)
    {
        currentCollisions = new List<Entity>();
        previousCollisions = new List<Entity>();
        base.Initialize(caller);
        hasInitialized = true;
    }

    public override void Update(GameTime gameTime)
    {
        List<Entity> nearby = Global.QuadTree.GetNeighbours(parent);

        for (int i = 0; i < nearby.Count; i++)
        {
            if (nearby[i] != parent)
                if (parent.Collider.Intersects(nearby[i].Collider))
                {
                    currentCollisions.Add(nearby[i]);
                    AlertEntity(nearby[i]);
                }
        }


        previousCollisions = currentCollisions; // Ready for the next frame
        currentCollisions.Clear();
        base.Update(gameTime);
    }

    public void AlertEntity(Entity entity)
    {
        if (previousCollisions.Contains(entity))
           parent.OnCollisionStay(entity.Collider);
        else
           parent.OnCollisionEnter(entity.Collider); // This is never called
    }
}

('parent' refers to the entity that the component 'Collision' is attached to)

If you could suggest why this is happening, I'd be grateful. Thanks


Solution

  • Calling currentCollisions.Clear() will also clear previousCollisions because they are both referencing the same List object. Instead of calling currentCollisions.Clear(), you should set it to a new List<Entity>().

    // . . .
    
    previousCollisions = currentCollisions; // Ready for the next frame
    currentCollisions = new List<Entity>(); // Now both lists are not clear
    base.Update(gameTime);