- Home /
Always stay upright and follow parent's y and z rotation
How do I force a child object to always stay upright and follow the parent's y and z rotation?
I've created an object that resembles to this:
I'm using rigidbody on the parent with two child objects containing wheel collider in each. I was able to move it and turn. All okay, but I just wanted the main body to stay up-right. When moving and hitting rocks on ground, I need the whole object to freely rotate in any direction as it is driven by physics. When the object is flipped upside down, the main body is to rotate back to its upright position. I added this to the parent:
void Update()
{
transform.Rotate(new Vector3(0.5f, 0, 0));
}
I added this on a child:
void Update()
{
transform.LookAt(Vector3.up);
}
But that causes the child to always face up and cannot rotate in x and z axis when the parent rotates in all axis.
To ensure the child follows the parent's y and z axis, I tried this:
void Update()
{
transform.LookAt(Vector3.up);
transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, 0, 0);
}
When you start the game, the child rotates, but wait until the parent finishes its revolution, then the child will remain facing upright. Another full revolution of parent, the child then rotates.
I've included an unity package file to demonstrate what I'm trying to do.
How do I force a child object to always stay upright and follow the parent's y and z rotation?
EDIT: After reading Eno Khaon's answer, I realize that the attached demo I provided was not clear. I've updated the file to explain the demo better.
Answer by Cow-Necromancer · May 03, 2015 at 07:42 AM
under the rigid body, lock the rotation
I need the whole object to freely rotate in any direction as it is driven by physics. Let's suppose I threw a grenade at it. Boom. If I had the rigidbody freeze rotation in any axis, the object wouldn't move in a natural motion while flying off the ground from an explosion. I want it to be able to flip upside down. Once it is upside down, the main body would also be upside down.
Freezing the rotation does not rotate the main body back to its upright position and is not the solution I am looking for.
Answer by Eno-Khaon · May 03, 2015 at 09:46 AM
Maybe I'm looking at this the wrong way, but it sounds like you should try applying torque.
Using AddTorque on the parent should give you a means of flipping back upright if flipped over, then you can scale the strength of the torque applied relative to the dot product of its transform.up and the global Vector3.up values.
I've used motorTorque to move and rotate the wheels. Works good. The physics isn't an issue and flipping isn't either. The two-wheel object should flip in any direction and do not require flipping back.
$$anonymous$$y original question is how do I force a child object to always stay upright and follow the parent's y and z rotation? Take a look at the attached file in the original post to see what my problem is.
Ahh, sorry, guess I jumped the gun a little bit there.
The problem here is Gimbal Lock, as seen during your rotation. The parent object rotates from 0 to 90 degrees on the X axis. At 90 degrees, the rotation doesn't change, but the interpretation of that rotation changes from (90, 0, 0) to (90, 180, 180). Same rotation, different notation.
When this occurs, the continuation of that rotation decrements the X axis value while the object itself rotates the same direction.
$$anonymous$$eanwhile, your cube is perfor$$anonymous$$g a LookAt(Vector3.up). Up and Down are THE most ambiguous directions you can use for LookAt, for the reason the overloaded function may suggest. The complete version would be transform.LookAt(Position, UpDirection).
Because you're looking straight up, there's no specific direction to treat as an appropriate "up" for the cube's own "up" direction. $$anonymous$$ore than that, however, there's a secondary flaw here. LookAt is the wrong choice for this. This causes the cube in the middle to look at the vector (0, 1, 0), rather than to look in a given direction.
Counteracting rotation through Euler Angles while dealing with Gimbal Lock is no simple task. On way to handle it would be to use Quaternion rotations ins$$anonymous$$d, but there's a much simpler approach you could consider: What I would recommend doing is adding an additional Empty gameObject as a separate parent to handle spinning the wheels. Your heirarchy would look like this:
ParentObject
-Cube
-WheelSpinner(SpinForever script)
--LeftWheel
--RightWheel
With that, your center object should remain upright and the wheels spin, then any further interactions could be handled by the root ParentObject with no negative repercussions.
Thank you for the detailed answer. You're right that I'm experiencing a gimbal lock. I've tried your setup and realized that I did not give a good example of what I was trying to accomplish. I used SpinForever script as an example of a physics rotating the parent. That has been removed and I've updated a better demo file in the first post. I need the rigidbody to be in the parent game object in order to move all children.
$$anonymous$$oreover, I'm experiencing a new problem similar to the 1st post. As the parent rotate, the wheel colliders' contact point is no longer facing downward as it should. I've tried freezing the X and Z rotation, but that would cause unnatural motion when getting hit by an explosion.
Perhaps I'm going about this all wrong?
Wheel colliders only function when landing on their "bottom" side. In the scene view, the gizmo representing that is a small circle beneath the wheel collider.
Because the assumption is that the vehicle itself would be unable to drive while upside down, this is normally not a significant problem. However, in this case, there are potentially infinite exact orientations (or, with the X axis locked, two I suppose) possible.
I think it would be prudent to make a script to rotate the wheel colliders to always have their downward direction face down relative to the wheels. In other words, have them rotate only on their X-axis, to match the wheels' look, but still face down correctly.
Yes, that's related to my original question: How do I force a child object to always stay upright and follow the parent's y and z rotation? The same goes for the two wheel colliders, how do I force the wheel colliders to always face downward and follow parent's y and z rotation?
Am I going to always have Gimbal Lock problem and should abandon all hope?