I am trying to get the current pitch (rotation.x) angle of an object and using transform.eulerAngles.x works great except that it only shows a positive angle, no matter which direction I am rotating the object… so it goes 0<->360 if I pitch up and 0<->360 if I pitch down.
I need to get 0<->360 pitching up and 0<-> -360 as it pitches down… any ideas?
Generally, the only way you can tell if you have pitched up or down is to store the previous pitch angle and compare it to the current angle. However, I recommend you don’t do this using eulerAngles because you get the fiddly modulo-360 problem (which I’m sure you have already experienced). Try storing the object’s transform.forward vector at the end of each frame update. When you need to check the object’s pitch, do a cross product of the stored vector with the freshly-read forward vector. The direction of the resulting vector will tell you whether you have pitched up or down.
If you think about it, you can only rotate 360 degrees about a given axis, so it’s entirely reasonable that Transform.eulerAngles gives you a number from 0-360. If you want to translate that into pitching up or down, you can do something like:
This will give you 0-180 up and 0-(-180) down. The sign will switch when pitch reaches ±180.
If you want anything fancier like differentiating between 360 degrees in both directions, you’ll have to keep track of how someone got to a certain angle. This is because every rotation can be reached by going one way or the other, and the distinction you are making is geometrically arbitrary. In order to implement a solution, you will have to decide what happens when someone pitches past ±360 degrees.
Actually, it does look a bit nasty when I read it again. Sorry!
Does your object have a rigidbody? You could try using the x component of the angular velocity. Or you might be able to cheat, say, if your object is tracking the position of another object (ie, get the target’s y coordinate and see if it has increased or decreased).
This is a little confusing to me, not that confusing me is hard. When you say pitching, do you mean something like pitching upward from the world horzontal, or do you mean that you are rotating upward from the local object prospective. So if you were dealing with a plane, do you want to know if the plane was pointing upward, or do you want to know if the plane is doing a loop?
If the first (pointing upward) you could take the forward vector, convert to world space, and then compare that to whatever world axis you want.
If the second, that can be more tricky. Are you applying forces or modifying the rotation? If so, you can just determine the “pitch” when since you know how you are rotating or applying the force. If you are not doing the application of force/rotation, then I think you are going to have to store a prior forward and then compare. It is actually pretty straight forward. Putting the comparison code in another function will make it much easier to work with and change if you need to. Unfortunately I do not have Unity with me right now, otherwise I would try to code up an example
Find a way to keep track of how much you’ve rotated each frame/fixedFrame. Then, compare it to the initial angle.
In other words, don’t use the hard eulerangle results, make your own.
Quaternions can invert all angles at will, so the eulerangles returned by them are pretty useless to compare between each other.
Hope that makes sense. There are other threads out there about rotating and clamping how far you rotate. I’m not sure of the context of what you are trying to do though.
Not quite. In the case where pitch is greater than 180 degrees you need to subtract 360 from it. As written above you’ll only ever get values 0-180 (imagine a value of 270, using the above that will display as 90 degrees whereas it should be -90). So do this instead:
thanks all for your help. All I am wanting to do is display the pitch (up/down) angle of one of my turret barrels in Turret Wars. I am not looking at a way of clamping or controlling the pitch at all. It’s just for a GUIText for a HUD.
I was really hoping there just was an easy way to display it from -angle to +angle. Doesn’t seem to be.
I’ll look into the tracking of rotation direction to work out the +/- angle.
So, just track the amount rotated as the player changes the pitch in your own variable. Start at zero or whatever your starting angle is. Change it by the same amount you rotate. It’s your variable now, so it can be any number you want. Display your variable and forget about your problems.
You don’t find the simple math conversions simple enough? Or perhaps I’m still a bit clueless as to exactly what you’re trying to do…
// wrap the value to make sure it is never greater than 180
while (angle > 180) { angle -= 360; }
// wrap the value to make sure it is never less than -180
while (angle < -180) { angle += 360; }
// display your angle and it will always be -180 to 180!
// negative values show that you're pitched down
// positive values show that you're pitched up
You need those two while loops as you may have an angle value of 834 degrees (the same as 114 degrees) or -742 degrees (the same as -22 degrees).
Edit: and my post kind of assumes something along the line of Aaron’s, angle is your own variable that you use for display purposes only.
Higgy, I don’t follow… the angle is never lower than 0. It never gets into negative numbers, so I don’t see what your code does that helps me?
Right now I have a Quaternion rotation of a GO that I want to show just the x axis part as an angle in Degrees that shows positive and negative degrees.
It seems my only option is to track a variable myself (as Aaron suggested) which is fine, but it’s just more overhead. I know it’s not a lot, but more overhead = bad
Ahhh, see that’s where I wasn’t clear on what you’re doing. You mentioned wanting to display numbers +/- so I thought that the angle might go negative.
Yup, that’s what is likely necessary in some way. My code was to take any angle, regardless of its value, and clamp it to -180 to 180 degree range, that’s all. Sounds like you know what’s needed from here…
There’s also a specific function for calculating the angle. Following from David’s original code:
var angle = 90 - Vector3.Angle(v, Vector3.up);
This is effectively the same thing, but it’s a bit terser. Vector3.Angle is the same as Mathf.Acos(Vector3.Dot(…)), but it returns the angle in degrees in the first place.