Difficulty with rotating child around parent axes

坚强是说给别人听的谎言 提交于 2020-01-06 15:11:26

问题


I know there's a million questions on rotating, I've tried and read many things but I can't seem to solve this particular problem.

The only way I can think to explain it properly is with some poorly drawn diagrams so here goes!

I have a parent object, and a child object (here it's represented as a die where opposite faces add up to 7), the axes in this diagram are the parents X, Y, and Z directions

Starting point:

I want the child object to have two methods that I'll call RotateZ and RotateX. RotateZ and RotateX should rotate the child dice around the parents Z and X axes in 90 degree steps.

RotateX:

RotateZ:

The code I currently have is this

void RotateZ(int value) {
    transform.rotation *= Quaternion.AngleAxis(90f * value, pivot.transform.forward);
}

void RotateX(int value) {
    transform.rotation *= Quaternion.AngleAxis(90f * value, pivot.transform.right);
}

I should note pivot is the parent object

This appears to work great if the child starts at (0, 0, 0) rotation, repeatedly calling RotateZ or RotateX with (0, 0, 0) starting point works great. This problem comes if for example I call RotateX then RotateZ.

After the initial RotateX call it will look like this, giving the child a rotation of (90, 0, 0).

Then after a RotateZ the desired result is this:

But instead I end up with this:

I'm really at a loss as to what I'm doing wrong. I have a feeling I've hit the limit of what I can do with Euler angles and I need to learn quaternions to prevent this problem. What rotation function do I need to get the desired result?


回答1:


It looks like what you need is the really awesome call

RotateAround

it's one of the most important in Unity. RotateAround doco

Don't forget RotateAround rotates around a vector - ANY vector.

Huge tip...

A ubiquitous technique in video game engineering is: you use markers" - meaning just an empty game object - which you attach to objects or to which you attach your objects.

Very often, you temporarily attach an object to a marker, so as to move it, and then remove it from the marker again.

Here's how to do it in code. Make a marker "controlRotator"...

  1. make controlRotator a child of your controlObject.

  2. make it perfectly straight locally: ie, simply exactly the same orientation as the parent, controlObject, ie, local rotation = identity

  3. next, cleverly set the WORLD position of controlObject to exactly the WORLD position of smallCube...

  4. your smallCube, make a note of it's parent. take smallCube off that parent.

  5. next, temporarily make smallCube a child of controlRotator

... and now you can ...

  1. rotate the controlRotator any way you like!

You simply rotate controlRotator, not the small cube.

Note that you are now doing exactly what you asked to do, you're rotating smallCube using the axis of the controlObject. Clever right?

  1. finally, put smallCube back on to the parent you saved in step 4.

This is exactly how you do it. In practice this is so commonplace that you'll have an extension or function to do it.

Note that it is fine to make the GameObject controlRotator on the fly as needed, and get rid of it after the twist. (It's only a mathematical abstraction.)

Further tip...

This operation should work "on" controlObject. Make a script called

TwistSomethingOnMyAxis.cs

and put that ON the CONTROLOBJECT.

It would have one call

 public void twistThisThing(Transform twistIt) {}

What you do is, when you want to twist SMALL CUBE, you actually call to the TwistSomethingOnMyAxis ON THE CONTROL OBJECT. You see? So like

TwistSomethingOnMyAxis:twistor = 
  controlObject.GetComponent<TwistSomethingOnMyAxis>();
twistor.twistThisThing( smallCube , .. 90 degrees on Y or whatever .. );

I hope that makes sense! Enjoy!



来源:https://stackoverflow.com/questions/37753519/difficulty-with-rotating-child-around-parent-axes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!