大家好,今天给大家带来一个FPS游戏中最常见的东西——靶子,几乎所有的FPS游戏中都会有训练场这个东西,玩家会在里面锻炼枪法以及判断枪械的强度。我做为一个FPS游戏迷,就想着去实现FPS游戏中的各种功能,于是我就决定从最开始的靶子开始。话不多说进入正题。文章会有点长,我把代码实现思路也写进去了。看完你肯定会有收获。 首先是准备工作,先要找到一个靶子的模型,然后分析它需要有哪些功能。下面是我总结的一些功能:
  • 被击中时会显示子弹造成的伤害数字;
  • 击中靶子不同的部位会有不同的伤害;
  • 当伤害量到达一定量时,靶子会被击倒,然后隔几秒会再立起来(这个立起来取决于自己);
  • 子弹击中时会显示命中特效和声音。
①先来实现第二点功能,我们要实现不同位置的区分,可以给靶子添加几个空物体,然后给空物体加上Collider组件,把空物体放到靶子不同部位即可。如图:
然后给每个空物体挂上脚本,脚本中要实现的功能是:子弹打到这个部位,这个部位就应该通知靶子扣除血量,并且每个部位要扣除的血量也不一样。于是我们采用观察者模式,利用一个事件中心EventCenter去管理所有的消息。EventCenter利用委托去存储方法,主体就是三个函数 Regist (向事件中心注册这个事件,表示我关心这个事件,以后只要事件触发我就会接到通知), UnRegist (取消注册,顾名思义就是不再关心这个事件), Trigger (用于触发事件)
实现完事件中心后,我们要做的就是在合适的时候去触发事件了。不难发现当子弹碰撞到靶子时,会触发相应部位的OnCollisionEnter函数,所以我们只需要在该函数内触发一个”Hit“事件即可,然后在靶子的脚本中的Start方法里注册这个“Hit”事件,这样一旦子弹击中靶子的某个部位,靶子就会收到信息。思路有了,接下来就是写代码:
上面三个就是靶子的三个不同部位,代码整体都一样,只是中间的伤害计算方式不一样(大家可以找到更好的伤害计算方法,我这里就是非常简单的方式),然后在触发事件时,最后一个参数也不一样,用来区分不同的部位,这样靶子就能通过这个int类型的参数来区分开不同的部位。接下来就该解决靶子的脚本,其实这个的思路上面已经提到过,就是收到Hit事件触发的消息后扣除血量。另外靶子的脚本应该负责特效和音效的播放,还要播放对应的动画。所以靶子的脚本如下:
在上面的代码中,主要的就是OnHit函数,上面的注释也写了,就是在事件出发的时候会调用这个函数 (参数的意义:第一个object其实就是击中靶子的子弹,Param1就是伤害量,Param2就是一个判断参数,这些参数都是在触发事件是由对应的触发类传递的), 判断出类型后就可以做对应的处理,我这里就只是扣血操作,所以没什么区别,每个case的代码都一样,但你可以加上其他的操作。然后就是特效和声音的播放,这部分很简单就不多说了。到此最核心的部分已经实现了。
②靶子倒下动画的实现:由于动画就只包含倒下和立起来,我就自己用Animation做了一个简单的动画(不会的可以自行学习,真的很简单),为了方便,我把倒下和立起来做成了一个动画。(注意,要把动画的Loop选项勾选掉,不然靶子会一直重复倒下和立起来),然后拖入到靶子的Animator中,我们还需要做一个Normal动画(这个动画只需要创建出来,里面什么也不用干),拖到Animator中让其成为默认动画状态.还需要添加两个变量去控制动画之间的切换。
前两个关键帧就是靶子倒下,中间的间隔就是隔多久靶子重新立起来,后两个关键帧就是靶子立起来,然后我们还要把动画和代码结合起来才能控制动画的正确播放。上面我们说过,当靶子的生命值health≤0时,靶子才会倒下,所以我们在靶子的脚本中的Update中每帧进行血量的判断。
现在就可以正常执行了,但这个时候你会发现一个问题,靶子倒下了之后也会一直重复的倒下和立起来。这是为什么呢?因为我们靶子在立起来后我们没有吧health给它恢复,所以他会一直重复这个动画。所以我们需要一个Reset函数
然后我们回到Animation窗口,在最后一个关键帧添加一个帧事件。下图红色地方就是添加帧事件的地方。然后把Reset添加给帧事件即可。
到此功能2,3,4就都完成了。只剩下功能1,功能1我是用了UGUI HUD插件来制作,非常简单,代码中只需要调整字体的相关参数即可。
效果图:
Logo

分享前沿Unity技术干货和开发经验,精彩的Unity活动和社区相关信息

更多推荐