Okay, so this is a problem I've been trying to figure out for quite some time. Mine is a 2D platformer game with a world made up of (usually) immobile tiles and mobile sprites, both of which use AABBs to represent their hitboxes. This game is NOT grid-based due to some complications with moving layers of tiles.
I can detect collisions and easily figure out the depth of the collision. I use the "shallowest axis method" to determine which way to resolve a collision between the sprite and the tile. If the sprite is deeper horizontally than vertically, the direction to resolve is either up or down. If the sprite is deeper vertically than horizontally, the direction to resolve is either left or right.
This is simple enough, and it works pretty well. That is, until you have a sprite colliding with more than one tile. As, by their nature, each collision has to be checked separately, different collisions may have different direction to resolve in. For example, if a sprite is trying to walk across a row of tiles, for one frame they will intersect the next tile such that the horizontal depth is shorter than the vertical depth. As the collision says "resolve left", it will be pushed back and will be stuck on the corner.
I've been mulling this problem over, on and off, for quite some time, and several solutions have come to me, but all have flaws. I could mark certain sides as unreachable, but without a grid-based engine, determining "unreachability" is remarkably complex, especially with moving layers of tiles always a possibility.
Another possible method would be to predict collisions before they happen and "work back" the movement to the point of the collision, I suppose, but I'm not sure how the math on that works.
I feel that I'm missing something incredibly obvious, especially since games from the 80s have already solved this problem.