unity做帧同步的动作游戏,如何防外挂?
看到一些说法强调帧同步要将逻辑与表现分离,把客户端的战斗逻辑放在服务器端同样跑一遍进行验证,通过这样的方式防止开挂,我觉得这样很有道理,但是一些游戏很难将战斗逻辑与战斗表现分离,例如像黑暗之魂这种游戏,角色的挥刀攻击,攻击是否命中的逻辑依赖于表现层,就是说攻击判定盒(逻辑层)随着动画(表现层)移动,这样的话好像根本无法做到逻辑与表现分离,然后服务器去跑战斗逻辑,所以我想问问,像黑暗之魂这种类型的游戏该怎么防外挂? 先说结论,逻辑与表现分离对防外挂毫无作用。逻辑与表现分离的概念可以参考我这篇文章:
放牛的星星:Unity手游实战:从0开始SLG——ECS战斗(三)逻辑与表现分离当客户端需要和服务器交换数据的时候,我们才会谈起同步概念。同步又分为状态同步和帧同步。
如果需要服务器来跑战斗逻辑,告诉客户端结果,那就是状态同步。帧同步的计算是完全放在本地的,所以才会出现外挂修改数据的现象。
对于帧同步而言,我们谈论更多的是如何检测和解决不同步。因为一旦不同步发生,那么不同的玩家就进入的完全不同的平行世界里去了。而不同步则来自于两个方面,1是自身逻辑产生的BUG,1是外挂。
拿著名的《王者荣耀》来说,一局游戏5V5共10个玩家,检测思路就是,每个玩家每段时间将自己端的数据上报,由服务器比对各个玩家数据的一致性,如果谁数据和其他人不一致了,则表示此人发生了不同步。此时程序是无法分辨出究竟是自己的代码出了问题,还是有人用外挂修改了数据。必须通过后台的人工追查才能定位问题。所以,王者其实是有一个允许的不同步值(大约在万分之五)。
回到黑魂的联机来说,也只是在极其有限的条件下,比如boss战才会开启联机。这个时候,对于游戏执行层面来说,增加一个玩家就好比是增加了一个AI一样。只是AI的逻辑和数据是来自于客户端预置,还是由服务器转发的其他玩家的行为。
它和暗黑3的房间模式有本质差别,暗黑3完全是由服务器控制的逻辑。
所以,综合结论,黑魂是没有办法防止别人外挂对你的影响,因为服务器不负责判定数据的真实与合法性,只是做数据和逻辑的转发。
但是,它可以从逻辑本身入手,进行外挂防治。
第一,加密客户端配置和资源。让玩家无法轻易的修改本地攻防数据。
第二,加密内存数据,不能让外挂轻易的找到存储攻击力、防御值等核心数据的存储地址,从而修改内存数据。
第三、混淆代码,不要让外挂轻易找到相关的函数地址,不然它只要把扣血的函数返回值改为0,那么就是无伤挂。 这个问题里其实包含着几个混沌在一起的问题了,这些问题包含几个领域:
正确的游戏开发中,视觉必须依赖于逻辑“裁判机”的无能,与想法的漏洞从游戏设计出发“无视”作弊
第一个问题:正确的游戏开发中,视觉必须依赖逻辑。
这个往往是区分游戏开发外行和内行的标尺。最常见的问题是:动作游戏里,当角色一刀砍下去,刀砍中对方的身体,这是不是模型碰撞?如果你只是用肉眼看,你会觉得就是啊,而且大多引擎都提供了模型碰撞的判定,但是那个判定是给你用来做动作游戏的吗?模型是美术资源,即“视觉”的核心构件之一,如果你需要的是“模型碰撞级”,你也应该用外部工具,把模型动作的每一帧的顶点数据导出数据文件(比如2进制文件或者json等配置文件),依赖于加载这个文件里的数据做碰撞,这才是“模型碰撞”,而不是真的两个美术资源之间产生了碰撞就是碰撞。这可以算是游戏开发外行的典型漏步。
所以游戏开发中,没有任何东西是必须依赖视觉的,如果你也玩过几乎所有市面上的引擎,你会发现有很多引擎里面有2个update(),一个是给逻辑的,在Unity是FixUpdate;一个是给渲染的,在Unity是Update,你可以类比(有点危险,但是那个意思)为2个线程,Update是再根据当前游戏的数据(注意,是数据,仅仅只是数据)做渲染和播放声音,而FixedUpdate是专门用来做逻辑的,之所以他2帧间隔一定是等时间的,是因为这就是逻辑FPS(Frame Per Second),逻辑帧是游戏逻辑世界的最小时间单位,而不是沙雕策划们理解的“秒”。由此你不难看出,视觉和逻辑分离是做游戏的基本功,而FixedUpdate下的逻辑去修改的所有数据,都可能是你帧同步时候的关键数据。
第二个问题:“裁判机”的无能,与想法的漏洞
实际上这个概念在我入行的时候,也就是2002年已经存在过,即做一些p2p游戏(游戏行业管“帧同步”游戏叫p2p游戏,因为是点对点数据传播的,不知何时被哪个根本不写代码的文章写手改名为“帧同步”了)的时候采用一台“裁判机”,裁判机只跑上面说的FixedUpdate,而根本不跑Update。你也看到了,一切依赖的数据,都没有模型之类的美术资源数据,裁判机的加载也是飞快的,讲道理逻辑应该是完全同步的,但是想法是美好的现实是残酷的。
首先,同步问题中就存在如果不同步该怎样的问题?因为我们知道p2p游戏同步需要做到数据准确同步以及校对问题,这里就涉及到浮点数无法相等的问题,以及随机数在不同计算机上的不同,尽管我们可以只用int(是的,游戏开发只要int是可以做好的,反而像现在Unity用浮点,单位是米而不是像素,在2D渲染的时候才会很容易出现“裂缝”等问题),以及做一个随机数算法就能完成这个任务,但是依然面对网络延迟以及局部的运算错误问题,我们不可能严格到一丁点不对就把一个玩家踢出游戏,裁判机的问题就在这里,裁判机的权力过大了,所以通常比如10个玩家一起的游戏,采用“投票制”,与大多人数据都不同且大多人数据都相同的时候,我们认为这个客户端存在异常,踢出游戏才是好的办法。事实也是如此,用裁判机,当时几乎每10盘游戏就有1个玩家被踢出,如果你把10盘游戏想做自己玩,那还能接受,但是你想想如果是10组玩家同时在玩(比如lol王者荣耀这种可能同时有10几万组玩家),有1组会有玩家被踢,这是多大的运营事故?
而另一方面,帧同步游戏最常见的作弊,并不是修改数据,而是模拟玩家的操作。比如玩CS的时候,作弊往往是帮你自动瞄准,而自动瞄准其实就是根据数据精准的将鼠标移动到对应的位置按下按钮。问题来了,玩家的操作其实也是将鼠标移动到某个位置,只是移动的位置并没那么“精准”,所以这个行为你很难判断是否是作弊。比如PC Windows,这类外挂往往就是模拟PostMessage或者SendMessage给windows的过程,这个和键盘操作是一样的,并且权限超过了一个软件本身,首先制作第三方安插在玩家的pc里是很恶劣的行为,当然在今天可能用户被蹂躏惯就那样了。所以回到“裁判机”,在这样一个玩法下,裁判机几乎是无能的。
第三个问题:从游戏设计角度出发“无视”作弊
事实上这个问题也很好理解,开始的时候我们竭尽全力去反作弊,最后发现这是一个沙雕行为。因为我们这么做就忘了多人游戏的初衷——几个小伙伴聚在一起乐一乐了(注意,我们说的是帧同步,大规模用户同场的大型网游,即便是行星边际2也不可能用帧同步),就像一群人聚在一起打麻将,允不允许出老千,出老千之后该怎么惩罚,这应该是玩家自己去协调的心态。玩就是图个乐趣,作弊坑害了游戏的乐趣,应该是玩家以及游戏策划去设计规则惩罚作弊者,而即使不是作弊者,因为水平差距过大引起了不快乐,玩家也会想惩罚这样的人(比如一起玩星际的时候,有个人打得太好了,于是大家7v1打他,这其实也算是一种惩罚),所以在这个问题应该从玩家自发、以及规则层(游戏设计)的角度去“协调”,而不是从程序角度强行解决,程序角度来看,技术上是根本防不了作弊的,就这么简单。
所以像黑暗之魂这类的游戏,如果他的作弊是采用一套脚本来模拟高玩操作,那你根本没有任何办法也没有必要去防这种作弊。 帧同步的前提就是逻辑与显示分离,你说像黑暗之魂这样的游戏,虽然我没玩过,但是应该也是逻辑显示分离的,你看上去是画面中碰撞产生攻击行为,实际上是逻辑上驱动的,你看到的都是视图假象。 只是你看起来好像是攻击判定依赖于表现,实际上未必是这样子的,单机的话怎么做都可以,传统的做法是跟表现分离的,可以参考
sfvsim: SFV Simulator 服务器是完整模拟,也有对应的物理系统就好了,不过犹豫网络延迟存在,对于高响应要求游戏,还是不够,还需要客户端自己做预测,和服务器做同步
如果是信息和操作外挂,服务器模拟也没啥用
黑魂这种高精度动作游戏,基本不会考虑外挂这种问题 所有功能写在服务器客户端只接收计算后的结果显示。 你说的这个动画在表现层是错误的观点,动画的本质是根据时间演进到相应的进度。换言之,只是改变了表现层想展示的样子罢了,与是否展示无关。
至于帧同步防挂方面,一者如你所言,另者在多人交战时,可考虑在关键时刻上报玩家信息做出对比,是为投票。 如果你的战斗逻辑依赖表现层,那你怎么保证帧同步的一致性呢?
页:
[1]