How to make an objetc follow the rotation of its parent only in one axis?

Hi there. I’m very new at Unity, but I have a very specific question about a project I’m working on, so I’m going to explain myself.

I have an spheric racingpod like the one on Fig 1. In Unity, the seat in the middle is grouped as one and parented to the rest of the model. The overall model has attached two scripts that make it behave as a roller ball (in fact, these scripts are the ones that Standar Unity’s Rollerball has: “Ball” and “BallUserControll”), as well, my object has a Rigidbody and an Sphere Collider. On the other hand, the grouped seat only has the following script:

private float lockPos = 0;

void LateUpdate(){
transform.rotation = Quaternion.Euler (lockPos, lockPos, lockPos);
}

2976388--221230--C_01.jpg
Fig. 1. Spheric Racingpod .

With that script I have locked the rotations of the seat, so when the sphere moves and rotates, the inside won´t rotate as well. Nevertheless, this is also a problem beacuse I don´t need the seat only following the position of the sphere, but also the Y axis rotation of its parent. Otherwise, when rotating it would look like in Fig. 2.

2976388--221232--C_03.jpg
Fig. 2. Racingpod moving with all 3 rotation axis locked.

So, I did this:

private float lockPos = 0;

void LateUpdate(){
transform.rotation = Quaternion.Euler (lockPos, transform.eulerAngles.y, lockPos);
}

The problem now is that when the sphere moves forward, the seat does an automatic wierd rotation and ends up like in Fig. 3.

2976388--221231--C_02.jpg
Fig. 3. Wierd automatic rotation when moving.

My question is: how can I make the seat follow the sphere but only in its Y axis with out making that wierd automatic rotation? I also don’t know if that rotation has something to do with the aceleration or general physics of the roller ball’s script. Any help (answer, explanation, etc.) will be very appreciated.

Finally, I have to say that I used too the Mathf.Clamp class to restrict the seat’s values of rotation, but I got the same results as in Fig. 2.

private float lockPos = 0;
float MinRot=1;
float MaxRot=1;

void LateUpdate(){ transform.rotation = Quaternion.Euler (lockPos, Mathf.Clamp(transform.localEulerAngles.y, MinRot, MaxRot), lockPos);
}

Thanks, guys, and sorry if this question is too basic and the post too long. Also, apologies for any grammar mistakes, I’m not a native English speaker.

I’m not a Quaternion guru but try this code to see if it works.

void LateUpdate(){
transform.rotation = Quaternion.FromToRotation(transform.up,Vector3.Up);
}

I think that should make your seat rotate around with the sphere, but then reset it so its local up is the world up.

Reminds me of this thingy from Star Wars:

Have you considered putting both the ball and seat as children of a third object? Typically this would require movement logic to apply to the empty parent, then separate rolling logic for the ball. If rolling and movement are all done by physics, this probably won’t work right-- however, parents can also be used for organizational purposes.

I.e. you may just put the ball and seat as children to an empty object solely for the purpose of creating a prefab that includes both objects. then you can manually update the position of the seat based on that of the ball with a quick script, and the same with the y-axis for rotation.

I think that by removing space dependency you’ll find more freedom in chiseling out the behavior of the seat.

Thank you, takatok, I proved your code, when the sphere starts to move the seats moves too on X-axis, altough it follows when turning around, but after some time the seat completelly mess up. I proved by changing “up” to “right” and it kinda works, but the same happens after some time.

Ok, that might work, but can you then explain me how those updates are made?

@Ralex51

Something very simple like

public Transform ballComponent; //Assign ball to this in inspector

//..

transform.position = ballComponent.position; //Copy the position from the ball...

//Calculate xRot and zRot of the seat here, or set them to constant values

float yRot = ballComponent.eulerAngles.y;

transform.eulerAngles = new Vector3(xRot, yRot, zRot);  //Set the rotation based on calculated values

should work fine. You can adjust and add features as you go along.

2 Likes

@Hyblademin

Hi.I did as you said and use your code, the seat now does follow the Y-axis rotation of the ball as it should, but a I got a new problem. As the vehicle moves the seat will suddenly change its Y-axis rotation to 179 degrees or higher, so it looks like flipping, like in the image.

2977899--221391--Flip_01.gif

Can this be related to the eulerAngles’s calculations? How can I fix it? Thank you very much for the help.

When you access Transform.eulerAngles, Unity calculates a set of Eulers from the stored quaternion rotation. Small variations in rotation can sometimes cause Unity to calculate a set of Eulers whose components are all individually very different from, say, those that were provided in the previous frame, but whose applied rotation still puts the object in the correct orientation. For example, (0, 0, 0) is the same orientation as (180, 180, 180), and the calulated Eulers can be either (~0, ~0, ~0) or (~180, ~180, ~180) when Unity is asked for them. I bet that’s what’s happening here.

Sorry for leading you down the wrong path. When it comes to reading or setting eulerAngles in general, you should be prepared for this kind of error, especially when you are only reading or setting only one axis, and I tend to forget about this until the error shows its face.

Instead, try setting the Transform.right of the seat to that of the ball. I think you’ll find that this works better, and is easier to use anyway:

public Transform ballComponent; //Assign ball to this in inspector

//..

transform.position = ballComponent.position; //Copy the position from the ball...

transform.right = ballComponent.transform.right; //Align the red axis of the seat with that of the ball-- yaw and roll will be matched, but pitch will not change

See if this works for you.

More information: The sudden changes in the Eulers are due to the fact that orientations are not unique when using rotation by Euler components. In addition, some orientations are subject to gimbal lock. Gimbal lock is a problem with axis-driven rotation mechanisms where two or more axes align and prevent the object from being able to rotate along a specific ‘world’ axis. The problem is intuitively understood while toying with physical gimbals, and is not escaped in an abstraction of a gimbal using Euler angles. Gimbal lock can be compensated for by changing one set of Eulers to an equivalent set that is gimbal-locked on a different axis than the one where rotation is desired.

Rotations applied and represented by quaternion values do not have this problem, but they are less intuitive for us. It doesn’t take a lot of effort to understand how rotations are represented using quaternion representation, but understanding its manipulation is more complex.

2 Likes

Thank you very much, Hyblademin, it works perfectlly!

1 Like