Search Unity

Spinning an Object with a Natural, Smooth Ending

Discussion in 'Scripting' started by g0tNoodles, Dec 12, 2019.

  1. g0tNoodles

    g0tNoodles

    Joined:
    Nov 28, 2010
    Posts:
    193
    I was wondering if anyone could help me amend some code to try and help me give a more natural feeling/appearance. The object currently spins pretty well, the main issue is making it come to a (complete) stop more naturally. Currently, with the stopping/slowing part you can pretty easily tell when it's happening, it's quite jerky.

    The is part of my current spin script:

    Code (CSharp):
    1. public void SetSpinValues()
    2.     {
    3.             setRotation = Random.Range(minRotation, maxRotation);
    4.             targetRotation = Quaternion.Euler(new Vector3(0, 178, 0));
    5.             spinTime = Random.Range(minSpinTime, maxSpinTime);
    6.     }
    Code (CSharp):
    1. f (isSpinning == true)
    2.         {
    3.  
    4.             if (spinTime > 0)
    5.             {
    6.                 spinTime -= Time.deltaTime;
    7.                 spinnerCentre.transform.Rotate(Vector3.up, 360 * Time.deltaTime * 1.0f);
    8.             }
    9.             else if (spinTime <= 0)
    10.             {
    11.                 spinTime = 0;
    12.                 currentRotation = spinnerCentre.transform.eulerAngles;
    13.                 isSpinning = false;
    14.             }
    15.  
    16.         }
    17.         else if (isSpinning != true)
    18.         {
    19.             targetRotation = Quaternion.Euler(currentRotation.x, currentRotation.y + setRotation, currentRotation.z);
    20.             spinnerCentre.transform.rotation = Quaternion.Lerp(spinnerCentre.transform.rotation, targetRotation, 1f * smooth * Time.deltaTime);
    21. }
    Any help/advice is appreciated.
     
  2. Errorsatz

    Errorsatz

    Joined:
    Aug 8, 2012
    Posts:
    555
    It looks like some code got cut from the snippet, but from what I can see that Lerp isn't going to match the velocity it was spinning at except by coincidence. Also, while you set targetRotation in StartRotation, it gets overridden in the actual rotation code.

    Since you're just trying to stop over a fixed distance rather than at a particular target (Probably? The use of setRotation is unclear), I think you'd be better off using actual deceleration.

    Code (CSharp):
    1. void Update()
    2. {
    3.    if(spinTime > 0)
    4.    {
    5.       spinTime -= Time.deltaTime;
    6.       spinCentre.transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime);
    7.    }
    8.    else if(rotateSpeed > 0)
    9.    {
    10.       rotateSpeed = Mathf.Max(rotateSpeed - deceleration * Time.deltaTime, 0f);
    11.       spinCentre.transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime);
    12.    }
    13. }
    Rotate line is repeated instead of outside the condition so that it doesn't get called when not spinning. Obviously you'd set the rotateSpeed to whatever starting velocity at the same place you set the spinTime.
     
    Last edited: Dec 12, 2019