动作游戏中的击打判定
最近在玩怪物猎人世界,断断续续差不多 100 小时了,加上之前花在这个系列上的几百小时,不敢说是个老猎人,忠实粉丝还是算得上的。
因为职业原因,我又琢磨了一下这类游戏的实现方法。在网上搜不到太多直接资料,所以这篇 blog 更多的是对自己的想法的记录。这次主要还是想理解一下游戏中是如何处理武器和怪物之间的击打判定的。
我知道动作游戏和格斗游戏侧重点不同,但也有类似之处。格斗游戏尤其是 2D 格斗游戏资料比较全,制作方法成熟,从网上能找到不少资料介绍原理。浅谈格斗游戏的精髓——方块的战争 讲的非常清楚。为了性能,也为了简化及明确规则,2D 格斗游戏用了若干 AABB 轴对齐的矩形来做击打/碰撞判定。格斗游戏会精确到帧来做规则判定,在特定帧勾勒出 hurtbox (惯例上用红色框)作为攻击范围判定;如果击打判定帧的 hurtbox 覆盖了那一帧对手的受击盒 hitbox (惯例用蓝或绿色框)区域,就认为击打有效。另外,还会设定出碰撞盒 collisionbox 用来避免和对手重叠,或和障碍物做碰撞检测。
即使现在用 3d 技术来渲染,大多数格斗游戏依然可以归到 2d 格斗类型中,还是可以用这种方法来做的。比如最新的 Street Fighter 5 ,完全延续了平面 AABB 攻击盒的规则。在网上甚至可以找到工具 显示出攻击盒,帮助玩家训练,提高技艺。
也不是所有的 2d 格斗游戏使用 AABB 盒做击打判定,例如任天堂大乱斗就是用了圆和胶囊。比如 这个视频 很好的解释了攻击极打判定规则,武器对撞 clanging 规则,弹刀 rebound ,还有出招前摇 startup lag ,受击硬直 hit lag 。武器格斗会比拳脚格斗更丰富一些,例如同样是挥砍,剑尖的伤害会比中段的击打伤害高一些,这里是用多个优先级不同的 hurtbox 来实现的。
fps 游戏不同。其一,它一般是全 3d 逻辑的,其二,它一般是用子弹对敌人造成点伤害。所以,fps 游戏一般直接把一些立体的小盒子 Cuboid 绑在人物骨骼上,作为 hitbox 做受击判定。子弹的轨迹在很短时间(两帧之间)内可以看作是一个线段。所以这就是线段和若干 Cuboid 求交的数学问题。最早期的 fps hitbox 例如 Quake 3 采用的依旧是 AABB 轴对齐的盒子,这可以极大的减少计算量。当然,另一个原因是当时游戏还是采用的是帧动画而非骨骼动画。在 3d 引擎普遍采用骨骼动画后,通常采用把立方体直接绑定在动画骨骼上来描述 hitbox 。CS:GO 在 2015 年之后改用胶囊体和球来描述 hitbox ,胶囊体更接近人体的四肢,且运算复杂度要小于立方体。
怪物猎人这类游戏又不一样。我认为,把 hitbox 绑在怪物骨骼上这点,和 fps 游戏并无不同。但刀剑挥砍则更接近格斗游戏。但是,作为 3d 逻辑的游戏,我们无法再用平面的框框来在攻击判定帧勾勒出 hurtbox ,那么应该用什么呢?
我觉得应该采用空间的四边形来标识 hurtbox 为主。以太刀举例,我们可以在攻击判定帧设定一个攻击平面,平砍,纵砍,还是斜劈,这个平面可以根据攻击帧和前一帧的武器位置来决定,也可以设计人员自己设定。然后在这个平面上勾画出一个或几个矩形定义出 hurtbox 。击打判定其实就是这个四边形和代表 hitbox 的立方体或胶囊体求交。对于大锤这种有体积的武器,则可以用平行的两到三个矩形来模拟出其厚度。
之所以不用专用的物理系统来做几何体碰撞检测。一是没有必要浪费计算力,尤其是连续运动过程的碰撞检测运算量很大;二是我们需要一个规则更简洁明了的击打判定规则。不过,我们需要定制编辑器去让设计人员定义动画中的 hurtbox 区域,编辑器的开发会是工作量较大的部分。