声明:此篇文章是个人学习笔记,并非教程,所以内容可能不够严谨。可作参考,但不保证绝对正确。如果你发现我的文章有什么错误,非常欢迎指正,谢谢哦。
1 transform.rotation
transform.rotation和Inspector面板上的rotation不同, 获取的是一个四元数(Quaternion)。它的值可由Inspector面板上的欧拉角rotation转换而来的。
小实验:
//EulerRote是个Vector3,它的值等同于旋转物体Inspector面板上的rotation的值
//TargetObject是旋转物体的transform
Debug.Log("欧拉角转的四元数:" + Quaternion.Euler(EulerRotate));
Debug.Log("transform.rotation:" + TargetObject.rotation);
Debug.Log("Inspector面板上的rotation:" + EulerRotate);
Debug.Log("transform.rotation转化的欧拉角:" + TargetObject.rotation.eulerAngles);
Debug.Log("transform.EulerAngles:" + TargetObject.eulerAngles);
输出结果
从结果来看Inspector面板上的rotation就数值而言与transform.rotation转换的欧拉角是不相等的,但二者代表的旋转效果一样。
而Inspector面板上的rotation转换的四元数与transform.rotation是相等的,所以为了更好理解二者之间的关系,我将transform.rotation看作是Inspector面板上rotation转换而来或者Unity对Inpsecotr面板上的rotation采用了特别的封装。(实际上不一定)。
但是实际上真正的底层逻辑我就不得而知了。
2 transform.EulerAngles
官方API解释:https://docs.unity3d.com/ScriptReference/Transform-eulerAngles.html
我摘出了几句重要的官方解释:
When viewing the rotation of a GameObject in the Inspector, you may see different angle values from those stored in this property. >This is because the Inspector displays local rotation,
这句话的意思是Inspector面板上显示的是局部旋转(相对于父项的旋转),而 transform.EulerAngles表示的是全局旋转。但以我的理解来看,这句话不够完善。我们可以用transform.localEulerAngles来获取局部旋转,但有时候t它和Inspector面试的欧拉角rotation也是不相同的,因为同一个旋转用欧拉角表示可以有多种方式(如(-60,0,0)和(300,0,0)效果是一样的)。所以它应当补充一句:就旋转效果来说。
You can set the rotation of a Quaternion by setting this property, and you can read the Euler angle values by reading this property.
我的理解是: 如果我们给transform.EulerAngles赋值,它将会被转化为四元数,(存储到transform.rotation中)。
When you read the .eulerAngles property, Unity converts the Quaternion’s internal representation of the rotation to Euler angles. Because, there is more than one way to represent any given rotation using Euler angles, the values you read back out may be quite different from the values you assigned. This can cause confusion if you are trying to gradually increment the values to produce animation.
当我们读取EulerAngles时,获得的是由四元数转化儿来的欧拉角(应该就是transform.rotation了)。因为可以使用不同的欧拉角表达同一个旋转(如(-60,0,0)和(300,0,0)效果是一样的),所以读取到的值可能和我们设置的值不太一样,所以当我们试图不断让此值增加来生成动画时就会出现问题了。如果需要插值,尽量使用四元数。
总之transform.EulerAngles和transform.rotation在Unity内部是相互转化的。
3 transform.Rotate(参数列表)
3.1 欧拉角旋转
此函数是用来旋转的,它有一个参数要特别注意:, Space relativeTo 。这个参数是用来确定此次旋转是根据惯性坐标轴还是自身局部坐标轴旋转。
(1)如果选择的是Space.Self,会根据物体当前的局部坐标系为参考系来进行旋转。这就会导致下面两块代码的执行结果是不一样的
this.transform.Rotate(90, 60, 30);
this.transform.Rotate(90, 0, 0);
this.transform.Rotate(0, 60, 0);
this.transform.Rotate(0, 0, 30);
将上面代码放在start函数并挂在一个cube上,得到的结果:
原因:默认情况下Space relativeTo参数值为Space.Self,即以物体当前局部坐标系为参考系。每次调用Rotate函数都是基于当前的物体局部坐标系。
第一个代码块只调用了一次Rotate函数,物体将基于初始状态(欧拉角为(0,0,0))进行欧拉旋转,先绕Z轴旋转30°再绕X轴90°最后绕Y轴60°。
而第二个代码块调用了三次Rotate函数。第一次,物体先基于初始状态进行欧拉旋转,绕Z0°再绕X90°最后绕Y0°。重点来了,第二次物体将基于第一次旋转后的局部坐标系,也就是物体当前的局部坐标系进行欧拉旋转,先绕Z0°,再绕X0°最后绕Y60°。第三次同理,基于物体完成第二次旋转后的局部坐标系进行欧拉旋转。
(2)如果选择的是Space.World,则根据物体的惯性坐标系来旋转。注意是让物体基于当前的朝向来以物体惯性坐标系进行旋转,而不是让物体从初始状态(欧拉角为(0,0,0))重新从零开始旋转。
如果将上面提到的两段代码的relativeTo参数改为Space.World,执行结果依然不同。
注意:因为只有当我们在同一个固定的坐标系下反复修改欧拉角才会出现万向锁现象,但是Rotate函数每次执行都是以现在的物体局部坐标系为参考系,也就是说每次的旋转坐标系和上一次的都不一样,所以按道理不会出现万向锁。
3.2 绕轴旋转
public void Rotate(Vector3 axis, float angle, Space relativeTo = Space.Self);
绕指定的轴旋转
4 transform.RotateAround
public void RotateAround(Vector3 point, Vector3 axis, float angle);
绕指定的点和轴旋转
5 transform.LookAt
让物体指向目标位置,并且是的物体的transform.up与参数worldUp的夹角不超过90°
Transform类的更多函数请看官网API:https://docs.unity3d.com/cn/2019.4/ScriptReference/Transform.html