Prevent 'bobbing' or 'bouncing' with smooth locomotion on incline surface.

With the Continuous Move Provider, when moving down an inclined surface, there is some unpleasant bobbing. Since the unpleasentness only happens when going down a slope, my hunch is that it’s related to the gravity of the CharacterController sort of ‘catching up’.

I’ve tried turning off UseGravity, and added the following script, but it doesn’t provide great results either:

using UnityEngine;

public class LockToFloor : MonoBehaviour
{
    void FixedUpdate()
    {
        RaycastHit hit;       
        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, Mathf.Infinity))
        {
            transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.z);
        }
    }
}

I recorded a video demonstrating my issue, though it’s not super noticeable when you’re not wearing the HMD!
d89qbq

Any ideas on how to make it smooth?

You need to apply a constant force when you character controller is on a slope. The way I solved it was, when the character is moving in a direction, I shoot a raycast from the center down and check if the ray.normal is Vector3.up. if not, I apply charactercontroller.move(Vector3.down * slopeforce * Time.fixedDeltaTime).

Tho, I do not used the provided continuous move script. My project started before that existed.

Some of my code

 if ((inputAxis.y >= joystickDeadzone) || (inputAxis.y <= -joystickDeadzone) ||  (inputAxis.x >= joystickDeadzone) || (inputAxis.x <= -joystickDeadzone))
        {
            if (!offhandDirection)
                direction = headYaw * new Vector3(inputAxis.x, 0, inputAxis.y);
            else
                direction = handYaw * new Vector3(inputAxis.x, 0, inputAxis.y);
            character.Move(direction * Time.fixedDeltaTime * speed);
            if (OnSlope())
                character.Move(Vector3.down * (character.center.y) * slopeForce * Time.fixedDeltaTime);
        }
public bool OnSlope()
    {
        if (this.gameObject.GetComponent<XR_JumpController>().isJumping)
                return false;

        RaycastHit slopeHit;      
        if (Physics.Raycast(transform.TransformPoint(character.center), Vector3.down, out slopeHit, (character.center.y - slopeRayLength)))
        {
            if (slopeHit.normal != Vector3.up)
                return true;
        }
          
        return false;

    }
1 Like

Thanks! I like your thought process. I’ll give it a try!

Eureka! I’ve got it working. The issue was that I was doing my “Lock to Floor” calculations in FixedUpdate(), when I should have been doing it in LateUpdate().

Note: “Use Gravity” is disabled on the Continuous Move Provider.