- Home /
Why is a child object not rotating properly with parent?
The question:
Why is a child object accepting it's parent rotations when it itself is motionless, but seeming to refuse it when rotating itself?
The setup:
Assume 3 transforms in a hierarchy. (A) is the parent of (B), (B) is the parent of (C).
(A) has a script attached to it that controls movement of the collective. It has a section inside FixedUpdate() that translates input into rotation:
//handle body yaw and tilt calculations
float yawMag = rotationSpeed * Time.deltaTime * Input.GetAxis ("BodyYaw");
//this actually rotates the main transform
transform.Rotate (Vector3.up, yawMag);
There is also a section a little later that simulates inertia and tilts the transform a bit as yaw and speed increases.
transform.localEulerAngles = new Vector3(0, transform.rotation.eulerAngles.y, balanceRotationLimitDegrees*balancerLoad);
(B) is a pivot for (C), which is the actual camera. (B) has a script with code in FixedUpdate() like this to handle and limit rotation:
float trot = Input.GetAxis("Camera Traverse") * Time.deltaTime * traverseRate;
transform.Rotate(transform.up, trot);
float angleOffBow = Quaternion.Angle(transform.parent.rotation, transform.rotation);
//Debug.Log("AoB: " + angleOffBow);
if (angleOffBow > traverseLimit) {
transform.Rotate(transform.up, -trot);
Debug.Log("Bounced off traverse limiter");
}
float erot = Input.GetAxis ("Camera Elevation") * Time.deltaTime * elevationRate;
childCamTransform.Rotate(Vector3.right, erot, Space.Self);
angleOffBow = Quaternion.Angle(childCamTransform.rotation, transform.rotation);
//Debug.Log("AoB: " + angleOffBow);
if (angleOffBow > elevationLimit) {
childCamTransform.Rotate(Vector3.right, -erot, Space.Self);
Debug.Log("Bounced off elevation limiter");
}
When running around and yawing (A), everything works as expected. The camera pivot (B) is appropriately rolled with the main body and comes back when (A) comes back to full vertical. The camera itself (C) also functions properly, yawing and elevating within its limits. When these two things combine, however, things go wrong. Rotating (B) while (A) is tilted results in some sort of permanent local Z axis rotation and (B) comes back up with its axes screwed up. I've tried a bunch of different iterations of different ways of rotating things and referring to axes, but I'm missing something fundamental here.
Any thoughts?
EDIT: Fixed it. Took the instances of
transform.Rotate(transform.up, trot);
and changed them to
transform.Rotate(Vector3.up, trot, Space.Self);
I was under the impression that these two things are essentially the same = the Vector3.up vector in self space is essentially the transform's up axis. Clearly I'm wrong here so, the question answer criteria is now "can someone tell me why/how these things aren't the same?"
Thanks!
Hi, you use multiple objects to simplify the rotations of the camera and that's usually the best way to do it. When coding this kind of script, I found it easier to manage the angles values myself and feed them through the localRotation of the object's transforms. I.$$anonymous$$ define a "private float TRot" in B class (and ERot) and setting the angles of your B object with localRotation = Quaternion.Euler(ERot, TRot, 0.0f). That way, all local angles are known and Unity will combine those rotations when computing the transform hierarchy (it's also easier to debug).
I'm not familiar with transform.Rotate but I suspect it may use the existing hierarchy to compute the rotation, using the parent's rotation in the equation. This may introduce some little rotations that accumulate. $$anonymous$$aybe if you do all the rotations in the Space.self like you do for some, it may fix it.
$$anonymous$$y understanding of transform.Rotate is that it operates entirely in Quaternion space and only local to the rotation itself, but I could definitely be wrong. I'll be messing with this while waiting for someone to show up with a "gotcha".
EDIT: fixed above. Want to take a swing?
transform.up is rotated by the object's transform but Vector3.up is not (And I've checked, the default value for the "Space" is Space.Self so this doesn't make a difference, I should have checked this in my previous comment :-)
So, transform.up will take in account the parent's rotation while Vector3.up won't (= always (0,1,0)). It explains why you had some sort of "permanent" rotation that adds up (transform.up = Vector3.up rotated by the parent's transform)
Answer by maradine · Jan 03, 2015 at 02:13 AM
Can you convert that to an answer so I can give you credit?