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. Dismiss Notice

How to smoothly rotate gameobject to the specified value

Discussion in 'Scripting' started by elmar1028, Sep 11, 2014.

  1. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    Hi guys,

    Basically I want to set the rotation value of a gameobject which then smoothly rotates to that point.

    I've tried using Mathf.SmoothDamp, but it didn't work.

    Any ideas?

    Thanks in advance! :)
     
  2. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    659
    Quaternion.Slerp( currentRot, targetRot, 0.1f );

    if you want to be really fancy, get Time.detlaTime involved.
     
  3. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    What should I put instead of currentRot and targetRot? Should I put some values or transform value or Vector3?
     
  4. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    659
    They are both quaternions. The idea is that currentRot is you current rotation, and targetRot is the rotation that you want to go to.

    so I guess something like this

    Float speed = 0.1f;
    Quaternion currentRot = transform.rotation;
    Quaternion targetRot = a quaternion that represents that rotation you want to go to.

    transform.rotation = Quaternion.Slerp( currentRot, targetRot, speed );

    And this would get called every Update. Basically it moves it 10% of the way to the target rotation each time.
     
    Gigiwoo likes this.
  5. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    Thanks!

    What is this w component in the inspector? I thought there are x, y, z axis only :O

    Edit: To be more detailed I am trying to rotate the camera (which is constantly controlled by mouse)
    So far I have created a function which allows me to stop camera from being controlled and then look down wait for several seconds and then look up.
     
  6. fffMalzbier

    fffMalzbier

    Joined:
    Jun 14, 2011
    Posts:
    3,276
    for the
    The Euler-angels are a Vector 3 (x,y,z), they are used because they are simple to wrap the head around.
    The actual Rotation is calculated in Quaternions (x,y,z,w). That is needed to avoid some problems like Gimbal Lock .
     
  7. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    659
    Don't worry about the internal components of a quaternion. All you need to know is that it represents a rotation.

    Although if you're interested... basically, you're right. A rotation is 3 dimensional. These quaternions are in fact "unit" quaternions, meaning they have magnitude 1. So they essentially represent a point on the boundary of a 4 dimensional ball of radius 1, which is a 3D space. Think of it as a 3D space that wraps back round on it's self in each direction. It's a much better way to store a rotation than a 3 variable pitch-roll-yaw system because it doesn't suffer from gimbal lock.

    Sounds like you want it to look down. Try this:

    if( lookingDown )
    {
    Float speed = 0.1f;
    Quaternion currentRot = transform.rotation;
    Quaternion targetRot = Quaternion.LookRotation( -Vector3.up, transform.forward+transform.up );

    transform.rotation = Quaternion.Slerp( currentRot, targetRot, speed );
    }

    Super bonus optional framerate independance:

    Float speed = 10f*( 1f - Mathf.Exp( -Time.deltaTime ) );

    instead of the constant value.
     
  8. BmxGrilled

    BmxGrilled

    Joined:
    Jan 27, 2014
    Posts:
    238
    Code (JavaScript):
    1. //smoothRot.js
    2. //Javascript
    3. public var rotation : Vector3;
    4. public var damping : float;
    5.  
    6. void Update()
    7. {
    8.     Quaternion currentRot = transform.rotation;
    9.     Quaternion targerRot = Quaternion.Euler(rotation);
    10.     Quaternion smoothRot = Quaternion.Slerp(currentRot, targerRot, Time.deltaTime / damping);
    11.     //TODO: assign smoothRot where needed, e.g. transform.rotation = smoothRot;
    12. }
    13.  
    Code (csharp):
    1. //smoothRot.cs
    2. //C#
    3. using UnityEngine;
    4. using System.Collections;
    5.  
    6. public class smoothRot : MonoBehaviour
    7. {
    8.     public Vector3 rotation;
    9.     public float damping;
    10.  
    11.     public void Update()
    12.     {
    13.         Quaternion currentRot = transform.rotation;
    14.         Quaternion targerRot = Quaternion.Euler(rotation);
    15.         Quaternion smoothRot = Quaternion.Slerp(currentRot, targerRot, Time.deltaTime / damping);
    16.         //TODO: assign smoothRot where needed, e.g. transform.rotation = smoothRot;
    17.     }
    18. }
    19.  
    ~
    Another walk in the park.
     
    Last edited: Sep 11, 2014
  9. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    659
    Emma's script is ok.

    However, I can't stand ideally by when someone puts Time.deltaTime into a Lerp or Slerp time parameter. This doesn't give you any kind of frame-rate independence. Think about this example used to illustrate the point. If you're frame rate drops to the point where you are putting a 1 into the function, the result will snap straight to the target rotation. Where as if the function had have been called several times over that period (as normal) it would still be nowhere near the target.

    Please use 1f - Mathf.Exp( -Time.deltaTime ) instead.

    This way the resulting angle will end up the same with respect to time, regardless of how long the frames take to process.

    I'm not suggesting you calculate this value for every Lerp or Slerp that you do. Just do it once per Update and reference the result in each function.

    (This is just for when you use Lerp and Slerp for exponential decay, like we're doing here, not for things that change at a constant rate.)
     
  10. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    Thank you @Zomby138 and @TwixEmma

    1) I have no errors, however when I press the button, it instantly looks down, then after several seconds it goes back up in the same manner.

    2) Also, how do I make it go down to 75 units?

    3) Just a reminder, my camera is constantly changing rotation values since it's controlled by player's mouse. It's also parented to the player GameObject.
     
  11. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    659
    Personally I would do both the mouse controlled rotation and this code in the same script. I would have a bool for if you're in the looking down mode and use an if-else to control which code happens based on that.

    As for it instantly looking down, my first guess would be that you got the wrong value for the first Slerp parameter. Second guess is the script isn't attached to the correct transform. We'd need to see your code to really help you.
     
  12. Zomby138

    Zomby138

    Joined:
    Nov 3, 2009
    Posts:
    659
    Also, I didn't understand what you meant by 75 units?
     
  13. elmar1028

    elmar1028

    Joined:
    Nov 21, 2013
    Posts:
    2,353
    I want my camera's x rotation to be set to 75. (smoothly rotating towards this point) I have attached your script to the camera directly.
     
    Last edited: Sep 13, 2014