- Home /
The question is answered, right answer was accepted
Quaternion.Slerp rotating immediately not over time
I am trying to create a camera system akin to the DSi/3DS version of Persona or Demon Gaze for the PS Vita. The problem is when I rotate the camera, it snaps to the end rotation immediately rather than over time (there's an empty game object with this script and a character controller attached with the camera as the child). The debug.log spits out that the timeProgressed variable is still counting upwards after it rotates 90 degrees (it's still less than one) but it's like Slerp/Lerp (tried both) ignores it.
private float rotation;
private Transform to;
private Transform from;
public float rotateSpeed;
void Update () {
ControlPlayer();
}
void ControlPlayer(){
from = transform;
if(cInput.GetKeyDown("Left")){
rotation -= 90.0f;
to.rotation = Quaternion.Euler(0, rotation, 0);
StartCoroutine(SlerpRot(from, to, rotateSpeed));
}
if(cInput.GetKeyDown("Right")){
rotation += 90.0f;
to.rotation = Quaternion.Euler(0, rotation, 0);
StartCoroutine(SlerpRot(from, to, rotateSpeed));
}
}
IEnumerator SlerpRot(Transform startRot, Transform endRot, float slerpTime){
float startTime = Time.time;
float endTime = startTime + slerpTime;
while(Time.time < endTime)
{
float timeProgressed = (Time.time - startTime) / slerpTime;
Debug.Log(timeProgressed);
transform.rotation = Quaternion.Slerp(startRot.rotation, endRot.rotation, timeProgressed);
yield return new WaitForEndOfFrame();
}
}
}
Answer by Deadcow_ · Apr 05, 2015 at 08:13 PM
You don't show where you instantiate to
variable, but it seems like variables from
and to
references the same object. Try to use Quaternion instead of Transform:
StartCoroutine(SlerpRot(transform.rotation, Quaternion.Euler(0, rotation, 0), rotateSpeed));
And the coroutine (I changed the way to calculate time a bit, I'd prefere this strict way instead of calculating global time):
IEnumerator SlerpRot(Quaternion startRot, Quaternion endRot, float slerpTime)
{
float elapsed = 0;
while(elapsed < slerpTime)
{
elapsed += Time.deltaTime;
transform.rotation = Quaternion.Slerp(startRot, endRot, elapsed / slerpTime);
yield return null;
}
}
Thanks, that seemed to fix it. To was initially assigned in the start function (the bit I pasted was only part of the entire script). I don't know if it was on my end, but I had to change the startRot to a transform and separate the Quaternion.Euler part since it would only rotate "smoothly" if I tapped the left or right arrow twice.
Update code:
if(cInput.Get$$anonymous$$eyDown("Left")){
rotation -= 90.0f;
to = Quaternion.Euler(0, rotation, 0);
StartCoroutine(SlerpRot(transform, to, rotateSpeed));
}
if(cInput.Get$$anonymous$$eyDown("Right")){
rotation += 90.0f;
to = Quaternion.Euler(0, rotation, 0);
StartCoroutine(SlerpRot(transform, to, rotateSpeed));
}
Coroutine:
IEnumerator SlerpRot(Transform startRot, Quaternion endRot, float slerpTime)
{
float elapsed = 0;
while(elapsed < slerpTime)
{
elapsed += Time.deltaTime;
transform.rotation = Quaternion.Slerp(startRot.rotation, endRot, elapsed / slerpTime);
yield return null;
}
}
Follow this Question
Related Questions
Flip over an object (smooth transition) 3 Answers
How do i determin if an objects rotation is between 2 values on each axis? 0 Answers
Cube Gravity - Apply Gravity to a Curve 0 Answers
Distribute terrain in zones 3 Answers
Player rotation issues (Player returns to default forward rotation after releasing keys) 1 Answer