0
\$\begingroup\$

The bots have a simple Capsule collider which cannot tilt. Movement is applied across the horizontal axes, gravity is enabled on the rigidbody. It moves up stairs okay with steps roughly 0.2 units high. When the bots speed is too slow or he is moving up steep ramps he gets stuck. I've tried tinkering to fix the problem but to no avail.

    float gravity = currentMovementSpeed * 2f;
    Physics.gravity = new Vector3(0, -gravity, 0);

Here is the problem: https://youtu.be/ypCavT3_As0

enter image description here

What is a simple way to consistently force a collider up ramps and stairs?

\$\endgroup\$
0
\$\begingroup\$

I managed to tinker my way to success. But if someone has a REAL answer to this question, please go ahead and post it.

I set an empty gameobject inside the collider and raycasted two rays, one straight down, one at a 45deg angle forward (The bots only move forwards). I calculate the incline of the slope from the two hitpoints of the rays.

The steeper the slope, the lower gravity acts onto the object.

Trouble is if the distance of the gameobject off the ground is too low it will not recognise a slope because the collider bumps into it much further away. If the distance is too high, the collider will think the slope has flattened before it actually has. To fix the issues I actually raycasted twice, once from very close off the ground, and one from a distance equal to the radius of the collider:

enter image description here

enter image description here

Seems to work: https://youtu.be/6qfwMhLqrfo

Code:

void setGravity()
{
    RaycastHit hitInfoDown;
    RaycastHit hitInfoAngle;

    Ray rayDown = new Ray(slopeReader.transform.position, -Vector3.up);
    Ray rayAngle = new Ray(slopeReader.transform.position, transform.forward + -Vector3.up);

    if (Physics.Raycast(rayDown, out hitInfoDown, 1000, shootLayerMask)) { }
    if (Physics.Raycast(rayAngle, out hitInfoAngle, 1000, shootLayerMask)) { }

    float angleHigh = Vector3.Angle(slopeReader.transform.forward, hitInfoAngle.point - hitInfoDown.point); //Angle 0.5m above the ground
    if (hitInfoDown.point.y > hitInfoAngle.point.y)
        angleHigh = -angleHigh;


    rayDown = new Ray(slopeReader.transform.GetChild(0).transform.position, -Vector3.up);
    rayAngle = new Ray(slopeReader.transform.GetChild(0).transform.position, transform.forward + -Vector3.up);

    if (Physics.Raycast(rayDown, out hitInfoDown, 1000, shootLayerMask)) { }
    if (Physics.Raycast(rayAngle, out hitInfoAngle, 1000, shootLayerMask)) { }

    float angle = Vector3.Angle(slopeReader.transform.GetChild(0).transform.forward, hitInfoAngle.point - hitInfoDown.point); //Angle 0.1m above the ground
    if (hitInfoDown.point.y > hitInfoAngle.point.y)
        angle = -angle;


    if (Mathf.Abs(angleHigh) > Mathf.Abs(angle))
        angle = angleHigh;

    float distanceToFloor = (hitInfoDown.point - slopeReader.transform.GetChild(0).transform.position).magnitude - 0.1f;
    if (angle > 0 && distanceToFloor < 0.4f)
    {
        angle = Mathf.Clamp(angle, 0, 60);
        float grav = Mathf.Pow(1 - (angle / 60), 5); //Increase power for higher slopes / higher speed on steep slopes (5 works fine for 60 degree slopes)
        float speedModifier = Mathf.Clamp(currentMovementSpeed / 2, 0, 1);

        grav = grav * speedModifier;
        grav = grav - 1; //-(1-grav)

        GetComponent<Rigidbody>().AddForce(Physics.gravity * GetComponent<Rigidbody>().mass * grav);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.