在Unity中实现最常用的几种旋转

Unity中的旋转相对于位移和缩放要复杂很多,究其原因是因为旋转不能简单地用Vector3类型的变量表示,想要深刻理解Unity中的旋转需要学习欧拉角,四元数等非常复杂的数学知识,但我们今天从实用的角度出发,只学习如何实现常用的旋转方式,并灵活的应用到自己的游戏里面即可。 

目录

一、自转

二、公转

三、环形排列

四、改变朝向


        在认识旋转之前我们需要知道一个Unity常识,即Unity的三条轴,forward,up和right,分别对应世界坐标系种的z,y,x我们一般有两种途径可以调用这三个变量,第一种是通过Vector3来调用,此时我们获得的是世界坐标系的三条轴,第二种则是通过transform来调用,此时我们获得的是对应物体自身的,两种轴默认情况下的指向是一致的,我们下面所有的旋转都需要找到一条合适的轴才行。

一、自转

首先我们要实现的是自转,即物体绕自身的某一个轴旋转。
要实现自转很简单,我们只需要一个函数

transform.Rotate(transform.forward, 自转速度 * Time.deltaTime);
该函数有两个参数,第一个参数用来指定要绕的轴,另一个则是旋转的速度,这里我们运行该代码就可以看到物体正在绕Z轴旋转,但有一个前提,即物体的初始旋转值必须是(0,0,0),此时物体才会绕它的z轴做旋转,,如果初始时刻物体就已经有一个旋转的的话,物体就不是绕其Z轴旋转了,而是做一个非常扭曲的旋转,具体原因,在我查阅相关资料之后了解到大概是由于欧拉角计算比较特殊,具体的原理我们就不去深究了,只需要记住这里有一个小坑即可。

二、公转

其次我们要实现的是公转,即绕物体外的某一点旋转,和自转类似,Unity也为我们提供了很方便的函数接口。

transform.RotateAround(圆心.position,Vector3.forward,公转速度* Time.deltaTime);

参数依次是,公转的圆点,旋转的轴,以及公转的速度,
值得注意的是,这里的轴要用Vector3获取世界坐标的轴,如果用transform获取轴就可能出现奇奇怪怪的情况了。

以上是最基础的两种旋转,我们后面涉及到的所有更加复杂的旋转都是以他们为基础的,但相信大家已经发现一个问题了,就是上面两个函数都是指定物体绕某轴旋转多少度,但当我们想让物体的某个面转向某个向量时上面的两个函数就不太方便了,上面两个我个人常用来制作场景中某些不间断旋转的物体,比如说那种广告小游戏(鸠摩智转刀)里面那种身边总有几把刀绕自己旋转的功能。

三、环形排列

假设我们现在有这样一个需求,场景中有一个中心点A,我们需要在以A为圆心,半径为R的圆上,等距的创建n个物体,此时你会如何用代码实现呢?

这里需要用到一点点高中的知识,当我们知道原点坐标,半径和物体相对于某一条轴的角度时我们就可以利用三角函数轻易的求出物体的坐标(高中的时候应该经常用吧QWQ)知道这一点代码写起来很容易了。

 for(int i=0;i<count;i++)
 {
     float angel = 360f / count * i * Mathf.PI / 180;
     float x = Mathf.Sin(angel) * radius;
     float z = Mathf.Cos(angel) * radius;
     Vector3 pos = new Vector3(x, 0, z) + transform.position;//加上的这个position是圆心的坐标
     GameObject obj = Instantiate(cube);
     obj.transform.position = pos;
}

但这里还有两个小问题需要大家注意。

第一个是我这里得到的坐标分别赋给了x与z而非x与y,这是因为,我的物体形成的圆是处于x-z这个平面上的,假设你想要你物体绕成的那个圆在x-y平面上那这里就需要分别赋值给x,y

第二个问题则是我这里X是用的正弦值,而Z用的是余弦值,但如果有些同学不小心将让X用余弦值,让Z用正弦值,会发现同样能够达到我们的目的,两者最终的结果是一样的,那二者的区别在哪里呢?我们可以通过只生成一半来观察一下结果。

我们发现两次生成分别在上半圆和左半圆,说明哪个用正弦哪个用余弦会影响整个圆从哪个方向开始形成。

按照这个道理我们可以从二维扩展到三维,绕以某点为圆心的球体生成游戏物体,但考虑到这个文章是用来帮大家入门的,这个功能就留给大家自行思考如何实现了。

四、改变朝向

实现绕某一中心点圆形排列后,如果你使用的是游戏物体不是球体那你就该发现一个问题了,没错所有的游戏物体朝向都是一样的,但我们往往想要的是让他们都朝向圆心。

要实现这个功能我们有很多种途径,这里我介绍几种方法,希望大家可以通过不同的方法进一步理解unity中的旋转。
 

首先最简单粗暴的:调用LookAt
LookAt最常见的解释就是让物体朝向目标,准确来说就是让物体旋转保证物体的forward方向(也就是物体的Z轴)指向目标。
(当然,你可以利用LookAt的一个重载,不让物体的Z轴而是其它的某一个轴朝向目标,但涉及的问题有一点复杂,这里就不赘述了)

所如果我们在2D游戏中使用了LookAt函数很可能会出现物体直接消失不见的情况,这是因为在2D游戏中,Z轴是表示深度,即从屏幕指向玩家的方向,如果让这条轴指向物体,那我们就只能看到物体的一条边进而给人的感觉就像消失了一样。

其次与第一种方法类似,但是使用四元数。

Quaternion lookDir = Quaternion.LookRotation(transform.position - obj.transform.position);
obj.transform.rotation = lookDir;

由于该方法涉及到四元数这个非常复杂晦涩的数学知识,我们这里就不研究原理了,只探讨怎么用。

首先我们创建了一个四元数lookDir 并让它获取到了Quaternion.LookRotation()的返回值
而Quaternion.LookRotation的参数我们传入的是由物体指向圆心的一个方向向量,这个方向正是我们希望物体朝向的方向。
最后我们把获取的四元数赋值给物体的rotation物体就能成功的朝向圆心,如果此时我们画出物体的forward方向可以发现forward方向也指向圆心。
 

综上述我们不难推出该方法的用法,假设我们希望物体的forword指向一个dir,我们可以通过Quaternion.LookRotation将Vector3的dir转换为对应的四元数,我们再把这个四元数赋值给物体的rotation时,物体的forward方向就能对齐dir方向,这种方法与LookAt非常相似。

第三种方法,利用Rotate函数的一个重载。
我们假设物体从圆心上方开始顺时针生成,且第一个物体的forward对向圆心,我们简单作图之后就可以看出来物体只需要顺时针旋转自身相对于生成轴的角度即可。
(需要注意的是我这里是从圆心的上方开始生成,即X对应Sin,Z对应Cos,如果是从圆心的右方开始生成我们还需要加一个偏移量。)

Rotate函数我们在自转的部分,用它来绕指定的轴按我们设置的速度旋转,但这里用到的是Rotate的另一个重载;

obj.transform.Rotate(new Vector3(0, 360f / count * i, 0));

即传入一个Vector3的参数来表示欧拉角.这里我传入了一个(0,x,0)的变量,就表示让物体绕Y轴顺时针X度(注意这里的单位是角度而非弧度喔)。

第四种方法,直接修改欧拉角

obj.transform.eulerAngles = new Vector3(0, 360f/count*i, 0);

与第三种方法类似,想让物体绕哪个轴旋转多少度,就在对应的位置填入度数。

对于第三和第四种方法有几个需要注意的地方。
首先欧拉角的计算方法很复杂,对于X,Y,Z的修改顺序不同都会导致最终得到的效果不同,所以使用这两种方法的时候最好保证物体没有初始旋转。

第二,我们这里实现的效果使使forward对向圆心,如果说你的素材是一个不规则的图形,需要让forward以外的方向对向圆心,你可以给要旋转的度数加一个偏移值,顺时针加逆时针减。

第三也是非常重要的一个点,如果你在2D游戏中使用上述的方法你会发现你的游戏物体会转的乱七八糟。原因非常简单,如果你对比一下2D游戏中的2D场景和3D场景你会发现,2D场景实际上是相对于3D镜像过来的。


所以我们在代码中使物体顺时针旋转,而我们看到的结果是物体逆时针旋转了。
要解决这个问题也很简单,我们要想让我们看到物体顺时针旋转,只需要在代码中使其逆时针旋转,所以我们可以把要旋转的角度设为负数,或者用360-旋转角度,就能得到镜像视角下应该旋转的角度。
 

以上内容全部来源于本人实践与经验,但由于本人也是一个Unity初学者,如上文内容存在谬误,恳请发现者于评论区指正,感激不尽。

  • 29
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值