- Home /
EulerAngles conversion Quaternion problem
Hello,
I want to tilt the body of a vehicle in order to simulate a (cheap but still) suspension.
Here is my code:
float tilt = (Input.GetAxis("Horizontal") * 3.0f); // Rotate the body by -3/3 degree
Vector3 targetRot = new Vector3(270 + tilt, body.transform.eulerAngles.y, body.transform.eulerAngles.z);
Quaternion targetRotation = Quaternion.Euler(targetRot);
body.transform.rotation = Quaternion.Slerp(body.transform.rotation, targetRotation, Time.time * 0.1f);
I'm tilting on the X axis because it corresponds to the body's forward.
My problem is the vehicle doesn't rotate correctly. It should go from 267 to 273 degrees depending on the Input. But it never goes below 270.
I found that the issue comes after "Quaternion.Euler". It always return an EulerAngle between 270 and 273.
Did I forget something ? How could I fix this ?
Thank you in advance !
There is more than one set of euler angles that can represent the same rotation.
Anyway your use of Quaternion.Slerp is wrong: Time.time*0.1f will always return a value > 1 after 10s.
Finally, note than an angle of 270 (= -90) is a bit strange. Why do you need to rotate your object that much?
The imported model was a vehicle laying on the ground. I had to rotate it -90° in order to get it on its wheels.
Quaternion.Slerp does not clamp from 0 to 1 the speed value. $$anonymous$$aybe you are talking about $$anonymous$$athf.Lerp ?
Answer by aldonaletto · Sep 11, 2012 at 12:44 PM
As @Kryptos said, there are several Euler angles combinations that result in the same rotation. This may become a big problem when you try to modify one of the Euler angles: Unity may return a completely different combination when one of the other angles crosses some "magical" boundary (changes signal, crosses 180 degrees etc.), and the resulting rotation suddenly becomes completely wrong.
The easiest way to tilt an object independently of its current orientation is to make it a child of the main object and modify its localEulerAngles:
Car hierarchy:
Car <- main object, which moves and turns Body <- empty game object that will be tilted forth and back BodyModel <- actual body model
Body script:
public float speed = 5.0f; void Update(){ Vector3 tilt = new Vector3(Input.GetAxis("Horizontal") * 3.0f, 0, 0); transform.localEulerAngles = Vector3.Lerp(transform.localEulerAngles, tilt, speed * Time.deltaTime); }
The speed variable controls the tilting time: 5 means that the object will take about 1 second to reach 95% of the desired rotation, 10 means half second, and so on (0.1f would take 50 seconds! that's why the body didn't even move!). Input.GetAxis has its own smoothing time, which will add to the Lerp effect, thus you may have to use higher speed values.
NOTE: Notice that an extra parenting level was added: the Body empty object is sandwiched between the Car and the BodyModel. From your code, it seems that the model have flipped axes (a common problem when importing models), thus it must be rotated to (270,0,0) to be properly orientated. The Body empty object works as an interface between the model and the car: it can have localEulerAngles = (0,0,0) while allowing complete freedom to orient the model. You can eliminate this intermediate object, if you want: child the model directly to the Car, attach the script to the model and change the base X angle to 270, as you did in your code.
Thank you very munch for the hint and explanations.
I will try this, but for the moment I found that only flipping the body by 2 ins$$anonymous$$d of 3 degrees won't made the rotation to act anormally (due to the multiple combination you mentionned).
Again, thank you, both of you :)
Double check all possible car movements, since turning left or right when the vehicle is climbing a ramp may trigger the problem.
O$$anonymous$$G IT WOR$$anonymous$$S!!
Thank you so much!!
Answer by Kryptos · Sep 11, 2012 at 11:15 AM
Since you are only changing the x-value (roll) of the euler angles why do you use quaternions?
float tilt = (Input.GetAxis("Horizontal") * 3.0f); // Rotate the body by -3/3 degree
Vector3 eulerAngles = body.transform.eulerAngles;
eulerAngles.x = Mathf.LerpAngle(eulerAngles.x, 270+tilt, Time.deltaTime*0.1f);
body.transform.eulerAngles = eulerAngles;
Depending on the situation, you may need to use localEulerAngles instead of eulerAngles.
I already tryied this way, but there are two problems.
1) The body is not moving at all (it might be the last parameter of the lerpangle function. I don't know how to tweak it. When it is too low, the body does not move and when it's too high the movement is not smooth..)
2) When I turn left (and it happens only on left) my car is vibrating again and again. Like a continue shaking effect