【Unity3D】刚体自动寻路的抖动问题和运动边界、空气墙的制作
《【Unity3D】自动寻路》(点击打开链接)给我们带来很多方便,尤其是3D游戏的主角移动方面,但是这个东西同样也会带来很多问题。如下图所示。这是一个比较失败的自动寻路例子,由于蓝色的球并不是让玩家主控,只是一个NPC,而这个NPC未来又可能像主角一样进行移动,我们无法像白色的立方体如同墙一样,在自动寻路界面给它上一个Navigation Static属性,因此,我们只是给红球和蓝球共同上一个刚体RigidBody的属性。
此时大家就可以看到如下图的问题,虽然蓝色球作为一个刚体被撞产生移动是没问题,但首先我们不像这个球被撞出白色平面。由于蓝色球不像,也不可能像红色球上一个Nav Mesh Agent组件,不然会影响自动寻路的。同时,还有更严重的问题,红色球在自动寻路的移动中,不可避免地有可能和蓝色的球产生碰撞,然而才产生碰撞之后,红色球的开始鬼畜地抖动,同时不停控制在无须移动了——大家可以看到我的鼠标根本没点Plane任何一个地方,这种鬼畜的抖动和不停使唤的情况在自动寻路Nav Mesh Agent组件的加速度Acceleration设置得越高越为明显。
以下是上述两个大问题的解决方案,让自动寻路至少看起来更合理更完美一些。
一、刚体自动寻路的抖动问题
首先,正如上面提到的,对于上了Nav Mesh Agent组件的自动寻路主角,如果你想它移动快一些,你应该将其Speed调大,而不是Acceleration。
当然,以上仅仅是一个治标不治本的做法,更多的是,需要同时给自动寻路主角,也就是上例红色的球,上一个Rigidbody属性,同时将Is Kinematic勾上,
至于诸如上图的蓝色球,这类不是诸如白色墙Navigation Static一动不动的,而是未来或许会和自动寻路主角,也就是上例的红色球,发生交互的物体,你也同样上一个Rigidbody属性,但要将Is Kinematic取消掉。
这时,红色球的自动寻路就不会有鬼畜抖动的效果,能够做到完美寻路了,你并不需要还在脚本特意写些条件,视图锁定xyz轴的position和rotation这么复杂。
你只需要弄好Is Kinematic这个属性就好。Is Kinematic的官方定义是这样的:
上述文字取自Unity3D的对于刚体Rigidbody的官方API。这个属性之所以这么大魔力,主要是因为它控制了,这个刚体首先是影响物理引擎的东西,也就是像蓝色球被撞,它根据3D碰撞力会向其余地方移动,还是首先响应运动学,也就是人为改变其transform的动作。
我们在不停对这个红色球进行自动寻路动作,其实就是,不停人为改变其transform。大部分情况下,在刚体自动寻路产生严重的抖动问题,也就是不停地在鬼畜,原因就是,默认情况下,刚体是没有勾上Is Kinematic的。导致其不停计算碰撞又不停计算我们对其下达的自动寻路命令,因此导致了严重的鬼畜。
二、运动边界空气墙的制作
之后,我们借防止蓝色球滑落Plane,说说运动边界,空气墙的制作。运动边界,空气墙在3D游戏中很常见的,毕竟地图再大如《上古卷轴》或者《辐射》也就是有边界的,更不用说《*飞车》这种规定路线移动的游戏了,我们注定要设置一个运动边界,不可能让玩家移动到地图外面去,诸如这个例子,蓝色球被碰到Plane外面了。
所以我们要制作运动边界和空气墙。毕竟,蓝球,并非自动寻路的主角红球,不会自动产生运动边界。至于红球如何取消运动边界可以参看《【Unity3D】自动寻路的跳跃》(点击打开链接)。
空气墙实质就是一个看不到的立方体而已,如下图所示:
其制作不是通过cube弄出来的,而是在一个空物体Empty中加一个特定位置的Box Collider完成的。当然,墙也不一定是立方体的形状,Unity3D本身就有Sphere Collider等各种形状的碰撞体。这样刚体碰到这个透明的东西,就真的像碰到空气墙一样了。
或许有人说我为何不直接弄个大的边界碰撞盒子来完成这个问题,也就是这样,多省事啊!
这样当然不行,因为Unity3D所有的碰撞体都不是实心的。这样做,最后的效果,就是这个碰撞盒子里面的所有刚体,直接被击飞不知道飞哪里去的。因为Unity3D对于碰撞的计算是根据刚体与刚体在下一帧的可能相交体积来决定的。
上述两个物体解决之后,就能收到以下比较完美的效果图,可以看到红球在自动寻路的过程中,就算碰到蓝球都没鬼畜和不可控现象,并且蓝球也不会被撞出Plane,掉下去。
其实完全可以根据上述原理来完成一个台球游戏啊!