A 'correct' solution would involve running the MPRToolbox.LocalSurfaceCast in the desired normal direction, similar to how the MPRToolbox.RefinePenetration function works. That's kind of complicated and not super duper cheap, so I'd recommend just approximating it.
One simple option would be to project the offset onto the plane whose normal is the moving object's movement direction. That way it would only ever move perpendicularly to the movement direction. In pseudocode, it would look something like:
Code: Select all
var offset = normal * penetrationDepth
var projectedOffset = offset - dot(offset , movementDirection) * movementDirection
where 'movementDirection' is normalized.
The resulting offset will always be smaller than the 'true' penetration offset along any given direction (assuming the collision detection system correctly detected the minimum depth). It may remain in collision for more than one frame, since it isn't resolving the 'true' penetration every frame, but it may work just fine. There is a chance that an object that is perfectly aligned along the movement direction doesn't get moved at all. If that becomes a problem, you could detect it and introduce an arbitrary bias along some perpendicular direction.