I’m using Unity3D and I’m trying to determine the direction that the player is moving only when they are on an angled surface. Currently the code below works as it should on angled surfaces but when I stand on a flat surface and press W or A, the message "Moving uphill" activates, and when I press D or S, the message "Moving downhill" activates. When I am on a flat surface that should not happen but I’m not sure where the issue is.
// Update()
if (controller.isGrounded && Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, 2f))
{
Vector3 move = new Vector3(move.x, 0, move.y).normalized;
float surfaceDot = Vector3.Dot(move, hit.normal);
if (surfaceDot == 0)
{
Debug.Log("On a flat surface");
}
else if (surfaceDot < 0)
{
Debug.Log("Moving uphill");
// Reduce player speed
}
else
{
Debug.Log("Moving downhill");
}
}
>Solution :
You can use Vector3.Angle to calculate if it’s an uphill or downhill.
// that angle returned by surfaceAngle for perfectly flat surface.
float flatAngle = 90f;
if (controller.isGrounded && Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, 2f))
{
Vector3 move = new Vector3(move.x, 0, move.y).normalized;
float surfaceAngle = Vector3.Angle(move, hit.normal);
// only activate if inclination is above 35°
if (surfaceAngle - flatAngle < 35f)
{
Debug.Log("On a flat surface");
}
else if (surfaceAngle < 90)
{
Debug.Log("Moving uphill");
// Reduce player speed
}
else
{
Debug.Log("Moving downhill");
}
}
If the surface can tilt in all directions, then this might be more difficult.