当前位置:   article > 正文

【Unity】常见对象旋转方法

【Unity】常见对象旋转方法

1 前言

        记录下常见的游戏对象旋转API。

2 旋转API

2.1 Transform.Rotate

        自身旋转。

public void Rotate(Vector3 eulers, Space relativeTo = Space.Self);

  • eulers:旋转角度。

  • relativeTo:坐标轴

代码:

  1. using UnityEngine;
  2. public class _Rotation : MonoBehaviour
  3. {
  4. void Update()
  5. {
  6. //以世界坐标轴,旋转y轴
  7. this.transform.Rotate(new Vector3(0, 0.1f, 0), Space.World);
  8. }
  9. }

演示:

代码:

  1. using UnityEngine;
  2. public class _Rotation : MonoBehaviour
  3. {
  4. void Update()
  5. {
  6. //以自身坐标轴,旋转y轴
  7. this.transform.Rotate(new Vector3(0, 0.1f, 0), Space.Self);
  8. }
  9. }

演示:

2.2 Transform.RotateAround

        绕某一点的某轴旋转。

public void RotateAround(Vector3 point, Vector3 axis, float angle);

  • point:旋转中心点。(绕谁旋转)

  • axis:旋转轴。(中心点的轴)

  • angle:旋转角度。

代码:

  1. using UnityEngine;
  2. public class _Rotation : MonoBehaviour
  3. {
  4. public GameObject Center;
  5. void Update()
  6. {
  7. //以自己为中心点,绕世界y轴旋转,每秒30度。
  8. //this.transform.RotateAround(this.transform.localPosition, Vector3.up, 30.0f * Time.deltaTime);
  9. //以自己为中心点,绕自身y轴旋转,每秒30度。
  10. //this.transform.RotateAround(this.transform.localPosition, this.transform.up, 30.0f * Time.deltaTime);
  11. //以Center为中心点,绕Center自身z轴旋转,每秒30度。
  12. this.transform.RotateAround(Center.transform.localPosition, Center.transform.forward, 30.0f * Time.deltaTime);
  13. }
  14. }

演示:

图中,长条矩形是Center,蓝色轴是z轴。

2.3 Quaternion.RotateTowards

        四元数计算,从某一角度转到某一角度。 ​ 使用四元数不会出现万向锁问题,具体四元数角度与Vector角度的区别可自行查询,在旋转效果上基本没什么区别。

public static Quaternion RotateTowards(Quaternion from, Quaternion to, float maxDegreesDelta);

  • from:当前角度。(四元数形式的角度)

  • to:目标角度(四元数形式的角度)

  • maxDegreesDelta:每次执行时的最大旋转角度。

代码:

  1. using UnityEngine;
  2. public class _Rotation : MonoBehaviour
  3. {
  4. //选择最终角度
  5. Quaternion qua;
  6. void Start()
  7. {
  8. //确定好旋转的最终角度,在当前坐标系y轴上加200度。然后将欧拉角转为四元数。
  9. qua = Quaternion.Euler(this.transform.localEulerAngles + new Vector3(0, 200, 0));
  10. }
  11. private void Update()
  12. {
  13. //从当前角度往目标角度旋转,每次旋转的最大值为30.0f * Time.deltaTime,基本除了最后一次旋转,前面的每次旋转都是这个值,因为最后一次到达目标角度所需要旋转的角度可能小于30.0f * Time.deltaTime。
  14. this.transform.localRotation = Quaternion.RotateTowards(this.transform.localRotation, qua, 30.0f * Time.deltaTime);
  15. }
  16. }

演示:

可以看到,箭头旋转了大概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里一直更新目标角度就行了,这就不演示了,很基础的思路。

2.4 Vector3.RotateTowards

        从某一角度转到某一角度。

public static Vector3 RotateTowards(Vector3 current, Vector3 target, float maxRadiansDelta, float maxMagnitudeDelta);

  • current:当前角度。

  • target:目标角度。

  • maxRadiansDelta:每次执行时允许旋转的最大角度。

  • maxMagnitudeDelta:此旋转所允许的矢量大小的最大变化。(希望返回的方向向量长度,最大有效值为目标方向向量(target)的长度,传0将返回单位向量长度)(前面是我看别人的解释说是长度,但我也不确定这到底是个什么)

代码:

  1. using UnityEngine;
  2. public class _Rotation : MonoBehaviour
  3. {
  4. //选择最终角度
  5. Vector3 vc;
  6. void Start()
  7. {
  8. //确定好旋转的最终角度,在当前y轴上加200度
  9. vc = this.transform.localEulerAngles + new Vector3(0, 200, 0);
  10. }
  11. private void Update()
  12. {
  13. //从当前角度往目标角度旋转,每次旋转的最大值为30.0f * Time.deltaTime,基本除了最后一次旋转,前面的每次旋转都是这个值
  14. this.transform.localEulerAngles = Vector3.RotateTowards(this.transform.localEulerAngles, vc, 30.0f * Time.deltaTime, 10);
  15. }
  16. }

演示:

跟Quaternion.RotateTowards类似,但不如其好用,而且最终角度设置不好还会造成不停胡乱旋转的情况,不好用。

        另外,在旋转前,Inspector不是以Inspector面板中的欧拉角,是以调整后在[0,360)的欧拉角旋转。比如初始y设置-5度,目标设为200度,那么在运行时实际就是从335→200的旋转,会逆时针。另外输入的角度值应在[0,360)范围内(在代码中设置为负角度的话,就会以负值输入),否则会胡乱旋转。
        总结一下就是,旋转时自身欧拉角会被定到[0,360)内,所定的最终目标角度值也应在[0,360)内(否则会胡乱旋转),然后就是从当前角度往目标角度旋转,这样以来实际就是在两个[0,360)范围内的角度之间旋转,这样一看,此API的旋转过程就比较清晰了。

3 结束语

        后续根据情况再补充,一般情况下,本文前三个旋转操作就能满足大部分需求了。Quaternion.RotateTowards是真滴好用!是真滴好用!是真滴好用!只需要给出起始四元数角度和终点四元数角度就好,完全不担心出问题,就是其只走小角度的问题有时候会影响使用,不过这种情况选Transform.Rotate就好,是最简单的方法也正因此可塑性、灵活性很强。

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/123979?site
推荐阅读
相关标签
  

闽ICP备14008679号