Say we represent a character with a sphere and an environment with a set of triangles: our first goal might be to move our character along the environment surface.
Every game tick we would take our original character position, represented as a vector, and compute the position where the character would sit just above the surface. Every time we move the character laterally, we would again vertically shift, or snap, the character to the surface. In cases where the next position is above the surface, we would snap the character downwards. In cases where the next position causes the character to intersect the surface, we would snap the character upwards.
We reason that such a location, if it exists, would exist within some range just above to just below the character. To find it, we perform a spherecast that originates from just above the character and cast downwards. To cap the range in which we find our intersection, we perform our spherecast from a distance maxUp above the character and consider only those results that don’t exceed a maxDown threshold. As we may have several triangles that we could intersect in this range, we perform a separate spherecast per triangle. We discard any result to where the character still intersects some other triangle. Of the remaining results, we choose the closest.