Search Unity

[Solved] Quaternion smooth rotation

Discussion in 'Scripting' started by darugylsweater, May 12, 2015.

  1. darugylsweater

    darugylsweater

    Joined:
    Oct 26, 2013
    Posts:
    17
    So I am working on a Wipeout/F Zero style game, we have the hover mechanics work and we have the player aligning to the grounds normal's but when the players ship rotates to match the ground it is very choppy, I think it has something to do with this line of code
    Code (JavaScript):
    1. transform.rotation = Quaternion.FromToRotation(Vector3.up, rcHit.normal);
    Is there a way to smooth it out
     
    maifee likes this.
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    I think this should work...

    float rotSpeed = 10;

    transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.Euler(rcHit.normal.x, rcHit.normal.y, rcHit.normal.z), rotSpeed * Time.deltaTime);
     
  3. darugylsweater

    darugylsweater

    Joined:
    Oct 26, 2013
    Posts:
    17
    That did
    That didn't work if it helps here is the whole script
    Code (JavaScript):
    1. function FixedUpdate()
    2. {
    3. //make platform adjust terrain rotation
    4. var rcHit : RaycastHit;
    5. //Make raycast direction down
    6. var theRay : Vector3 = transform.TransformDirection(Vector3.down);
    7. if (Physics.Raycast(transform.position, theRay, rcHit))
    8. {
    9.      //this is for getting distance from object to the ground
    10.      var GroundDis = rcHit.distance;
    11.      //with this you rotate object to adjust with terrain
    12.      transform.rotation = Quaternion.FromToRotation(Vector3.up, rcHit.normal);
    13.      //finally, this is for putting object IN the ground
    14.      //transform.localPosition.y = (transform.localPosition.y - GroundDis)+1;
    15. }
    16. }
    And a demonstration video of what is happening, watch how choppy it is when it aligns to the surface of the track
     
    treedimober likes this.
  4. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,616
    hmm Ive never used FromToRotation, so must have mis-understood how it works.

    either way, you need to incorporate deltaTime to smooth out the movement...

    this looks nasty, but might work... increased speedRot if its not rotating fast enough.

    float speedRot = 45;
    transform.rotation= Quaternion.RotateTowards(transform.rotation, Quaternion.FromToRotation(Vector3.up, rcHit.normal), speedRot * Time.deltaTime);
     
  5. darugylsweater

    darugylsweater

    Joined:
    Oct 26, 2013
    Posts:
    17
    I was able to fix it myself, here is the fixed code
    Code (JavaScript):
    1. var smooth = 10;
    2.  
    3. function FixedUpdate()
    4. {
    5. //make platform adjust terrain rotation
    6. var rcHit : RaycastHit;
    7. //Make raycast direction down
    8. var theRay : Vector3 = transform.TransformDirection(Vector3.down);
    9. if (Physics.Raycast(transform.position, theRay, rcHit))
    10. {
    11.      //this is for getting distance from object to the ground
    12.      var GroundDis = rcHit.distance;
    13.      //get rotation
    14.      targetRotation = Quaternion.FromToRotation(Vector3.up, rcHit.normal);
    15.    
    16.      //Smooth rotation
    17.      transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime * smooth);
    18.      //finally, this is for putting object IN the ground
    19.      //transform.localPosition.y = (transform.localPosition.y - GroundDis)+1;
    20. }
    21. }
     
    Protokoll likes this.
  6. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    This is the wrong way to use Lerp

    Code (csharp):
    1. transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime* smooth);
    Yes, it will look like it works, but the final argument to Lerp should be a value between 0 and 1, determining how it should interpolate between the original and target quaternion. When you do it like above, it will never quite reach the target rotation, because Time.deltaTime*smooth never increases, it's about the same value all the time.

    You should instead use Quaternion.RotateTowards. It should work like this:
    Code (csharp):
    1. transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, smooth * Time.deltaTime);
    The only difference to watch out for is that smooth is now maxDegreesDelta, so a higher smooth value will give faster movement, while a lower will give slower and smoother movement.
     
  7. wyt000

    wyt000

    Joined:
    Jan 27, 2016
    Posts:
    1
    Thank you! It solved my problem.
     
  8. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,566
    In case someone runs into this thread in the future.

    This:
    Code (csharp):
    1. transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime* smooth);
    Is actually an almost valid idea, except that instead of Quaternion.Lerp,. Quaternion.SLerp should be used, and actually it can be done without scaling with delta time.

    In practice, those two fragments have different effect.
    Code (csharp):
    1. transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, smooth);
    Code (csharp):
    1. transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, smooth * Time.deltaTime)
    Quaternion.RotateForwards will slow down maximum rotation speed, so the rotation will slowly turn towards the target like a turret.
    However, it will not remove any small jitter that may be present in target rotation.

    Approach based on Quaternion.Slerp, however acts like a stabilizer or "lowpass" filter. Meaning if there's jitter present in target rotation, it will smooth it out, without limiting maximum rotation speed.

    In practice, even though it "isn't supposed to quite reach the target rotaion", it will do so over time.

    One issue is that the "smooth" parameter doesn't quite scale based on delta time and works best with a fixed value. However, using a fixed value makes the calculation framerate dependent.
     
    CullyLine and spiney199 like this.
  9. aniiket101

    aniiket101

    Joined:
    Feb 21, 2021
    Posts:
    3
     
  10. aniiket101

    aniiket101

    Joined:
    Feb 21, 2021
    Posts:
    3
    This work for me thanks man
     
  11. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089