Search code examples
c#collision-detectiongame-enginecollision

Freeing stuck objects after collision


I have run into a slight issue with the collision resolution in my game engine. If two objects collide and that collision causes the velocity to go to zero, the edges of the objects will overlap each other and they'll be stuck.

Is there a way to implement a catchall for this kind of a situation? i.e. move the objects just enough in the right direction so they are not stuck.

Here is how I am checking collisions and moving objects. When update is called on an entity, it moves the (x,y).

    public static void Update()
        {
            for (var iterator = 0; iterator < PhysicsEntities.Count; iterator++)
            {
                for (var index = iterator + 1; index < PhysicsEntities.Count; index++)
                {
                    if (!Collision.ResolveCollision(PhysicsEntities[iterator],
                         PhysicsEntities[index], Detection)) continue;
                    PhysicsEntities[iterator].Update();
                    PhysicsEntities[iterator].Collided = true;
                    PhysicsEntities[index].Update();
                    PhysicsEntities[index].Collided = true;
                }
            }

            foreach (var entity in PhysicsEntities)
            {
                entity.Update(velocity: true);
                entity.Collided = false;
            }
        }
    }

Here is the update function for the entities:

public void Update(bool velocity = false)
    {
        if(!Movable) return;
        if (!Collided)
        {
            var moveX = Velocity.X / Universe.UpdateInterval;
            var moveY = Velocity.Y / Universe.UpdateInterval;
            Position.Move(moveX, moveY);
            BoundingBox.Move(moveX, moveY);
        }
        if(velocity) UniversalForces();
    }

    private void UniversalForces()
    {
        Velocity.Scale(1 - Universe.Friction);
        Velocity.Add(Universe.GravityMag, Universe.GravityDir);
    }

Finally, here is a image of one simulation where the objects get stuck. As you can see, it is just the edges that are getting stuck:

enter image description here


Solution

  • The quick solution is to move both objects back to the previous tic's position and any other object that causes a collision with to move back as well. It works, but it looks messy and causes some behavior that looks really bad - things like pushing directly at a wall leaves a gap, but angling towards a wall leaves a smaller gap. Very messy.

    The better solution is to move both objects back just far enough along their negative velocity vector so that they are no longer touching. Usually some dot product math can give you what you need for this, though iterating backwards can work (slow).

    Long story short, don't ever allow objects to overlap. Take care of it before it happens and you avoid stuck jitters, can't move stuff, etc.