查看: 5862|回复: 4
打印 上一主题 下一主题

有关游戏角色控制的几种实现方式(二)

[复制链接]

21

主题

7

听众

651

积分

初级设计师

Rank: 3Rank: 3

纳金币
0
精华
3

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-10-24 23:23:00 |只看该作者 |倒序浏览
  这一篇我接着上一篇继续讨论角色控制方面:利用胶囊体与刚体对角色的动作进行控制。我仿照了官方的Angrybots,自己写了3个控制脚本,分别为:SuperMarioMoveAnimaiton.cs,SuperMarioRigidbody.cs,SuperMoveMotor.cs。这三个脚本我也一并奉上。
    与前面的控制方法不同的是,这次没有用角色控制器来控制角色了。现在我来演示一遍我的做法。
    我们在刚才的官方的工程中新建一个场景,取名为:TestRigibody。然后从Project面板下展开Goober Artwork文件夹下的子文件夹FBX,将area这个FBX文件拖拽到Scene视图中去。



顺便也将goober的FBX文件拖拽到Area上。至此我们的场景已经搭建好了,如图:



接下来我们要做好几项准备工作了:
首先,我们为goober添加一个Capsule Collider( 胶囊碰撞器 :菜单-->Component-->hysics-->Capsule Collider),然后,我们调节此胶囊碰撞的一些参数,直至适合goober的大小,再次注意一下,胶囊碰撞器的底部一般要高于角色的脚部的高度,这样运行起来角色就不会像悬浮在地面上一样。我调的具体参数的截图如下:





现在,我们像goober加入Rigidbody(  刚体 :菜单-->Component-->hysics-->Rigidbody )组件,然后再在Inspector面板下调节缸体组件中的Constraints参数,如图:










我此时冻结了刚体的X与Z轴向的旋转,具体为什么要这样做呢?因为刚体这个组件一旦添加到角色身上,那么英伟达的PhysicX引擎将作用于角色,角色如果受到哪怕一丁点力的作用就会产生物理效果,这里我们不想让角色倒地,所以冻结了它的X与Z轴。
接下来我们就要来拖拽脚本到我们的goober上去了,好,我将这三个脚本全都拖拽到goober上面。摄像机还是用的是SmoothFollow这个js脚本( 以后一定会用更特别的脚本来控制摄像机的 )。这样做还不够,我们还必须将goober从Hierachy面板下拖拽到刚才goober本身的Super MarioRigidbody.cs脚本下的Motor变量位置,由于Motor的类型是SuperMoveMotor,那么此时Motor选项中的goober自动提取其下附着的SuperMarioRigidbody组件作为此变量值。
首先,我将我的两个脚本的截图奉上:




我们可以观察一下,上面这个脚本中有一个SuperMoveMotor类型的变量,名字与我自己写这三个脚本中的一个名字相同。其实,我们的脚本就是一个类,可以继承别的脚本,也可以被继承( 有点面向对象了! )。并且脚本也是一个组件,其实,Unity里的所有组件归根结底就是脚本。甭废话了,看我们的代码吧!
首先还是老规矩,如果变量很多的话,就先看函数,貌似我的脚本中的变量也不多啊,算了。第15行,初始化motor中的moveDirection向量为Vector3( 0,0,0 ),我们看下面这张截图,可以发现motor下正好有一个moveDirection变量,而且还是公有的,正好可以再其他脚本中使用。下一行就比较简单了,存储摄像机的transform。我们看Update函数。

   因为Update函数每帧都在执行,所以他的第一行不出意外也会每帧执行一次,也就是UpdateMoveDirection每帧更新。
我们先跳转到UpdateMoveDirection这个函数下。第29~33行我截个图:


第二十九行,我们发现了我们刚才一开始没有看的成员变量screenMovementSpace现在被赋值了,其值的类型是Quaternion,四元数。而且是将摄像机的世界Y轴方向的旋转角转换为四元数,现在还不清楚要做什么,我们看第31行,将此四元数与世界坐标系中的Z轴方形的单位向量相乘。四元数与三维向量相乘,功能是将此三维向量用该四元数来旋转,就是用摄像机绕世界Y轴旋转的角度来旋转此单位向量,这就是这个乘法的功能。下面第33行也是同样的道理。我们可以想象一下,如果摄像机绕世界Y轴没有旋转的话,那这两个向量会是什么情况?从顶视图看就会使这个样子:





一般情况下是这个样子 :





注意:蓝颜色的是Z轴,红颜色的是X轴,绿颜色的是Y轴,图中的那个空的GameObject的Z与X轴可以看做是我们的Vector3.forward与Vector3.right,组合成一个十字架。
那么如果摄像机绕世界Y轴旋转,那么这个十字架的世界坐标系Y轴方向旋转角度也会与其一致,你此刻会发现,这个向量或许可以作为我们goober移动的方向,这样想很好,但是接下来我们看到的代码会有点特殊,因为此刻我们不再用CharacterController这个组件了。
下面这两行的用意很明显,利用方向键来控制motor.moveDirection的值,与前一篇一样。然后保持此向量的方向,让其长度为1个单位长度。接下来我们就来分析motor了。




motor是SuperMoveMotor类型的,且moveDirection这个变量最终是要在这个脚本中大显身手的。由于此脚本也绑定在goober身上,那么他必然起着一些直接作用。老样子,先看函数,
我们看第12行,将刚才的moveDirection与一个walkSpeed变量相乘,存储在一个临时变量targetVelocity里面,紧接着用此变量减去刚体组件的速度。一个好像是将要移动的方向,另一个
又是移动时速度,这两者相减得到一个类似于速度差的向量deltaVelocity。我们再往下看,if语句,如果刚体使用了重力,那么就向下执行。先看第15行,让刚才的速度差的Y轴方向分量为0,也就是让此向量平行于世界坐标系中的XZ平面。然后对刚体施加力。那为什么施加这样一个力呢?




我们可以运算一下:
deltaVelocity + rigidbody.velocity = targetVelocity -rigidbody.velocity + rigidbody.velocity=targetVelocity
=moveDirection * walkingSpeed。至此,你应该明白了为什么要施加这样一个方向的方向力给刚体了,是为了校正刚体的移动方向 与moveDirectoin一致。
其大小deltaVelocity与一个浮点型的变量的乘积,且施加力的模式是渐渐增加的( ForceMode.Acceleration)。我们再看下面if里面的语句:




出现了一个好像与旋转相关的变量rotationAngle,此变量的值是由AngleAroundAxis这个静态函数来处理的。为此,我们必须了解这个函数该怎么使用。截个图:







我们看穿进去的是什么参数:transform.forward,这个是goober的自身Z轴的单位方向向量。moveDirection,这个与goober将要移动的方向有关,也是单位向量。Vector3.up,还是单位向量
只是它是平行于世界Y轴方向的。
我们看第28,29行,用到了一个平时很少用到的函数Vector3.Project( )。那么这个函数是用来做什么的呢?是用来求得dirA投影到axis上的向量的。如果你的向量运算方面比较好,那么这两行的意思你立马就能明白。其实就是将dirA与dirB这两个向量的Y分量设为0。也就是让这两个向量水平罢了。具体是这样算的:
首先用dirA投影到axis上的向量为b,由于axis传进来的参数是Vector3.up,也就是世界坐标Y轴单位向量,设dirA与世界Y轴的夹角为a,我画一张图你就能明白的:


第30行是求dirA与dirB之间的夹角,第31行中涉及到了向量的两种基本概念,即点乘与差乘。你应该熟悉点乘,就是两个向量的x,y,x分别相乘之和,但是差乘就有点麻烦了,但是我这里提供以下我自己的一点点经验:两个向量a,b的差乘的结果是一个向量c,且c垂直与a与b形成的平面。而且c的方向可以用左手定则来确定,也可以利用3阶行列式相乘来确定。左手定则的具体做法是:伸出你的左手,让大拇指垂直ab平面,且四指朝向向量a指向的方向,然后你可以试着顺时针旋转左手看能不能顺利的旋转到向量b所指向的方向,如果可以,则大拇指指向的方向就为c的方向,反之亦然。
那么第31行的意思就是:如果俯视向量dirA与dirB,发现从dirA旋转到dirB只需要旋转一个小于180度的角,那么该函数最后的返回值为angle,否则为-angle。如果读者还不明白,可以给我留言.

我们回到24行,由静态函数AngleAroundAxis返回的角度变量用作对角色施加的角速度的一个度量,然后对其大小进行一番调节,即乘以turningSmoothing。最后对刚体施加一个角速度。




至此为止,我们用刚体加胶囊碰撞器控制角色已经全部完成了。总体思路就是:对刚体不断施加一个渐渐增长的很小的一个力,并且相应的施加一定的角速度来触使角色边移动边旋转。并播放动画(动画脚本比较简单,读者可以自行研究一下,以后如有机会,我会专门讲动画这一部分的)。里面涉及到了不少向量方面的运算,都比较基础,如果空间几何学的不错,那么理解这些真的是不费吹灰之力。这种实现方式跟官方的AngryBots是一致的,只不过官方的实现要复杂很多,读者用兴趣可以认真分析一下官方的例子。

















分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

.    

3797

主题

11

听众

5万

积分

首席设计师

Rank: 8Rank: 8

纳金币
32328
精华
41

活跃会员 优秀版主 荣誉管理 论坛元老

沙发
发表于 2012-10-25 21:04:03 |只看该作者
顶起
回复

使用道具 举报

may    

8830

主题

80

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
52312
精华
343

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

板凳
发表于 2012-11-30 22:20:50 |只看该作者
支持楼主的帖子
回复

使用道具 举报

may    

8830

主题

80

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
52312
精华
343

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

地板
发表于 2012-11-30 22:21:15 |只看该作者
支持楼主的帖子
回复

使用道具 举报

2317

主题

54

听众

2万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
20645
精华
62

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

5#
发表于 2012-12-28 23:24:57 |只看该作者
学习了,虽然还是有难度,谢谢楼主的用心
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-5-12 23:16 , Processed in 0.098288 second(s), 33 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部