【Unity】常见对象旋转方法

1 前言

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

2 旋转API

2.1 Transform.Rotate

        自身旋转。

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);
    }
}

演示:

2.2 Transform.RotateAround

        绕某一点的某轴旋转。

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轴。

2.3 Quaternion.RotateTowards

        四元数计算,从某一角度转到某一角度。 ​ 使用四元数不会出现万向锁问题,具体四元数角度与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里一直更新目标角度就行了,这就不演示了,很基础的思路。

2.4 Vector3.RotateTowards

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

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的旋转过程就比较清晰了。

2.5 Quaternion.AngleAxis

创建一个绕指定轴旋转指定角度的四元数。

public static Quaternion AngleAxis(float angle, Vector3 axis);

  • angle:旋转角度。

  • axis:轴。

代码:

using UnityEngine;

public class _Rotation : MonoBehaviour
{
    //角度
    private float angle = 30f;
    //轴
    private Vector3 axis = Vector3.right;

    private void Update()
    {
        //计算旋转四元数(参数含义:每秒旋转30度,绕x轴)
        Quaternion rot = Quaternion.AngleAxis(angle * Time.deltaTime, axis);

        //旋转
        this.transform.rotation *= rot;//与旋转四元数相乘后再赋值
    }
}

演示:

可以看到其绕着x轴进行旋转。需要注意,角度值是区分正负的,正值顺时针,负值逆时针。

3 结束语

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

  • 26
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值