- Home /
Why does resetTimer act counter-intuitively?
In the following code, when you press the WASD keys the object rotates in that direction. On releasing the keys the object should rotate back to its initial rotation, (which is 0,0,0).
This works, but the resetTimer variable should control the time taken to rotate back to the start position. However, the lower the value of resetTimer, the longer it takes. This seems counter-intuitive. Surely the higher the value, the longer it would take. Can anyone explain why this is the case?
The code of interest is at the bottom, I've included the whole lot so people can see what I'm trying to do.
var rotSpeed : float = 100.0;
var durationPressed : float = 0.0;
var resetTimer : float = 6;
var keyPressed : boolean = false;
var startRot : Quaternion;
//var timeVar : float = Time.deltaTime * resetTimer;
function Start ()
{
startRot = transform.rotation;
}
function Update ()
{
// w key down
if (Input.GetKey ("w"))
{
transform.Rotate(rotSpeed * Time.deltaTime, 0, 0 );
durationPressed += Time.deltaTime;
keyPressed = true;
}
// w key up
if (Input.GetKeyUp ("w"))
{
durationPressed = 0;
keyPressed = false;
}
// a key down
if (Input.GetKey ("a"))
{
transform.Rotate(0,0, rotSpeed * Time.deltaTime );
durationPressed += Time.deltaTime;
keyPressed = true;
}
// a key up
if (Input.GetKeyUp ("a"))
{
durationPressed = 0;
keyPressed = false;
}
// s key down
if (Input.GetKey ("s"))
{
transform.Rotate(-rotSpeed * Time.deltaTime, 0, 0 );
durationPressed += Time.deltaTime;
keyPressed = true;
}
// s key up
if (Input.GetKeyUp ("s"))
{
durationPressed = 0;
keyPressed = false;
}
// d key down
if (Input.GetKey ("d"))
{
transform.Rotate(0,0, -rotSpeed * Time.deltaTime );
durationPressed += Time.deltaTime;
keyPressed = true;
}
// d key up
if (Input.GetKeyUp ("d"))
{
durationPressed = 0;
keyPressed = false;
}
if (!keyPressed)
{
transform.rotation = Quaternion.Slerp(transform.rotation, startRot, Time.deltaTime * resetTimer);
}
}
Answer by hatuf · Jul 18, 2013 at 10:19 AM
The last parameter of Quaternion.Slerp is a value between 0 and 1 that's used as a multiplier for the current rotation. When it's 0 it means it's at the transform.rotation, when it's 1 it means it's reached startRot. 0.5 means it's right in the middle of those two rotations.
I recommend adding a new variable that you add the deltaTime to and then you can use that to divide it by resetTimer to get a value between 0 and 1. Also instead of using transform.rotation as the first parameter of Quaternion.Slerp, you should save the transform.rotation of when the keyPressed is set to false, now it's updated every frame to be the current rotation when it should be the original rotation.
Following your suggestion would create linear interpolation (Just saying he might actually want the effect he gets now)
The formula for Lerp(start, end, t)
is:
start + (end - start)*t
That should explain everything ;)
Thanks for the responses, I think I understand a bit better now.
To clarify (and make sure I have it right), the last parameter of the Quaternion.Slerp is expressed as a decimal fraction, (0 - 1) so the lower my resetTimer, the smaller the increment each frame and the longer the animation takes to complete.
I think I've accidentally achieved the result I was looking for, but it's very clear my code isn't very elegant.
Could someone post an example of getting the transform.rotation if a condition is met, then use it to animate the rotation back to 0,0,0, using a timer variable expressed in milliseconds/frames?
I've tried to modify my code to achieve the above, but the closest result I've achieved so far is the code already posted. Even just some pseudo-code would be great, then I can puzzle it out for myself.
Thanks again for the help.
@Spider_newgent If you're looking for a way to represent the amount of time it will take, while still having the same effect as you have now (starts fast and ends up slow), I can tell you it's impossible. The time it actually takes to get to your destination is infinite (with your current solution), so even some maths will not allow you to get the time (or set the time), it takes to move to your destination, since you never actually reach it.
If you want to do it completely linearly (or spherically) @hatuf already have a solution :)
You can always do something called a tween or easing where you manipulate the 0 - 1 value. I think in the asset store there's a free package called iTween that you could play around with.
Answer by Spider_newgent · Jul 19, 2013 at 11:17 AM
As I said in my above post, "I appreciate the pseudo-code above wont work, it's just illustrative of the kind of effect I'm trying to achieve." I presume you could infer what I was trying to achieve?
I merely highlighted that what I'd consider a relatively straightforward concept (On condition, change the rotation over time until it equals x), isn't actually as straightforward as I thought.
You seem a bit abrasive. It's clear to anyone reading that my question is basic, and that I'm trying to learn the syntax and concepts of a new language.
Rather than questioning my ability to understand, perhaps you could have suggested an alternative method to achieve the same goal, or explained how "calling" invalidates my example.
Anyway, thanks for taking the time to reply.
The problem is not an inability to understand the language. That main consept, what you were doing with the rotation does not work. Unless you want to learn how Quaternions work, I would suggest using the inbuilt Lerp function (as you have already done)
The reason it's not streight forward, is exactly that Unity (like any game engine) uses quaternions to represent rotation in 3d space. Even in 2d space rotation is way more complicated than translation. "LerpAngle" (Vector3) or "Lerp" (QUaternion) take care of all that complicated stuff.
On that note, if you wanted resetTimer
to be more "intuative" you could divide deltaTime
by it, ins$$anonymous$$d of multiplying it. Unless you are actually using timers, resetTimer
will never truely represent the amount of time it takes, but at least a bigger value will make it take more time ;)
Lastly, please do not post comments as answers :)
Your answer
Follow this Question
Related Questions
Get slerp to work just as LookAt(,Vector3.right) does 1 Answer
Rigidbody spins out of control when colliding into corner 0 Answers
Quaternion.Slerp rotation speed increases over script life. 1 Answer
How to get Angle float of specific axis.(Turret clamping related). 2 Answers
Defining specific controls for rotation. 0 Answers