Search Unity

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

Discussion in 'XR Interaction Toolkit and Input' started by HeyBishop, Mar 15, 2021.

  1. HeyBishop

    HeyBishop

    Joined:
    Jun 22, 2017
    Posts:
    238
    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:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class LockToFloor : MonoBehaviour
    4. {
    5.     void FixedUpdate()
    6.     {
    7.         RaycastHit hit;      
    8.         if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, Mathf.Infinity))
    9.         {
    10.             transform.position = new Vector3(transform.position.x, hit.point.y, transform.position.z);
    11.         }
    12.     }
    13. }
    I recorded a video demonstrating my issue, though it's not super noticeable when you're not wearing the HMD!


    Any ideas on how to make it smooth?
     
  2. dpcactus

    dpcactus

    Joined:
    Jan 13, 2020
    Posts:
    53
    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

    Code (CSharp):
    1.  if ((inputAxis.y >= joystickDeadzone) || (inputAxis.y <= -joystickDeadzone) ||  (inputAxis.x >= joystickDeadzone) || (inputAxis.x <= -joystickDeadzone))
    2.         {
    3.             if (!offhandDirection)
    4.                 direction = headYaw * new Vector3(inputAxis.x, 0, inputAxis.y);
    5.             else
    6.                 direction = handYaw * new Vector3(inputAxis.x, 0, inputAxis.y);
    7.             character.Move(direction * Time.fixedDeltaTime * speed);
    8.             if (OnSlope())
    9.                 character.Move(Vector3.down * (character.center.y) * slopeForce * Time.fixedDeltaTime);
    10.         }


    Code (CSharp):
    1. public bool OnSlope()
    2.     {
    3.         if (this.gameObject.GetComponent<XR_JumpController>().isJumping)
    4.                 return false;
    5.  
    6.         RaycastHit slopeHit;      
    7.         if (Physics.Raycast(transform.TransformPoint(character.center), Vector3.down, out slopeHit, (character.center.y - slopeRayLength)))
    8.         {
    9.             if (slopeHit.normal != Vector3.up)
    10.                 return true;
    11.         }
    12.          
    13.         return false;
    14.  
    15.     }
     
    HeyBishop likes this.
  3. HeyBishop

    HeyBishop

    Joined:
    Jun 22, 2017
    Posts:
    238
    Thanks! I like your thought process. I'll give it a try!
     
  4. HeyBishop

    HeyBishop

    Joined:
    Jun 22, 2017
    Posts:
    238
    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.