Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

Question Why is Rigidbody controller unrealistically launching into the air upon traversing a steep slope?

Discussion in 'Physics' started by ml785, Dec 10, 2022.

  1. ml785

    ml785

    Joined:
    Dec 20, 2018
    Posts:
    119
    UPDATE: I figured out it's because I'm clamping X and Z velocity but not Y velocity, so I'm moving slowly forward but my Y velocity is allowed to just go insane. That being said, I don't know an elegant solution of clamping Y velocity while still allowing Gravity to act 'naturally' on my Player rigidbody.

    ___

    ORIGINAL POST:


    Desired behavior: Controller gets slower upon hitting steep slope and/or isn't able to move up it because it's too steep

    Current behavior: Controller can just run up a ramp and go completely airborne. Feels very physically unnatural. Gif of this happening:



    Why might this be happening? How might this board suggest altering the code to make the slope movement more natural?

    Current code below...

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Movement : MonoBehaviour
    6. {
    7.     Rigidbody r;
    8.     public CapsuleCollider capsule;
    9.     public Transform cameraTransform;
    10.  
    11.     //Base Movement
    12.     public float horizontalInput;
    13.     public float verticalInput;
    14.     public Vector3 moveDirection;
    15.     public Vector3 moveDirectionRaw;
    16.     public int rotDegPerSecond = 720;
    17.     public float speed;
    18.     public float maxSpeed;
    19.  
    20.     //GroundChecking
    21.     public LayerMask groundLayerMask;
    22.     public Transform groundCheckTransform;
    23.     public bool isGrounded;
    24.     public float groundCheckRadius = 0.25f;
    25.     public float distanceToGround;
    26.  
    27.  
    28.     void Awake()
    29.     {
    30.         r = GetComponent<Rigidbody>();
    31.         capsule = GetComponent<CapsuleCollider>();
    32.     }
    33.  
    34.     void Update()
    35.     {
    36.         horizontalInput = Input.GetAxis("Horizontal");
    37.         verticalInput = Input.GetAxis("Vertical");
    38.     }
    39.  
    40.     private void FixedUpdate()
    41.     {
    42.         moveDirection = new Vector3(horizontalInput, 0.0f, verticalInput).normalized;
    43.         moveDirection = (Quaternion.AngleAxis(cameraTransform.rotation.eulerAngles.y, Vector3.up) * moveDirection).normalized;
    44.         moveDirectionRaw = new Vector3(Input.GetAxisRaw("Horizontal"), 0.0f, Input.GetAxisRaw("Vertical")).normalized;
    45.         moveDirectionRaw = (Quaternion.AngleAxis(cameraTransform.rotation.eulerAngles.y, Vector3.up) * moveDirectionRaw).normalized;
    46.  
    47.         if (moveDirectionRaw != Vector3.zero && moveDirection != Vector3.zero)
    48.         {
    49.             Quaternion targetRotation = Quaternion.LookRotation(moveDirection); //or moveDirectionRaw
    50.             targetRotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotDegPerSecond * Time.deltaTime);
    51.             r.MoveRotation(targetRotation);
    52.         }
    53.  
    54.         Vector3 force = moveDirection * speed;
    55.         r.AddForce(force, ForceMode.Force);
    56.         }    
    57.  
    58.         Vector3 velocityH = new Vector3(r.velocity.x, 0, r.velocity.z);
    59.         Vector3 velocityV = new Vector3(0, r.velocity.y, 0);
    60.         r.velocity = Vector3.ClampMagnitude(velocityH, 5) + velocityV;
    61.         print(r.velocity.x + " " + r.velocity.y + " " + r.velocity.z);
    62.  
    63.         GroundStopSlide();
    64.         GroundCheck();
    65.     }
    66.  
    67.     void GroundStopSlide()
    68.     {
    69.         if (moveDirectionRaw == Vector3.zero)
    70.         {
    71.             Vector3 zeroMe = new Vector3(0, r.velocity.y, 0);
    72.             r.velocity = zeroMe;
    73.         }
    74.     }
    75.  
    76.     public void GroundCheck()
    77.     {
    78.         isGrounded = Physics.CheckSphere(groundCheckTransform.position, groundCheckRadius, groundLayerMask);
    79.  
    80.     }
    81.  
    82.  
    83.  
    84. }
     
    Last edited: Dec 10, 2022
  2. Edy

    Edy

    Joined:
    Jun 3, 2010
    Posts:
    2,565
    Most likely is about the code modifying the velocity of the rigidbody. Doing so overrides the calculations of the physics solver, which may result in unexpected effects. Removing any modification to r.velocity will cause a realistic behavior.

    You may try modifying the velocity using AddForce with ForceMode.VelocityChange instead of changing r.velocity. If the issue persists, then the issue is in your calculations for the velocity.

    You can modify the velocity of the rigidbody with AddForce like this:
    Code (CSharp):
    1. rigidbody.AddForce(wantedVelocity - r.velocity, ForceMode.VelocityChange);
     
    ml785 likes this.