Я бы избегал подъемов / пробежек, поскольку они могли бы создавать NaN, если местность вертикальная.
//currentPosition & targetPosition should be known to you
Vector3 potentialMove = Vector3.Normalize(targetPosition - currentPosition);
float steepness = Vector3.Dot(Vector3.Up, potentialMove);
if( steepness < 0.85f && steepness > -0.85f) // set to taste. 1 is vertically up, 0 is flat, -1 is vert down
{
//allow move
currentPosition = targetPosition
}