Help with Physics.BoxCast

I’ve been struggling with this issue for days. Please, someone help.

I’ve got a sphere whose movement I need to restrict when rolling up steep slopes. I’ve been able to make this work, sorta, but the last bit of fine-tuning is giving me trouble. Can anyone help?

I’m currently using a standard Physics.Raycast to check for when I’m on a steep slope. The follow code is attached to the sphere I need to restrict:

public class BallEntity : MonoBehaviour
{

//slope movement https://www.youtube.com/watch?v=GI5LAbP5slE
    [Header("Slope Control")]
    [SerializeField] float _groundRayDistance;
    [SerializeField] private RaycastHit _slopeHit;
    [SerializeField] float _slopeLimit;



public bool OnSteepSlope()
    {
        if (CheckIsGrounded() == false) return false;

        float scRadius = GetComponent<SphereCollider>().radius;
        if (Physics.Raycast(gameObject.transform.position, Vector3.down, out _slopeHit, scRadius + _groundRayDistance))
        {
            float _slopeAngle = Vector3.Angle(_slopeHit.normal, Vector3.up);
            if (_slopeAngle > _slopeLimit)
            {
                return true;
            }
        }
        return false;
    }
}

This works (well enough), but as expected, given the spherical shape of the, well, the sphere and the position of the raycast (center of the sphere), my method allows the sphere to move up the slope a bit before the steep slope is detected. See the image below, which uses OnDrawGizmos() to show the position of the raycast:
attachFull1012855

I tried:

  • Using Vector3.forward along with the sphere’s radius to place the origin of the RayCast at the front of the sphere. I got close with this method, but I couldn’t get it to work.
  • Using a SphereCast instead of a standard RayCast. I couldn’t get this to work.
  • Using a BoxCast instead of a standard RayCast. I couldn’t get this to work either.

Is one of the three methods above the best way to solve this issue? If so, I suppose I might be doing something wrong. Or, is there a simpler method that I haven’t considered?

Thank you so much for all your help!

7929778--1012855--Cast.png

Since it is a ball I will use Spherecast.

Thanks. I went back to trying with the Spherecast and got it to work a bit better. I’m still not certain I’m going about it the best way, though.

I think the problem with my original Spherecast attempt was that the SphereCast radius was the same as the player radius. This must have caused some collision issues. I thought casts ignored the collider they originate inside of, but I must not fully understand. I’ll do some research into my assumption.

Anyway, I revised the code as follows. shrinking the radius of the SphereCast by *.9 feels fragile to me (I feel like I’ll run into issues with that as the game gets more complex), but for now it will work.

    //slope movement https://www.youtube.com/watch?v=GI5LAbP5slE
    [Header("Slope Control")]
    [SerializeField] public float _groundRayDistance;
    [SerializeField] private RaycastHit _slopeHit;
    [SerializeField] float _slopeLimit;

public bool OnSteepSlope()
    {
        if (CheckIsGrounded() == false) return false;

        float scRadius = GetComponent<SphereCollider>().radius;
        if (Physics.SphereCast(gameObject.transform.position, scRadius *.9f, Vector3.down, out _slopeHit))
        {
            float _slopeAngle = Vector3.Angle(_slopeHit.normal, Vector3.up);
            if (_slopeAngle > _slopeLimit)
            {
                return true;
            }
        }
        return false;
    }

Ray/Sphere/Box casts ignorthe collider in wich they originate in some cases.
The fact is, that colliders dont collide in two directions, so if the spherecast is originated in the center of the sphere will ignore it, but in the case of box/spheres since there are not in one dimension if the box/sphere is not completly inside the collider when originated, they will collide with it, in your case the spherecast was detecting the ball.

Change the layermask of the ball to “IgnoreRaycast”, and put the radiois of the spherecast to 1 again.
This should work.

1 Like

Thanks @r31o . I just implemented this solution, and it seems to be working well. I completely forgot about the layerMask overload!