- Home /
Unity Quaternion Problem (Should be A Bug?)
Hi, i recently has a big problem. i searching from any forums and QA but didn't find any luck.
so my problem is i want to move (and rotate) object by adding value on every Update()
call, this is similar like to call Vector3.Lerp()
and Quaternion.Lerp()
. And this is my code :
void Update(){
if (doTim > 0 && Time.deltaTime > 0) {
doTim -= Time.deltaTime;
if (doTim != 0) {
if (doPos)
Behaviors [behaviorCycle].objTarget.localPosition += doPosTo / (doTimTotal / Time.deltaTime);
if (doRot)
Behaviors [behaviorCycle].objTarget.localRotation *= Quaternion.Euler (doRotTo / (doTimTotal / Time.deltaTime));
if (doTim < 0) {
if (doPos)
Behaviors [behaviorCycle].objTarget.localPosition += doTim * (doPosTo / doTimTotal);
if (doRot)
Behaviors [behaviorCycle].objTarget.localRotation *= Quaternion.Euler (doTim * doRotTo / doTimTotal);
}
}
}
}
the localPosition
changes on this Update
call are WORKED correctly, but for the localRotation
, it rotation will ended with very strange value.
if I rotate it by only one Axis (say, from (0,0,0)
to (0,90,0)
) it will rotating correctly, but if I rotate it using two or more Axis (say, from (0,0,0)
to (90,90,0)
) it will returning very strange value.
so, What should I do? is there something I missed? I have trying to using Transform.Rotate()
but it did the same things.
PS : I won't use Lerp()
function because the object are controlled by more than one script in my game.
Answer by Pangamini · Mar 03, 2015 at 01:30 PM
The problem is that you are doing interpolation with quaternions, but calculate the delta for your rotation from euler angles. If you were interpolating over euler angles (as a vector), the result would be different than quaternion slerp.
If you want to inrerpolate rotation smoothly towards some target, i suggest you:
Calculate angle between current and destination target rotation, i think it's angDist = Quaternion.Angle or something like that. The result is float
Calculate how much you want to rotate in this frame: angDiff = rotSpeed * deltaTime
Calculate the ratio of the total angle vs what you want to move, and feed that to slerp (not lerp, never lerp for quaternions that represent rotations). That would be: ratio = angDiff / angDist
Last, you can do the Slerp correctly (as it's meant to be, i never understand people who use deltaTime as lerp/slerp factor!!): newRotation = Quaternion.Slerp(oldRotation, targetRotation, ratio )
indeed! even i didn't use all of your solution, but using Slerp()
function is a great idea. my final code :
void Update ()
{
if (doTim > 0 && Time.deltaTime > 0) {
doTim -= Time.deltaTime;
if (doTim != 0) {
if (doPos)
Behaviors [behaviorCycle].objTarget.localPosition += doPosTo / (doTimTotal / Time.deltaTime);
if (doRot)
Behaviors [behaviorCycle].objTarget.localRotation *= Quaternion.Slerp (Quaternion.identity, doRotTo, Time.deltaTime / doTimTotal);
if (doTim < 0) {
if (doPos)
Behaviors [behaviorCycle].objTarget.localPosition += doTim * (doPosTo / doTimTotal);
if (doRot)
Behaviors [behaviorCycle].objTarget.localRotation *= Quaternion.Inverse( Quaternion.Slerp (Quaternion.identity, doRotTo, -doTim / doTimTotal));
}
}
}
}
thanks for the great answer!
Your answer
Follow this Question
Related Questions
How to ROTATE an object without slowing the ends (lerp) 3 Answers
How to smoothly rotate to certain directions using input axis 1 Answer
Need to check transform.rotation 1 Answer
How do you smoothly transition/Lerp into a new rotation? 3 Answers
How can I multiply the rotation of a mirrored object? 1 Answer