据Bmob官方人员的透露,他们一开始产生作Game SDK的念头,主要就是由于吃鸡的火爆。java
(还有一大缘由是,从后台数据、客服与开发者一对一聊天获取的信息来看,使用Bmob目前服务的开发者中,须要游戏实时数据云服务的开发者占了很大的比例。)算法
因此一开始Bmob团队开发Game SDK和Demo的时候,都是复刻 蓝洞的绝地求生
这款游戏,努力在还原全部这个正版游戏的设定。后来历经沧桑,开发到游戏 能跑了 ,微信小游戏
又出来了,而小游戏须要实时传输数据 仅支持Web socket ,且不少人都看好在这个小游戏平台开发的休闲类、益智类、棋牌类等等轻量的游戏。这样一来,之前面基于 FPS
开发的、 强交互
的、高频处理数据
的云服务就不适用了。数据库
因而Bmob团队把这一套服务 几乎彻底推倒重来,把核心算法保留下来后,再借鉴众多游戏的思路(其实就是主程沉迷过的游戏),解剖各种型游戏的各类场景,从新开发了一套BGS系统(心疼前面那一套花掉的血与泪一秒钟)。如下以 《梦幻西游》、《绝地求生》 游戏为小节,分析一下如何用BGS实现。安全
(笔者只是Unity开发萌新一枚,非专业游戏行业人士,若有错误,还望谅解)服务器
这个游戏真是让人又爱又恨啊,想当年...微信
好吧咱们仍是从技术层面来讨论一下。网络
首先,这绝对是一个是 很是依赖数据库
的网游,小到物品栏的摆放、刷塔得到经验,大到人物升级、任务完成,都是创建在数据库操做完成的基础上才容许客户端呈现的;
也就是说,在你网络很差的状况下,连物品栏你都调整不了摆放的次序,选中的东西会没掉,且不会移动到你指定的地方。若是你要说,这不是废话吗?哪一个游戏不是很是依赖数据库?那你就错了,不少实时对战的游戏还真不须要,例如FPS,只要在战斗开始时获取一下玩家姓名和皮肤,战斗结束时记录一下战绩就能够了socket
其次,全部玩家动做都以 服务器的计算
为准,例如玩家走路,在必定的帧数内你能走几步,都是服务器计算的;此外在战斗中,伤害的计算、经验的结算,都是由服务器计算的;挖宝图的时候,爆率都是服务器调整的;
也就是说,在你网络很差的状况下,连走路你都走不了,就算在客户端来看你迈出了几步,可是网络一恢复,你原来在哪仍是在哪。若是你要说,这不是废话吗?哪一个游戏不是全经过服务器来计算?那你就错了,不少实时对战的游戏还真不须要,例如FPS,玩家的位置在哪里、是否击中目标对其它玩家形成伤害,都是客户端本身说了算的,由于不少服务器没有内置整套的物理引擎,即便有,形成的服务器消耗太大,成本也过高(试想一下,在PUBG巅峰300w玩家同时在线的时候,可能有6w个房间,每一个房间都要有一套物理引擎,一局听说有10万+颗子弹,每一颗子弹飞出去都须要有弹道下坠,要逐帧计算初速度和重力加速度,以及和整个地图海量的3D刚体进行碰撞检测)。这也是为何PUBG有飞毛腿、隔山打牛、瞬移、神罗天征、万象天引等等外挂了函数
最后,除去IM系统来说,实时数据方面,主要是每一个城镇的其它玩家分布的位置,而梦幻西游一个城镇挂机的玩家是很是多的,因此开发的时候,确定是将每一个(有移动行为的)玩家的位置同步到界面可视范围内的其它玩家那里,而不是推送给整个城镇的玩家;即使如此,在有活动的时候,同屏的玩家仍然是很是多,这个时候就会感受什么操做都特别卡。也就是说,在你网络很差的状况下,哪怕你身边人山人海,你也可能一我的都看不到,而你在荒无人烟的野外跑商的时候,连聊天都比较流畅
若是你要说,这不是废话吗?哪一个游戏不是只传递可视范围内其它玩家的信息?那你就错了,不少实时对战的游戏还真不能够,例如FPS,你朝远方、朝天边随便开一枪,也可能射死个几公里之外、无需渲染的玩家,这也是为何透视外挂再远可以看到全部玩家的信息。spa
那么,如何使用 Bmob Game SDK
来实现像 梦幻西游
这样的一款网游呢?
首先,所有同区的玩家都在同一个Room,这个Room不须要同步任何玩家眷性
其次,必定要用 Bmob Game SDK
的 云端代码
,里面 自带
了 Bmob数据库
的操做接口,能够快速结合数据库实现不少功能
最后,必定要充分利用 Bmob Game SDK
的 云端代码
,用属性监控、事件监控等功能,能够完美实现上面所说的几个特性,例如伤害计算、同屏推送等
欢迎四排组队,本人亚服排名3w求大腿...
好吧咱们仍是从技术层面来讨论一下。
我以为比较有意思的讨论点在于:
FPS类,或者说全部有PVP模式的游戏,都有一个共同的烦恼,就是Damage谁来断定的问题;选项无外乎三个:攻击者
、被攻击者
和 服务器
首先,咱们排除掉单纯采信 被攻击者
断定伤害这个选项,虽然这种方式在某些场合下显得较为公平(玩家被攻击得明明白白,不会莫名其妙GG);可是这样很容易形成 高Ping大神
和 锁血挂
的出现;并且这样的话,掉线的玩家就永远不会受伤和死亡了。
所谓高Ping大神,就是将本身的网络搞差,例如利用南辕北辙的加速器,或者自己就是"卡B",他们能够在敌人的千军万马中几进几出,毫发无伤;说极端一点,拔掉网线,就能够进入无敌状态,还附送大招CD恢复
锁血挂的实现原理有不少种,有一种就是篡改本地逻辑或拦截网包,以破坏上报本身受伤的信息,服务器永远不知道客户端受到了伤害,在其它玩家看来就至关于锁血了。
其次,咱们也要排除掉单纯采信 攻击者
断定的方式,虽然目前大多数FPS游戏都是这样实现的,可是隔山打牛你见过吗?回放时看到神仙对着空气来一发喷子方圆公里寸草不生的恐惧你忘了吗?
所谓隔山打牛,其实就是利用了子弹与其它玩家的碰撞检测时发送信息给服务器这一点,若是hook了这个函数,或者破解了这个信息的网包协议,随便开一枪均可以将子弹精准得"碰撞"到对方头上,由于服务器傻啊
而后,还要排除单纯使用 服务器
断定的方式,由于这是一个对现实世界还原度很高的FPS游戏,不是LOL、农药那种MOBA游戏,也不是梦幻西游那样的回合制游戏。要完成模拟子弹的射出的话要求服务器有一套和客户端彻底同步的物理引擎(没有渲染功能),消耗太大;此外,在玩家须要爆头击杀、远程点杀的时候,稍微一点的角度误差也会影响最终的结果,这意味着即便是即使有足够的资源支撑服务器模拟3D世界,高Ping玩家也可能由于那一点点角度,永远都能击中但杀不死那个敌人。而PUBG的弹道下坠更是让服务器模拟起来更加吃力,毕竟不像某go是激光枪啊。
虽然上面已经讲过了,但这里为了字数再啰嗦一遍:
PUBG的玩家同时在线巅峰值是300万
假如每一个房间有50我的(不要说100人,有不少房间在决赛圈呢)
就会有有6万个房间正在进行游戏
每一个房间都要有一套物理引擎
每一颗子弹飞出去都须要有弹道下坠,这意味着要逐帧计算初速度和重力加速度,来肯定子弹位置
子弹飞出去后,要逐帧和整个地图海量的3D刚体进行碰撞检测
Uzi射速是0.048s/发
据分析源码的人说一局听说有10万+颗子弹
因此,我认为最好的断定方式是 攻击者
结合 服务器
断定的方式,攻击者上报了击中事件后,服务器计算这个上报信息是否可信,而后再作出最终断定
服务器判断可信度的方式有不少,等级也分不少种:
以目前的BGS内测的状况来看,作到 攻击者
结合 服务器
断定,而且加上 中层次的判断
是彻底没问题的:
要求开发者写云端代码,在云端代码添加 Position
和 Rotation
的 BmobGameHook
,在上报玩家击中事件时,用 java.lang.Math
里面的三角函数就能够简单判断一下此次击杀是否合理了
安全区确定是服务器统一肯定的,而且是逐帧计算的
随机圈的时候:
缩圈的时候:
其中m = (大圈半径 - 小圈半径) / 帧数
其中n = [(大圈圆心x - 小圈圆心x) / 帧数, (大圈圆心y - 小圈圆心y) / 帧数]
这一套彻底能够用Bmob Game SDK的云端代码的 Room.onTick
实现,而后再逐帧向客户端下发当前的安全区的圆心和半径,而且结合 Player.getPosition
,计算玩家是否在圈内,若是在圈外的,调用 Player.setHp
进行减血
请注意,上面提到的 getPosition、getRotation、onAction_Damage、setHp (还有相似 onUpdate_Posision)等方法,都不是Bmob Game SDK云端代码自带的!而是开发者在设定了他游戏有hp这个属性后,在上传的 Player.java 类内,直接按这种命名规则写这个方法就能够读取、监听、修改这些属性啦,超方便的!
有什么好的建议,给我留言,或者直接去Bmob游戏开发官方群中呼唤我:
Q群:726133616