Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Rigibody.velocity.magnitude on slopes.

Discussion in 'Physics' started by Denis-Valjean, Apr 19, 2015.

  1. Denis-Valjean

    Denis-Valjean

    Joined:
    Mar 25, 2015
    Posts:
    39
    Using the code below under FixedUpdate. Attached a video showing that the speed is shown correctly when on a flat plane, but as soon as I begin to climb a slope, it does not slown down (my char does) and when stopped over the hill, the actualPlayerSpeed gets crazy. Any Solution?



    // Forward Input
    if (vertical > 0.0f && horizontal == 0.0f) {

    playerRigidBody.velocity = transform.forward * maximumPlayerSpeed;

    }

    actualPlayerSpeed = playerRigidBody.velocity.magnitude
     
  2. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
    You are only adding velocity to your transform.forward. So when the terrain gradually gets more and more in front of you, the forward velocity becomes useless. To fix this you should consider rotating your player along the normals of the surface you are on.
     
  3. Denis-Valjean

    Denis-Valjean

    Joined:
    Mar 25, 2015
    Posts:
    39
    Can you give me a simple example, please?
     
  4. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
  5. Denis-Valjean

    Denis-Valjean

    Joined:
    Mar 25, 2015
    Posts:
    39
    Ok. Thanks for helping. I am gonna try.
     
  6. Denis-Valjean

    Denis-Valjean

    Joined:
    Mar 25, 2015
    Posts:
    39
    Ok. Using this:
    Code (CSharp):
    1.     if(Physics.Raycast(transform.position, -transform.up, out tick));
    2.             {
    3.                 transform.rotation = Quaternion.FromToRotation(transform.up, tick.normal);
    4.                 Debug.DrawRay (tick.point, tick.normal*5f, Color.red);
    5.    
    6.             }
    1. Raycast to find normal of slope;
    2. QuaternionFromToRotation gets the angle I shoud rotate my char in the "x" axis, the angle between transform.up and normal;
    3. But now, how do I rotate my char in the x axis? I tried: playerRigidBody.transform.Rotate(transform.rotation.eulerAngles, 0, 0); with no sucess. Video attached.

     
  7. Denis-Valjean

    Denis-Valjean

    Joined:
    Mar 25, 2015
    Posts:
    39
    Figured out! This ^*^&^&* script was messing it all!!
    Code (CSharp):
    1. void MouseRotatePlayer()
    2. {
    3. yRotation += Input.GetAxis ("Mouse X") * lookSensitivity;
    4. xRotation -= Input.GetAxis ("Mouse Y") * lookSensitivity;
    5. transform.rotation = Quaternion.Euler (0, yRotation, 0);

    6. }
    It was at update reseting my X rotation all time. Even though, my "current speed value "is still crazy when climbing slopes". Why?
     
  8. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
    How are you calculating current speed?
     
  9. Denis-Valjean

    Denis-Valjean

    Joined:
    Mar 25, 2015
    Posts:
    39
    I am using:

    actualPlayerSpeed = playerRigidBody.velocity.magnitude;

    I discovered that when using any other function that does a transform.rotation, like the Mouse RotatePlayer I mentioned above,the speed begins to get crazy on slopes, but only when stopped. If moving, the speed value is correct.. So, the align player with normals do the same thing. To solve the problem I am adding a function to check if the player is moving:


    Code (CSharp):
    1.     void CheckIfPlayerIsMoving()
    2.  
    3.     {
    4.         Vector3 curPos = transform.position;
    5.        
    6.         if (curPos == lastPos)
    7.         {
    8.             actualPlayerSpeed = 0f;
    9.         } else
    10.         {
    11.             actualPlayerSpeed = playerRigidBody.velocity.magnitude;
    12.         }
    13.        
    14.         lastPos = curPos;
    15.     }
    16.  

    Now, when not moving,the speed goes instantly to zero and speed when stopped is not "flickering" anymore (values like 1.xxxxxxxxxx-e). I dont know if is the right thing to do it, but its working. If anyone has a better suggestion... I am accepting, because I found a 'solution", but I want to understand what is causing the issue. Thanks.
     
  10. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
    Physics in Unity3D certainly is not perfect. And your method for zeroing the speed is fine if it works. When dealing with rigidbody.velocity you typically want to zero that value out if you know you are not moving - since this may cause some unnatural jitter if it is never getting zeroed. So where you say:

    actualPlayerSpeed = 0f;

    You may also want to put:

    playerRigidBody.velocity = Vector3.zero;