In this lesson, you will learn how to calculate the surface normal beneath your character to prevent them from sliding uncontrollably down steep hills or getting stuck on uneven geometry.
Understanding Surface Normals
When your character moves, they don't just exist on a flat plane. They interact with slopes of varying angles. To handle this, we use the RaycastHit information we covered in our Grounded State lesson. When our ground-detection ray hits a surface, it returns a normal vector.
The normal is a direction vector pointing perfectly perpendicular (at a 90-degree angle) away from the surface. By comparing this normal to Vector3.up (which points straight toward the sky), we can determine how steep a slope is using Vector3.Angle.
Implementing the Slope Check
If the angle between the ground normal and Vector3.up is greater than a threshold you define, you know the slope is too steep to climb.
Here is how you can perform this check within your movement logic:
if (Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, rayDistance))
{
float slopeAngle = Vector3.Angle(Vector3.up, hit.normal);
if (slopeAngle <= maxSlopeAngle)
{
// Slope is walkable; apply your velocity-based movement
MoveCharacter(inputVector);
}
else
{
// Slope is too steep; stop horizontal movement to prevent sliding
StopMovement();
}
}
Why This Matters
If you don't account for the slope angle, your character might try to "climb" a vertical wall by applying horizontal velocity, leading to jittery behavior as the physics engine fights against the geometry. By checking the hit.normal before applying your movement force, you create a natural-feeling constraint that keeps your character grounded only on surfaces where movement is logically valid. This also prevents the character from "getting stuck" on small geometric seams, as you can treat steep, unwanted edges as obstacles rather than traversable terrain.
Key Takeaway: By comparing the surface normal vector to the world-up vector, you can dynamically restrict movement to walkable slopes, ensuring stable and predictable character traversal.