Saturday, July 23, 2016

c# - Rotate an object smoothly on the Y axis in Unity


I am attempting a simple script to swing a door open in Unity. This requires a smooth rotation of 90 degrees around the Y axis. I have seen that one way to do this is using Unity's Quanternion object. I believed that this should work:


public class DoorOpenScript : MonoBehaviour 
{

public float smooth = 20;

// Use this for initialization

void Start ()
{
SwingOpen ();
}

// Update is called once per frame
void Update ()
{

}


void SwingOpen()
{
Quaternion newRotation = new Quaternion(transform.rotation.x,transform.rotation.y,transform.rotation.z,transform.rotation.w);;
newRotation *= Quaternion.Euler(0, 90, 0); // this add a 90 degrees Y rotation
transform.rotation= Quaternion.Slerp(transform.rotation, newRotation,20 * Time.deltaTime);

}

}


However, this just opens the door completely. I have tried playing with the third parameter to Slerp but with no results. What am I doing incorrectly?



Answer



Think about what you need to do, open the door over time. It's not going to happen all in one call in the Start function. You'll need to add a little more rotation each frame to rotate the object smoothly. Something like the following will rotate the object from 0 to 90 degrees over time:


void Update () {
SwingOpen();
}

void SwingOpen()
{

Quaternion newRotation = Quaternion.AngleAxis(90, Vector3.up);
transform.rotation= Quaternion.Slerp(transform.rotation, newRotation, .05f);
}

Notice it's using the Update() function instead of Start(). That's because we want to change it a little each frame. Using Slerp you'll notice that the object swings fast at first, then slower until finally reaching its rotation. The last parameter controls that rate of change, with 1 being instantly and 0 being never.


Perhaps this is your intended behavior, if not you can also perform a constant rotation over time with something like the following:


public float rotationDegreesPerSecond = 45f;
public float rotationDegreesAmount = 90f;
private float totalRotation = 0;
// Use this for initialization

void Start () {

}

// Update is called once per frame
void Update () {
//if we haven't reached the desired rotation, swing

if(Mathf.Abs(totalRotation) < Mathf.Abs(rotationDegreesAmount))
SwingOpen();

}

void SwingOpen()
{
float currentAngle = transform.rotation.eulerAngles.y;
transform.rotation =
Quaternion.AngleAxis(currentAngle + (Time.deltaTime * degreesPerSecond), Vector3.up);
totalRotation += Time.deltaTime * degreesPerSecond;
}


In this case, the rotation of the door will take 2 seconds to reach 90 degrees.


And just a tip, setting the variables to public will allow you to edit them from the Unity editor. This means you can apply this same script to multiple objects, but change the values for each object without editing the script.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...