- Home /
Roll by rotating camera past 360 degrees on x axis
The idea here is simple: I need to rotate the camera to provide the effect of rolling in first person. My major concern is that I want to rotate the camera on the x axis beyond 360 degrees. I am using Quaternion.Lerp for rotating.
//Inside the update function
EndAngle = Quaternion.Euler(5, 0, 0);
StartAngle = Quaternion.Euler(25,0,0);
if (tParam < 1)
{
tParam += Time.deltaTime * lerpSpeed;
Camera.main.transform.rotation = Quaternion.Lerp(StartAngle, EndAngle, tParam);
}
if (tParam >= 1)
{
tParam = 0;
}
Here is working code I am using to rotate the camera from 25 to 5 degrees. Of course, I want to start at 5 and end at 365(5). I would however like the lerp to start at whatever the current rotation angle on the x axis is for the camera, but am wary that using StartAngle = Camera.main.transform.rotation.x will result in the StartAngle updating constantly. How should I go about taking the starting angle of the camera in an efficient manner?
tl;dr How should I make the camera rotate to 365 degrees? (And should I use slerp to make the roll more realistic?) Thanks for any help in advance :)
"but am wary that using StartAngle = Camera.main.transform.rotation.x will result in the StartAngle updating constantly." - Don't worry about that, transform.rotation
is a Quaternion
, a Quaternion
is a struct, not a class (a value-type, not a reference type) - meaning when you do startAngle = camera.main.transform.rotation;
startAngle
now is a copy of the camera's rotation (when you modify the copy, you won't affect the original)
Thanks for that quick reply! So StartAngle wouldn't keep updating with the new value? (It's in the update/ if(is rolling) condition)
What I meant to say is:
startAngle = something;
print(startAngle); // gets X
print(something); // gets y
changeToY(something);
print(startAngle); // still gets X
print(something); // gets y
If you keep changing/assigning your startAngle
in your update each frame to something new, of course it will change :)
Ok, so should I try a check to see if I have gotten the rotation.x value? Like this:
Update ()
{
if(!findRot)
{
StartAngle.x = Camera.main.transform.rotation.x;
findRot = true;
}
}
Or is there a more efficient way?
I am terribly sorry for the delay, I've been messing around with it all this time, I really suck at rotations! - But I've managed to get a smooth rolling going on for the camera using $$anonymous$$athf.$$anonymous$$oveTowardsAngle - It rotates smoothly, but for some reason for me it just keeps on rotating :D I'm sure you'll use it better than me - You mentioned the x-axis, you want to roll forward and backward? - I thought you were doing a side roll, that way you have to rotate around your cam's local z. Here's a good tut about rotations, and here's a very useful tool about rotations that you might be interested in. I am sorry I couldn't provide you with better assistance. @ArkaneX requesting backup.
Answer by robertbu · Sep 18, 2013 at 05:43 AM
As you've found out, Quaternions are lazy...they always take the shortest distance path between two rotations. This means that you cannot do a rotation of more than 180 degrees with a single setup. One solutions is to use Vector3.Lerp() and assign the results to Transform.eulerAngles. There are two issues with using this method:
Vector3.Lerp() does not handle the 360/0 boundary, so you have to change the representation of the values to something that will be incremented and decremented the way you want. So if you wanted to start at 25 and end at 5 the long way, you could specify the start as 25 and the end at 365. Or you could specify the start as -335 and the end as 5.
You must never read Transform.eulerAngles. You need to maintain your own Vector3 representation of the angle and treat Transform.eulerAngles as write-only. If you were to read back transform.eulerAngles after setting it, you often find the internal representation different than the value you just set. As long as you only set eulerAngles, the rotation will work.
Thanks for the answer, I'm going to try using Vector3.Lerp and see how it goes. I had already thought of this solution, but I didn't want to bother with converting rotations beyond 360 degrees (though I suppose it won't be too bad?).
Here's my thought. Using your method, I can lerp the rotation to 365 or so. Then, once the lerp has finished, I could set the rotation to 5 degrees (or whatever respective angle) to compensate for wrap around 360.
Changing your representing after the rotation will work just fine. You can use any representation you want and change from one representation to another and everything will work just fine. You could also pick representation that did not require you to normalize the rotation (like start at 3600 for a 0 rotation). As mentioned, the only caution is to not read eulerAngles.
It is a fair point that I can use crazy huge representations for angles, because if I don't directly modify the rotation but just add to the rotation variable (e.g. EndRot = CurRot + 360) I could continue to correctly lerp the values even if they're not normalized. The only problem would be keeping the boundaries of the rotating camera affect while running (because if I start from a low rotation the boundaries will be lowered by the amount of deviation). For that reason, I'm going to stick to normalizing the result, but thanks for the insight! (and the read warning)
Your answer
Follow this Question
Related Questions
Top down camera for object moving on sphere 1 Answer
Finding roll angle 0 Answers
Rotate player to screen pos 0 Answers
Moving FPS/TPS camera to look at a target and resuming player control 1 Answer
Rotating camera with Quaternion 2 Answers