- Home /
Why am I getting such strange rotation values when using Quaternion.Euler?
I am trying to rotate the top section of a tank model (parented to the base of the tank) towards a target (the player), and then similarly rotate the cannon (parented to the top section of the tank) up and down to target the player. The top section of the tank rotates like it should, but I'm getting strange results for the cannon. Here's the code... Please help!
// Top section of the tank
Vector3 direction = _targetTransform.position - TopTransform.position;
float y = Mathf.Atan2(-direction.z, direction.x) * Mathf.Rad2Deg - 90.0f;
Quaternion topRotation = Quaternion.Euler(0.0f, y, 0.0f);
TopTransform.rotation = topRotation;
// Cannon
direction = _targetTransform.position - CannonTransform.position;
float x = Mathf.Atan2(direction.y, direction.z) * Mathf.Rad2Deg;
CannonTransform.rotation = Quaternion.Euler(x, y, 0.0f);
Answer by Owen-Reynolds · Jul 21, 2013 at 09:24 PM
The math (2nd last last line) appears to be incorrect. If you assume the cannon is y-rotated towards the target, you're solving the triangle: elevation / distance-along-ground. Distance along ground is local z, but you only have world. Instead of direction.z
should have flat distance: sqrt(x^2 + z^2.)
I'm guessing the code now works, or at least makes more sense, if you are pointed North (where local z is global z.)
Also, Unity thinks x-rotation is a forwards roll (+45 aims down, not up,) so may need *-1
in there.
Then, sometimes easier to set Cannon.localRotation=Q.E(x,0,0)
(your code has the barrel repeat the turret spin, which should work since Unity does y,x,z, but might be confusing.)
Thank you so much! Here is my working code for anyone with a similar problem...
private void AimAtTarget()
{
// Top section of the tank
Vector3 direction = _targetTransform.position - TopTransform.position;
float y = $$anonymous$$athf.Atan2(-direction.z, direction.x) * $$anonymous$$athf.Rad2Deg - 90.0f;
Quaternion topRotation = Quaternion.Euler(0.0f, y, 0.0f);
float t = _top$$anonymous$$oveSpeed * Time.deltaTime;
TopTransform.rotation = Quaternion.Slerp(TopTransform.rotation, topRotation, t);
// Cannon
direction = _targetTransform.position - CannonTransform.position;
float x = $$anonymous$$athf.Atan2(direction.y, $$anonymous$$athf.Sqrt(direction.x * direction.x + direction.z * direction.z)) * $$anonymous$$athf.Rad2Deg;
t = _cannon$$anonymous$$oveSpeed * Time.deltaTime;
Quaternion cannonRotation = Quaternion.Euler(x - CANNON_X_OFFSET, 0.0f, 0.0f);
CannonTransform.localRotation = Quaternion.Slerp(CannonTransform.localRotation, cannonRotation, t);
}
I didn't need to negate the X (don't know why). For anyone wondering about CANNON_X_OFFSET, my tank model had the barrel angled up a few degrees. Thanks again Owen!