1
votes

I'm making a movement system for a 3rd person platforming/action game. Since the character controller just stops on a sloped surface with an incline greater than it's max I've programmed some decent slope logic in but it hits an edge case.

RaycastHit hit;
Physics.Raycast(transform.position, Vector3.down, out hit);
if (isGrounded)
{
    if (Vector3.Angle(transform.up, hit.normal) > CC.slopeLimit)
    {
        gravVector.x += (1f - hit.normal.y) * hit.normal.x * slideFriction * Time.deltaTime;
        gravVector.z += (1f - hit.normal.y) * hit.normal.z * slideFriction * Time.deltaTime;
        if (gravVector.y > -maxGravity * Vector3.Angle(transform.up, hit.normal) / 90)
        {
            gravVector.y -= Vector3.Angle(transform.up, hit.normal) / 90 * accGravity * Time.deltaTime;
        }
        return gravVector;
    }
    //else gravity is straight down n stuff
}

Since I'm using a Raycast straight down from the player origin to find the normal of the surface the player is on, the player can slide to the end of a slope and the Capsule will still be colliding against the slope but the raycast either hits a flat surface or nothing at all and the player gets stuck in a falling state on the end of a sloped surface.

Visual representation of the issue

Is there a way to get the normal of the the surface the player is on without using some insane spherical raycast system or something? I tried using the Character Controller and some other collider around the player to get contact points but I just cant get this stuff to work.

1

1 Answers

1
votes

You could consider using Physics.SphereCast to cast over a larger area, say, the size of your controller's Capsule collider. It's not "some insane spherical raycast system" - it's a reasonably efficient built-in in Unity meant for situations like these.