How to get object to walk around on mesh sideways and upside down

Trying to get objects to move around things sideways and upside down… like a bug would walk on a ceiling or wall…

The green lines in the gif are projected normals from the collision point, and the blue line is the downward raycast from the movable object. Right now I have a convex mesh collider on the big orange capsule and no collider on the green movable object.

So far I am raycasting down from -transform.up and then trying to rotate the object to the normal of the collision point in FixedUpdate… I get this really jittery result where it seems like it kind of works but something is off.

Any help smoothing this out and getting it to work correctly?

public class WalkAnywhere : MonoBehaviour
{
    public float downRayDistance = 10;
    public Vector3 downDirection;

    void Update()
    {
        downDirection = -transform.up;

        Debug.DrawRay(transform.position, downDirection * downRayDistance, Color.blue);
        var downRay = new Ray(transform.position, downDirection * downRayDistance);

        RaycastHit downRayInfo;
        Physics.Raycast(downRay, out downRayInfo, downRayDistance, 1);

        Debug.Log(downRayInfo.point);
        Debug.Log(downRayInfo.normal);
        Debug.DrawLine(downRayInfo.point, downRayInfo.point + downRayInfo.normal, Color.green, 4, false);
        positionOnTerrain(downRayInfo);
    }

    void positionOnTerrain(RaycastHit downRayInfo)
    {
        Vector3 normal = downRayInfo.normal;
        Vector3 point = downRayInfo.point;

        Quaternion targetRotation = Quaternion.FromToRotation(transform.up, normal);
        Quaternion finalRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, 90);
        transform.rotation = finalRotation;

        transform.position = point + transform.up;
    }
}

I took your code for a spin, and it’s to do with the way you’re doing the rotation.

        Quaternion targetRotation = Quaternion.LookRotation(transform.forward, normal);
        Quaternion finalRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, 90f * Time.deltaTime);

This should fix the jittery behavior. But I suggest you look into an alternative method of achieving your goal, as a single raycast will more often than not fail to do what you’re looking for here. Especially when the mesh is complicated.


You should take a look at this as a way of doing it.