在很多游戏类型中,玩家角色对物理行为的处理往往和场景中其它物体的行为有比较大的区别。比如角色可能会以90多公里的时速狂奔,同时一次跳跃能跳10多米高,与此同时却几乎不会有任何惯性。同时角色在正常情况下当头部碰到障碍物的时候,应该只是会被阻挡前进,而不应该直接仰面摔倒。这些特殊的需求注定不应该以普通的碰撞区+刚体的形式来实现,所以unity为我们准备了名叫“角色控制器”(CharacterController)的组件。然而到目前为止(5.5)unity中只为3D物理提供了这个组件,针对2D游戏则需要我们自己实现一套类似的机制。
基本原理就是不用自带的那些物理判断,而使用射线检测等方法来判断前进方向上是否有障碍物等并修改移动的方向和距离,从而达到所需的效果。起初博主自己实现了一个有基础功能的版本,后来在github上发现了一个别人实现好的功能更全面的版本,所以在这里分享出来。
地址:https://github.com/prime31/CharacterController2D
博主使用这个控制器的主要目的是为了做一款平台动作类游戏,因此也会着重说一些制作使用途中遇到的问题以及解决方法。
先看一下组件挂载在GameObject上之后可以设定的属性:
可以看到这里和CharacterController一样也有Skin Width这个选项,这个选项会影响角色控制器检测碰撞时的射线,具体的实际影响会在之后代码的部分再详细说。
然后接下来是设定三种射线检测时的层级:不可穿过的墙壁、地面;触发事件而不会影响物理控制的触发区和可以单向穿过的平台。
再往下是上坡角度的限制、跳跃阈值以及在坡道上运动时由于坡度对速度造成的影响的曲线。跳跃阈值这里博主在自己的项目里并没有使用到,不过在作者的demo里面是有用到的。
最后就是水平方向和垂直方向分别的射线数量。射线数量越多,相对就会检测的越精确,不过也需要花费更多的计算资源。
需要注意的是,这个角色控制器会要求挂载的对象上同时也具备刚体(Rigidbody2D)及矩形碰撞区(BoxCollider2D)两个组件,其中刚体是触发碰撞必须的组件,而矩形碰撞区虽然必须挂载,但并不意味着就一定要使用它,可以在代码中随时进行切换,只不过如果在角色已经落地了的情况下,直接切换到一个更大的碰撞区的话,是有可能会导致角色卡住的(碰撞区底部陷入地面)
基本上最基础的使用就是调用move(Vector3 deltaMovement)这个方法。这个方法的意义是将控制器向deltaMovement向量移动,若其中有任何被标记过的不可穿过的碰撞区则都会阻碍这次移动。
有一个问题需要注意,就是移动的时候,若需要获取到是否在某个方向(上下左右)接触到了障碍物的话,一定要使传入的deltaMovement向量中包含着向障碍物方向移动的分量,否则将会导致跳过该方向的碰撞检测从而无法正确得知你所需要的信息(比如明明就在地面上,isGrounded属性却一直是false的话,很有可能是因为你的移动分量里没有向地面的分量,而碰撞区本身又有一点点倾斜,导致出现了检测错误)
下一篇将会更详细的说一下代码的部分。