赞
踩
记录下常见的游戏对象旋转API。
自身旋转。
public void Rotate(Vector3 eulers, Space relativeTo = Space.Self);
eulers:旋转角度。
relativeTo:坐标轴。
代码:
- using UnityEngine;
-
- public class _Rotation : MonoBehaviour
- {
- void Update()
- {
- //以世界坐标轴,旋转y轴
- this.transform.Rotate(new Vector3(0, 0.1f, 0), Space.World);
- }
- }
演示:
代码:
- using UnityEngine;
-
- public class _Rotation : MonoBehaviour
- {
- void Update()
- {
- //以自身坐标轴,旋转y轴
- this.transform.Rotate(new Vector3(0, 0.1f, 0), Space.Self);
- }
- }
演示:
绕某一点的某轴旋转。
public void RotateAround(Vector3 point, Vector3 axis, float angle);
point:旋转中心点。(绕谁旋转)
axis:旋转轴。(中心点的轴)
angle:旋转角度。
代码:
- using UnityEngine;
-
- public class _Rotation : MonoBehaviour
- {
- public GameObject Center;
- void Update()
- {
- //以自己为中心点,绕世界y轴旋转,每秒30度。
- //this.transform.RotateAround(this.transform.localPosition, Vector3.up, 30.0f * Time.deltaTime);
- //以自己为中心点,绕自身y轴旋转,每秒30度。
- //this.transform.RotateAround(this.transform.localPosition, this.transform.up, 30.0f * Time.deltaTime);
-
- //以Center为中心点,绕Center自身z轴旋转,每秒30度。
- this.transform.RotateAround(Center.transform.localPosition, Center.transform.forward, 30.0f * Time.deltaTime);
- }
- }
演示:
图中,长条矩形是Center,蓝色轴是z轴。
四元数计算,从某一角度转到某一角度。 使用四元数不会出现万向锁问题,具体四元数角度与Vector角度的区别可自行查询,在旋转效果上基本没什么区别。
public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);
from:当前角度。(四元数形式的角度)
to:目标角度(四元数形式的角度)
maxDegreesDelta:每次执行时的最大旋转角度。
代码:
- using UnityEngine;
-
- public class _Rotation : MonoBehaviour
- {
- //选择最终角度
- Quaternion qua;
-
- void Start()
- {
- //确定好旋转的最终角度,在当前坐标系y轴上加200度。然后将欧拉角转为四元数。
- qua = Quaternion.Euler(this.transform.localEulerAngles + new Vector3(0, 200, 0));
- }
-
- private void Update()
- {
- //从当前角度往目标角度旋转,每次旋转的最大值为30.0f * Time.deltaTime,基本除了最后一次旋转,前面的每次旋转都是这个值,因为最后一次到达目标角度所需要旋转的角度可能小于30.0f * Time.deltaTime。
- this.transform.localRotation = Quaternion.RotateTowards(this.transform.localRotation, qua, 30.0f * Time.deltaTime);
- }
- }
演示:
可以看到,箭头旋转了大概200度。
但同时我们也发现了一个问题,在定最终位置时设置的是y轴加200度,那这里应该是顺时针旋转呀,怎么是逆时针呢?这是因为此函数在旋转时,每次都会走最小角度,这一点很重要,在实际应用时是会影响到功能开发的。有个特例:那么180度和-180度怎么旋转,答案是:180逆时针,-180度顺时针,哎就是反着玩。
还有我们对对象的transform中的旋转x、y、z进行修改,实际旋转是绕坐标轴的x、y、z,而不是对象本身的x、y、z。Inspector面板里Transform中的信息显示的是局部信息,我们可以尝试手动修改,就会发现其是绕局部坐标轴的三轴旋转。代码里我是都是用的local角度,所以这里是绕自身所在局部坐标系三轴旋转。当然,案例中目前箭头模型没有父级,所以其局部坐标系就是世界坐标系。我们可以看到箭头是以世界坐标系的y轴旋转的,这是因为目前世界坐标系就是我们的局部坐标系。在代码中我们增加了y值,所以是以局部坐标系(这里就是世界)的y轴旋转了200度来定最终角度的,结果就是图中是以世界坐标轴的y轴来旋转的。
额,还有一点,绕最小角度旋转到目标角度,在Inspector面板中,x、y、z的变化是按实际旋转来变化。比如我们初始Rotation y是0,然后代码里加200来旋转,是不是应该旋转到200?错,因为我们走最小角度,所以逆时针旋转,然后角度就从0变化到-160度,-160和200度位置相同,差一圈。但实际上,Inspector面板中Transform组件里的Rotation显示的不是真正的欧拉角,我们在Inspector面板上设置的Rotation的欧拉角值在运行后debug出来的都是在[0,360)内,Unity会调整它。这里的-160就不是欧拉角真正的值,输出的话会发现是200度,角度变化过程是从一个接近360的角度→200。局部、世界欧拉角都是如此。但需要知道的是,本身这个旋转函数Quaternion.RotateTowards是使用四元数旋转的,四元素角度是区分正负的。
PS:另外也可以实现箭头的无限旋转,在Update里一直更新目标角度就行了,这就不演示了,很基础的思路。
从某一角度转到某一角度。
public static Vector3 RotateTowards(Vector3 current, Vector3 target, float maxRadiansDelta, float maxMagnitudeDelta);
current:当前角度。
target:目标角度。
maxRadiansDelta:每次执行时允许旋转的最大角度。
maxMagnitudeDelta:此旋转所允许的矢量大小的最大变化。(希望返回的方向向量长度,最大有效值为目标方向向量(target)的长度,传0将返回单位向量长度)(前面是我看别人的解释说是长度,但我也不确定这到底是个什么)
代码:
- using UnityEngine;
-
- public class _Rotation : MonoBehaviour
- {
- //选择最终角度
- Vector3 vc;
-
- void Start()
- {
- //确定好旋转的最终角度,在当前y轴上加200度
- vc = this.transform.localEulerAngles + new Vector3(0, 200, 0);
- }
-
- private void Update()
- {
- //从当前角度往目标角度旋转,每次旋转的最大值为30.0f * Time.deltaTime,基本除了最后一次旋转,前面的每次旋转都是这个值
- this.transform.localEulerAngles = Vector3.RotateTowards(this.transform.localEulerAngles, vc, 30.0f * Time.deltaTime, 10);
- }
- }
演示:
跟Quaternion.RotateTowards类似,但不如其好用,而且最终角度设置不好还会造成不停胡乱旋转的情况,不好用。
另外,在旋转前,Inspector不是以Inspector面板中的欧拉角,是以调整后在[0,360)的欧拉角旋转。比如初始y设置-5度,目标设为200度,那么在运行时实际就是从335→200的旋转,会逆时针。另外输入的角度值应在[0,360)范围内(在代码中设置为负角度的话,就会以负值输入),否则会胡乱旋转。
总结一下就是,旋转时自身欧拉角会被定到[0,360)内,所定的最终目标角度值也应在[0,360)内(否则会胡乱旋转),然后就是从当前角度往目标角度旋转,这样以来实际就是在两个[0,360)范围内的角度之间旋转,这样一看,此API的旋转过程就比较清晰了。
后续根据情况再补充,一般情况下,本文前三个旋转操作就能满足大部分需求了。Quaternion.RotateTowards是真滴好用!是真滴好用!是真滴好用!只需要给出起始四元数角度和终点四元数角度就好,完全不担心出问题,就是其只走小角度的问题有时候会影响使用,不过这种情况选Transform.Rotate就好,是最简单的方法也正因此可塑性、灵活性很强。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。