开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
这几天在把移动计算逻辑向 NIF 迁移的过程中,我一直在思考一个问题:要不要为服务器加上物理引擎?
为服务器增加物理引擎,主要出于以下几方面的考虑。
移动校验
物理引擎除了可以进行物理模拟,还可以对碰撞体之间关系进行检测,比如碰撞检测和射线检测等。而对于 物理模拟 和 碰撞检测,这正是一个能够有效防止客户端在位移方面作弊的绝佳手段。服务器在收到客户端发来的移动相关数据包后,服务器可以对服务器上的权威数据根据新的状态更新进行模拟,如果模拟的结果与请求不一致,那就可以认为客户端作弊。
对于 物理模拟,虽然精度很高,但是由于场景内的对象数量极大,对其全部进行模拟会极大消耗计算资源,不划算。因此可以退而求其次,只进行 碰撞检测,简化运动过程,把受力移动的部分抛开,只留下简单的定加速或匀速运动,这样就可以节省相当一部分的开销了。
当然要进行校验,有不止这一条路可选。我们还可以利用 NavMesh 的 可行走区域 对玩家的位置进行验证。但是我考虑的业务场景不仅仅是检查玩家有没有穿墙,还需要对 弹道 类物体进行验证,比如有没有被阻挡或命中,而这点是无法通过 NavMesh 做到的,所以就有了以下这个方面的考虑。
命中判定
我的想法是尽可能将这个 MMORPG 的游戏玩家尽可能向 ARPG 方向靠近,采用无锁定或半锁定的方式进行战斗。这样一来就需要我们在服务端进行命中相关的计算。
比如在近战技能中,我们需要判定挥剑的范围内有没有目标,从而对其进行伤害计算;又比如在远程火球技能中,我们向一个方向发射一个火球,火球沿直线前进,我们需要检测火球有没有击中目标,或者飞行途中有没有被场景中的物体所阻挡导致未命中。这时候就需要对其进行碰撞检测,如 Ray Casting 或 Shape Casting 之类的方法。
这些检测算法虽然也可以我自己手动实现,但是我对自己的水平没有那么自信,恐怕即使实现了效果也不会很好,况且我一直坚持一个理念—— 绝不重复造轮子 ,所以可以直接利用物理引擎实现这一项功能。
需求分配
除了 移动验证 和 命中判定,服务器还需要 寻路功能,这项功能利用 NavMesh 实现是最直接的,所以说 NavMesh 是有用的。这时如果把这集中需求放在一起讨论,我们就不必拘泥于某项功能必须由某种技术实现,而是哪种实现更方便高效就可以用哪种。如果没有 寻路 需求的话,那我们完全没有必要额外引入 NavMesh 的概念,完全用 物理引擎 实现就很完美。但是现在再来看,既然 NavMesh 一定存在且使用,我们不妨重新考虑下 移动验证 的实现方式。对于 NavMesh 来说,验证方法很简单,只需要看角色位置是不是落在 可行走区域 中,这个计算量非常小。而对于 物理引擎 来说,因为我不是很懂内部实现,所以不清楚他的碰撞计算量大小,但是我盲猜应该是比 NavMesh 直接对比要来得效率低一点。所以 移动验证 的功能我们是不是也可以考虑使用 NavMesh 来实现?
考虑方案:
- 移动验证:物理引擎/NavMesh
- 命中判定:物理引擎
- 寻路:NavMesh