坦克世界 0 fps 丢包 家用50M电信光猫丢包 进游戏时卡 一会又好了 人多30左右 看天空70左右 主要是什么原因

后使用快捷导航没有帐号?
查看: 6106|回复: 148
新人欢迎积分1 阅读权限30积分115精华0UID帖子金钱192 威望0
Lv.3, 积分 115, 距离下一级还需 135 积分
UID帖子威望0 多玩草0 草
我家是移动50M光纤的,骗人是小狗,网速好的时候下载速度可以每秒8M,不好的时候就是0!坦克游戏体验极差,吗的999的延迟,根本动不了,前天我给客服投诉,客服妹妹让我用移动盒子测试,好吧,我去试一下,我R了,测出来带宽1M!!!老子开的是50M光钎啊!深度测试,丢包率32.3%!移动自己的盒子测出来,全部得0分!这是什么破网,我父母家用的电信50M,玩什么都没问题,还能边看高清边玩游戏,毫无影响,我就是贪了便宜,移动比电信便宜不少,想着也是大公司吧,结果什么玩意!!
17:21:13 上传
17:21:13 上传
&想打游戏的,只推荐电信或者联通(看你的游戏在哪个区,对应的就选哪家的宽带)&
&我以前也是移动宽带,就是看中他的价钱,后来一怒之下电信包了3年20M的,我一边下载一边坦克,还有页游,以及爸妈的宽带电视,坦克速度一般在30&
&移动就是原来的铁通。。。垃圾的不能再垃圾了。&
&除了电信就是联通 其他宽带都是伪宽带&
&你需要一个加速器&
&移动宽带其实原来的铁路的铁通&
&成都移动用户免费送宽带,你说能有多好?&
&找客服来修啊&
&带宽和你网速没有必然联系&
新人欢迎积分1 阅读权限50积分1935精华0UID帖子金钱18215 威望0
Lv.5, 积分 1935, 距离下一级还需 565 积分
UID帖子威望0 多玩草0 草
哈哈,又一个入坑的,我现在也是移动100M的宽带,玩游戏电信区基本是110左右,网通区80左右。
我用电信宽带是30+联通宽带60+,移动还是厉害些。
交话费送的,我也就不说什么了
:没用哦,还是丢包,怒拍键盘&
&我也是移动的表示键盘已经砸烂,玩到你崩溃&
&下载一个移动专用的游戏加速器家可以了我在浙江软件名字叫《》浙江移动网络加速器《》各省名字不一样的&
&移动是微波辐射,无绳上网?丢失了&
&深有同感,痛苦的时候气得要摔鼠标砸键盘!&
&同,早上好点可以30流畅,晚上丢包&
新人欢迎积分0 阅读权限30积分122精华0UID帖子金钱1299 威望0
Lv.3, 积分 122, 距离下一级还需 128 积分
UID帖子威望0 多玩草0 草
我给你讲个笑话&&铁通玩网游&&开加速器都尼玛卡&&100M都一个鸟样&&
新人欢迎积分1 阅读权限80积分13805精华0UID帖子金钱15421 威望-1
Lv.8, 积分 13805, 距离下一级还需 4195 积分
UID帖子威望-1 多玩草100 草
新人欢迎积分0 阅读权限40积分360精华0UID帖子金钱9650 威望0
Lv.4, 积分 360, 距离下一级还需 640 积分
UID帖子威望0 多玩草0 草
有个叫uu 好人不谢
:20延迟居然会被喷→_→&
&uu就是不错的,我一直用,也有特权。&
:你用过网易uu么,那叫真心好,这么破司司就一坑钱的私开软件,流氓软件,网易多大的公司啊,多可信,免费还好用,我南方用联通加速后延迟20,,别喷网,我才20兆而已,和网没关系 &
:司司是个垃圾,我也买了一个月的,我的是乡下移动20m光纤,用uu,南方节点是27,多网是80到100,不掉线。用司司,我操,把把有特权,这个牛逼了,延迟40,妈的,还没打完一把呢,“你的特权已断开,请重新登陆”,我 &
&能不骗人吗,还uu,买了一个月的司司网吧特权晚上都卡着不能玩,免费的能用,我是50M移动宽带。&
新人欢迎积分0 阅读权限40积分779精华0UID帖子金钱1641 威望0
Lv.4, 积分 779, 距离下一级还需 221 积分
UID帖子威望0 多玩草0 草
移动宽带是啥?
哦对,他本来叫铁通来着
新人欢迎积分1 阅读权限30积分143精华0UID帖子金钱1604 威望0
Lv.3, 积分 143, 距离下一级还需 107 积分
UID帖子威望0 多玩草0 草
看电影用移动,其他还是电信吧。UU加速器可以到60吧
第三施工队队员
新人欢迎积分1 阅读权限80积分13666精华0UID帖子金钱61682 威望1
二雷始终不肯放弃治疗,真是头疼!!!
Lv.8, 积分 13666, 距离下一级还需 4334 积分
UID帖子威望1 多玩草1824 草
你肯定没用过长城宽带,和那比移动都算好的。。。
:用网易uu不行嘛?&
:我听一个工程师解释是小区用的是总线,底下是分线,但总线流量是固定的,就像水管一样,人越多越挤越细,大概是这个意思,真假不知道&
:深圳的长城宽带服务也蛮好,现在回来了,家里就三家,没别的选&
:为什么小区人多就卡?你是小区共用宽带?&
&青岛老乡路过。。。表示在韩国撸坦克,开玲珑一月100块。&
:爱普是啥,青岛没见过这个&
:主要取决于小区人多少,人多就卡&
:我在青岛长城宽带可以总结为除了服务态度其他什么都没有,现在换了有线电视的,别的也安不上。。。&
&在深圳用长城宽带,玩坦克还好,不卡&
&长城宽带看区域的,有好有怀,虽然长城宽带有一堆渣毛病,但这么多年来唯独连接电信的服务器速度比电信用户差不多,基本上都是10-40ping&
没时间解释了,快上车!!!
新人欢迎积分1 阅读权限90积分20180精华0UID帖子金钱23336 威望0
Lv.9, 积分 20180, 距离下一级还需 7820 积分
UID帖子威望0 多玩草718 草
卡死你,楼主。老老实实用电信
新人欢迎积分0 阅读权限60积分3745精华0UID帖子金钱10135 威望0
Lv.6, 积分 3745, 距离下一级还需 1255 积分
UID帖子威望0 多玩草160 草
移动的网络白送都不要,不知道多烂
:联通用得少,占线不多。还阔以&
:这个跟带宽没关系,只要不全部占用带宽不会卡,是移动服务器的问题,他的慢是因为周围用移动的太多,&
&我100M联通表示8个手机加上电脑才50-80高峰90。。&
:联通的8M开个迅游加速器还可以&
&我100M的看电影可以,开网页有时候卡,玩游戏嘛,感谢移动让我离开坦克世界&
新人欢迎积分0 阅读权限70积分8841精华0UID帖子金钱29014 威望0
Lv.7, 积分 8841, 距离下一级还需 1159 积分
UID帖子威望0 多玩草500 草
唉,我现在用的是电信的,但是角色是北区的,现在玩的时候经常丢包,开加速器都不顶用。。。北区服务器也渣
:没啥用,迅游用过,UU用过,还有啥好的吗?&
&你换个加速器试试&
:可能是我们本地电信问题吧,因为迅游经常提示本地网络波动&
:反正我不知道因为啥,以前没这样,是不是因为版本问题也是一部分原因,往前几个版本还没这样频繁丢包&
&北区,我这里移动宽带北区比南区好多了,70左右&
&我也是电信
玩的北区 也没事 我还边下载(你懂的)边游戏&
:所以北区服务器渣是公认的-_-||&
&我也百兆电信玩网通区,有迅游80左右偶尔还丢包。&
:北区这几天大姨妈&
:也确实该换了,但是木有钱啊,用的笔记本,最低效,但是去网吧玩北区也卡啊←_←&
新人欢迎积分1 阅读权限40积分764精华0UID帖子金钱10306 威望0
Lv.4, 积分 764, 距离下一级还需 236 积分
UID帖子威望0 多玩草0 草
移动的网你也敢用
斯蒂芬森多少分随风倒额
。。。。。。
新人欢迎积分0 阅读权限50积分2286精华0UID帖子金钱4782 威望0
Lv.5, 积分 2286, 距离下一级还需 214 积分
UID帖子威望0 多玩草51 草
移动是什么,现在只认联通电信
这个人真NB啊,什么也没写!
陪你一起走到死
新人欢迎积分0 阅读权限50积分1053精华0UID帖子金钱2273 威望0
Lv.5, 积分 1053, 距离下一级还需 1447 积分
UID帖子威望0 多玩草0 草
电信100兆光纤,联通ping50上下。
新人欢迎积分0 阅读权限105积分43115精华0UID帖子金钱6022 威望1
Lv.11, 积分 43115, 距离下一级还需 19885 积分
UID帖子威望1 多玩草80 草
元宝专属一阶勋章。已绝版
手机论坛勋章
APP发帖双倍积分,登陆即送勋章!
365天!天天有你
连续签到1年即可获得
狗年新春勋章
参加2018狗年论坛相关APP活动有机会获得
APP3.0勋章
3.0APP3倍积分,登录就送勋章!
需要金钱:1100
手机盒子客户端点击或扫描下载
Powered by坦克世界 进游戏卡得半天不动 前面是40 200-400_百度知道
坦克世界 进游戏卡得半天不动 前面是40 200-400
这个系统能不能升级做成64位系统我玩坦克世界老是卡游戏提示内存不足!如果不是操作系统才32位的问题那就好处理了关键也不是不能玩,,进去卡半天才会动,,,人家都跑出去半个地图了...
这个系统能不能升级做成64位系统 我玩坦克世界老是卡 游戏提示 内存不足!如果 不是操作系统 才32位的问题 那就好处理了
关键也不是不能玩 ,,进去卡半天才会动,,,人家都跑出去半个地图了我才能动 你 懂的,,,哎
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
猫耳小受知道合伙人
来自娱乐休闲类芝麻团
采纳数:876
获赞数:2233
参与团队:
可以找修电脑的 重做64位系统,内存条换一个8G的,最好是加一块固态硬盘,游戏和系统都放在固态硬盘里,从此秒进图至于显卡和CPU不换
画质也就保持最低 流畅。左上角两个数字 一个是 FPS 也就是帧数,这个数字低于30 基本就幻灯片一张一张的了右边的PING
是网络延时,如果延时到了1000
说明你按动一下鼠标,服务器1秒以后才会有反应PING右边还有一个 绿点,如果绿点变红,说明你丢包(掉线)了
石哥笑了知道合伙人
擅长:暂未定制
换电脑吧,这电脑卖二手最多三百
你可以弄个新的了,我刚配了一个电脑,我可以帮你参谋参谋
主要是 这 他 妈
那。。。。我也是之前06年的电脑50块
买的 二手货
一共 300 块 人家说可以玩坦克世界我才要的,现在嘛 看看能不能 把他做成64位操作系统 如果能就再试试 ,,,,,哎06年的电脑 花了我5000多 放了8年没用 今天 想用了 买的这坑爹货进游戏还卡,
这电脑斗地主都卡
Joke丶小怀知道合伙人
Joke丶小怀
采纳数:12
擅长:暂未定制
太低了吧,你这配置玩游戏是不行的呀
能升级不?
不能叫升级,应该叫换硬件
或者换主机吧,这都已经过时了
大哥 我也是刚买的 ,不懂呀 看能不能重做64位的
换换显卡 加个2G 内存条 能玩坦克世界不???????
坦克世界的话,主板和cpu要换,显卡起码要2G,就算系统重做加内存条硬件也是要跟得上才行的,不然会烧机
小小二二三四三知道合伙人
小小二二三四三
采纳数:94
获赞数:171
擅长:暂未定制
我晕 这电脑几十年了?
起码也的i3处理器550显卡 你这配置太老了
换是可以换,我怎么觉得不是显卡 和处理器的问题呀,,是不是操作系统的问题???
其他1条回答
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。&figure&&img src=&https://pic3.zhimg.com/v2-1ce91ebeffe63c4b866c68f88579eaef_b.jpg& data-rawwidth=&582& data-rawheight=&187& class=&origin_image zh-lightbox-thumb& width=&582& data-original=&https://pic3.zhimg.com/v2-1ce91ebeffe63c4b866c68f88579eaef_r.jpg&&&/figure&&p&
本篇文章我的观点,部分来源于多年的项目实践,部分源自和以前同事的讨论,以及对一些系列文章和问答的阅读。&/p&&p&&b&
正文开始前,先做一些声明,因为这种类型的讨论,必然导致很多反对。我只表明我个人的意见,说一点我的思考实践,以及给出一些我看到的能支持我想法的论据。后续内容中,我可能对mvc或者当前的一些框架和设计方式提出一些批评,并不表明我是百分百坚定我的想法,也不表明我认为自己的想法绝对正确,做法最优。为了不在行文中,反复需要表明我的不坚定,导致文章难以阅读,故在此统一声明,希望不要引起无谓的纷争。&/b&&/p&&p&&b&
以下文章中,MVC泛指MVC,包括MVVM,MVP等MVC衍生的类似设计模式。&/b&&/p&&p&首先,我是用MVC的,在毕业早期开发应用软件类程序,对不同数据的不同展示方式MVC是很好的设计。或者说,一个M(数据),多种V(展示),是应用软件的常见展示方式,很适用MVC。大家在看Design pattern介绍MVC的时候,常用的例子,就是一个数据,即要饼状图展示,又要柱状图展示。&/p&&p&
后来,转行做页游,觉得当时的项目,完全没有什么设计,胡乱堆砌,乱成一团,想起了MVC等设计模式,并且,还有很多人推荐的PureMVC,Robotleg等类MVC框架,并使用了依赖注入等模式,学习了demo之后,觉得很好地解决了游戏设计问题。在跳槽后,在新的项目中,已经使用了robotleg,我进去后就很开心,开心地使用。真实地开发一段时间以后,我开始感觉到MVC或者说这类框架的问题(在和同事的讨论中,也得到了牛逼同事很多提点),或者说,是使用者带来的问题:&/p&&p&1,代码繁冗,当你阅读别人的代码,一个很简单的逻辑,被封装了多次,需要在多个代码文件中索引,阅读效率极低。代码文件分散,一些很简单的逻辑,例如按钮点击,都做了多层封装。&/p&&p&2,不太专业的某些程序的惰性,导致他们并不是真正理解MVC或者说这些框架的原理,他们的目标只是,把功能搞出来。他们要么绕过框架,穿插了很多调用,要么整体copy别人的一个功能,去掉逻辑,留下骨架,然后填充自己的逻辑,也不管这个骨架是否适用。这样的人,大大增加了项目的混乱,leader要做到充分的代码review,去除这些问题,在开发进度吃紧,每周都要出版本的情况下,是不可能的。这些快速堆出功能的程序员,反而得到策划等非技术人员的赞赏。而认真处理,把每一块都做好,但是慢一点的程序,反而不受夸奖,这导致了劣币驱逐良币。我相信,除了极少数精英团队,很多团队都有这样的问题。&/p&&p&3,这些设计和框架,被滥用。比如MVC也许适用于UI部分的设计,但是,他是否适用一个战斗模块呢?他是否适用一个剧情模块呢?有些团队,机械地运用某些框架,并不根据需求去思考,认为某个东西是好的,就到处使用。&/p&&p&
当一个项目规模增长,人员难以保证精英,积累了大量的需求变更,运营期间,需要快速的迭代。这种繁杂冗余的框架式设计,会导致代码难以维护。有时候,并不是某个框架不够好,更多的是,我们没有仔细理清它的适用范围,也难以保证规范从头到尾的坚定执行。并留下大量过分设计的繁杂代码,一个一百行,几个funtion就能解决的问题,被包装成了多个class,层层调用,写了几大百行,逻辑处处分散。&/p&&p&
那么,到底是某个框架,或者设计模式不行,还是我们使用得不够好呢?&/p&&p&
我们回到最初,仔细考虑,MVC解决的核心问题是,一个M,多个V,那么,在游戏领域,这样的需求多吗?是强需求吗?我们到底应该根据需求来设计框架,还是应该根据框架来填充需求?一个框架,一套设计,适用不同的游戏,不同的逻辑吗?&/p&&p&
我认真地考虑这块问题,发现很多教程,文章,他们介绍MVC,MVVM,介绍各种框架,包括uframe,StrangeIoC等,都缺少了思考和提问:&/p&&ul&&li&这个框架适用什么需求?解决了什么问题?&/li&&li&在什么情况下我该用,什么情况不该用?他带来了什么问题?&/li&&li&是否适合我的项目,我的团队?&/li&&li&我是应该项目整体使用,还是某些局部的需求使用呢?&/li&&/ul&&p&等等问题,才是我们该问的关键。&/p&&p&
我们游戏领域的技术,特别是游戏的框架,受到了太多应用软件,web开发,app开发的影响,但是,这些模式并不适用我们啊!正式因为web,app这些领域的通用性,需求的固定性(相对游戏开发而言),他们才会诞生出如此多的框架,模式,并且在技术领域,发出了更多的声音。出现了看似高级的设计方式。并且,web,app的项目周期,以及后续的维护周期是很长的,少则三两年,多则十几年,确实必须要谨慎设计。但是,我们游戏,特别是现在手游的生命周期又有多长呢?当需求不同,考虑问题的方式,解决问题的方式,应该做些改变。&/p&&p&想想《代码大全2》开篇说的是什么?隐喻,隐喻的重要性。这是全书的纲领啊,同志们。游戏开发,和web,app开发,能归为同一个隐喻吗? 那么我们问问自己:&/p&&ul&&li&TDD适用我们游戏前端开发吗?&/li&&li&WinForm的数据绑定,是适合我们游戏开发的吗?&/li&&li&几十个设计模式,有几个能适用我们游戏开发的呢?分别对应什么应用场景呢?&/li&&li&用Design pattern的目的,到底是design,还是去解决具体的问题?&/li&&/ul&&p&
当我们去追逐更新的设计,更酷的框架,我们有了解他们解决的问题吗?我们有自己了解过他的原理吗?到底在我们自己的项目中,他能解决什么问题?我们有仔细思考过他在我们游戏开发的整个生命周期,会给我们带来什么吗?&/p&&p&
最近,因为守望先锋的一个分享,ECS开始火了起来。有个群里看到说,我们下个项目要上ECS了,问是什么类型,答不知道,但是ECS这种先进框架,肯定要用。我只能说汗~~~&/p&&p&
静下心来,我也追求过最新的技术,最新的框架。但是,当我们真心开始做一个项目,去解决一些问题的时候,我们需要审慎。&/p&&p&
比如ECS,我觉得&a href=&https://link.zhihu.com/?target=https%3A//blog.codingnow.com/2017/06/overwatch_ecs.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&云风的说法&/a&,是最中肯的:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-6bc7abbac21caa1d0850_b.jpg& data-size=&normal& data-rawwidth=&737& data-rawheight=&87& class=&origin_image zh-lightbox-thumb& width=&737& data-original=&https://pic1.zhimg.com/v2-6bc7abbac21caa1d0850_r.jpg&&&figcaption&云风博客截图,地址https://blog.codingnow.com/2017/06/overwatch_ecs.html&/figcaption&&/figure&&p&
最终,我们要回到需求和问题,ECS,核心是为了解决网络同步中预测和预测失效的状态回滚问题。如果你不是需要解决这类问题,你确定需要上ECS?一个回合制游戏,确定需要ECS?UI写法从MVC改ECS?&/p&&p&
写到这里,说了那么多批评的话,那么,我认为什么是最好的设计方式呢?&/p&&p&
我认为,没有最好的,只有根据需求来的,根据团队能力来的,根据项目进度,经费来的,一切都要“具体问题,具体分析”。这句话,说出来轻松,做起来难,也有可能导致什么都做不好,代码更加混乱。那么,只能根据团队能力来选择一个合适的开发方式,没有最佳。&/p&&p&
从MVC开始,说了那么多,太多都是务虚的。但是,我认为务虚是很重要的,思考方式,方法论,都是很重要的。甚至,我们程序员学点哲学,也是大大有益。至少,读读笛卡尔的《谈谈方法》吧。&/p&&p&
我们需要经验慢慢积累,也需要慢慢对一些技术名词去媚,没有一招吃遍天。以下,我给出一些文章,也是一些我看到的,和我想法类似的东西,大家可以参看:&/p&&ul&&li&&a href=&https://link.zhihu.com/?target=https%3A//gamedev.stackexchange.com/questions/3426/why-are-mvc-tdd-not-employed-more-in-game-architecture& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Why are MVC & TDD not employed more in game architecture?&/a& &/li&&li&&a href=&https://link.zhihu.com/?target=https%3A//stackoverflow.com/questions/2210026/is-the-mvc-design-pattern-used-in-commercial-computer-games& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Is the MVC design pattern used in commercial computer games&/a& &/li&&/ul&&p&从第一篇能衍生出很多链接,都可以参看思考。&/p&&p&
最后,我言辞可能略激烈,原因大家请参考前面的声明。希望这篇务虚的思考和讨论,能带来一些不一样的声音。&/p&&p&-------------------------------------------------------------------------------------------&/p&&p&补充:&/p&&p&
看了评论区里的一些评论,我觉得,我必须要说明一下:我写这篇的目的,不是要告诉大家,设计不重要,框架不重要。我想明确的是:我们要仔细思考需求,来选择合适的技术方案,而不是用在一个死板地框架里硬套需求。能够审慎地选择合适的设计方案,不盲从跟风。&/p&&p&
但是,有些评论走向了另一个不看重设计的极端,情绪式的发泄,我认为是不妥的,更加有害的。本来,做任何一个设计,都需要试错,根据需求的变更重构和改进,这当然需要时间成本,但是,这是我们的重要的个人成长之路,至少说明一个程序是看重自己的代码的,重视自己的工作的。
大环境的问题,老板的问题,或者leader的问题,进度紧的问题,当然是存在的客观因素。但是这些客观因素,不代表我们不能努力把事情做好,不代表我们不需要为自己的成长负责。如果因为客观原因,混日子,随便堆砌代码,是对自己的不负责任吧。&/p&&p&
行业开发进度紧,加班多,是一个非常不好的状态,我对此也很不满(之前加班痛苦时,甚至yy要组织个程序工会,汗~~)。但是我相信没有一个人的工作是绝对长时间维持饱和的。我们总有时间聊聊qq,微信,上上网吧,那代表我们总有时间去思考怎么把事情做得更好,只是个人选择而已。&/p&&p&
一个好的程序,会考虑当前需求,会预估一些需求的变化,给自己留些余地,多少也会考虑,如果别人接手,是否能理顺这个逻辑,后续变更大了,还会考虑去重构整理。甚至会站在用户,玩家的角度,给策划一些建议。这当然是知易行难的,所以,人和人,才有了区分,同样的工作经验,有的一两年,就能做到很好,能独当一面,有的5,6年后,混成了老油条。&/p&&p&
总而言之,我这篇文章,是希望在认真对待工作和技术的情况下,更明智地思考和分析需求,选择合适的设计或者实现方案。&/p&&p&
虚无主义地吐槽,总是容易的。努力,总是伴随着困难。&/p&&p&
看,我也能写点鸡汤呢。&/p&
本篇文章我的观点,部分来源于多年的项目实践,部分源自和以前同事的讨论,以及对一些系列文章和问答的阅读。 正文开始前,先做一些声明,因为这种类型的讨论,必然导致很多反对。我只表明我个人的意见,说一点我的思考实践,以及给出一些我看到的能支持我…
&figure&&img src=&https://pic4.zhimg.com/v2-aa55d25b08f0264ead19_b.jpg& data-rawwidth=&403& data-rawheight=&266& class=&content_image& width=&403&&&/figure&&p&
终于要写帧同步这块了,这块很难讲清楚,细枝末节有很多优化点,也有一些不同的优化方向,根据不同项目类型,对操作手感的要求,对联机玩家的个数等,会有不同的难点和痛点。不同的优化方向,优化手法的差异,可能导致一些争论。并且,帧同步,本身也有很多变种,以应对不同的需求。所以,我一切都是基于我们的项目类型(ACT)来做的方案和优化,并不一定适合其它也需要帧同步的游戏,故在此提前说一下,以免引起一些不必要的误解。&/p&&p&
有些东西,可能会写得详细些,有些可能会简略些,不可能照顾到所有程度的读者,见谅。&/p&&h2&&b&帧同步的几个难点&/b&&/h2&&p&
帧同步的基础原理,以及和状态同步的区别,已经有很多文章介绍,我就不再赘述,大家可以自行google。以下只说几个难点。&/p&&ul&&li&&b&保证客户端独自计算的正确,即一致性&/b&&/li&&/ul&&p&
帧同步的基础,是不同的客户端,基于相同的操作指令顺序,各自执行逻辑,能得到相同的效果。就如大家所知道的,在unity下,不同的调用顺序,时序,浮点数计算的偏差,容器的排序不确定性,coroutine内写逻辑带来的不确定性,物理浮点数,随机数值带来的不确定性等等。&/p&&p&
有些比较好解决,比如随机数值,只需要做随机种子即可。&/p&&p&
有些注意代码规范,比如在帧同步的战斗中,逻辑部分不使用Coroutine,不依赖类似Dictionary等不确定顺序的容器的循环等。&/p&&p&
还有最基础的,要通过一个统一的逻辑tick入口,来更新整个战斗逻辑,而不是每个逻辑自己去Update。保证每次tick都从上到下,每次执行的顺序一致。&/p&&p&
物理方面,因为我们战斗逻辑不需要物理,碰撞都是自己做的碰撞逻辑,所以,跳过不说,这块可以参考别的文章。&/p&&p&
最后,说一下,浮点数计算无法保证一致性,我们需要转换为定点数。关于定点数的实现,比较简单的方式是,在原来浮点数的基础上乘,对应地方除以,这种做法最为简单,再辅以三角函数查表,能解决一些问题,减少计算不一致的概率,但是,这种做法是治标不治本的方式,存在一些隐患(举个例子,例如一个int和一个float做乘法,如果原数值就要*1000,那最后算出来的数值,可能会非常大,有越界的风险。)。&/p&&p&
最佳的解决办法,是使用实现更加精确和严谨,并经过验证的定点数数学库,在c#上,有一个定点数的实现,&a href=&http://link.zhihu.com/?target=https%3A//www.photonengine.com/en-US/Photon& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Photon网络&/a&的早期版本,&a href=&http://link.zhihu.com/?target=https%3A//github.com/suzuke/TrueSync/tree/master/Assets/TrueSync/Engine/Math& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Truesync有一个很不错的定点数实现&/a&。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-54df1a2a2c4db77fdab09e9_b.jpg& data-size=&normal& data-rawwidth=&669& data-rawheight=&852& class=&origin_image zh-lightbox-thumb& width=&669& data-original=&https://pic2.zhimg.com/v2-54df1a2a2c4db77fdab09e9_r.jpg&&&figcaption&定点数的实现&/figcaption&&/figure&&p&
其中FP,就可以完全代替float,我们只需要将我们自己的逻辑部分,float等改造为FP,就可以轻松解决。并且,能够很好的和我们protobuf的序列化方式集成(注意代码中的Attribute,如下图),保证我们的配置文件,也是定点数的。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-ae47c66a1dbb7ce73207c7_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&437& data-rawheight=&383& class=&origin_image zh-lightbox-thumb& width=&437& data-original=&https://pic4.zhimg.com/v2-ae47c66a1dbb7ce73207c7_r.jpg&&&/figure&&p&TSVector对应Vector3,只要基于FP,可以自己扩展自己的数据结构。(当然,如果用到了复杂的插件,并且不开源,那么对于定点数的改造,就会困难很多)&/p&&figure&&img src=&https://pic3.zhimg.com/v2-de61f21d96bf38aad9a499ee30becd42_b.jpg& data-size=&normal& data-rawwidth=&973& data-rawheight=&288& class=&origin_image zh-lightbox-thumb& width=&973& data-original=&https://pic3.zhimg.com/v2-de61f21d96bf38aad9a499ee30becd42_r.jpg&&&figcaption&三角函数通过查表方式实现,保证了定点数的准确&/figcaption&&/figure&&p&我个人认为,这一套的实现,是优于简单的乘10000,除10000的方式。带来的坏处,可能就是计算性能略差一点点,但是我们大量测试下来,对计算性能的影响很小,应该是能胜任绝大部分项目的需求。&/p&&p&
对于计算的不确定性,我们也有一些小的隐患,就是,我们用到了Physics.Raycast来检测地面和围墙,让人物可以上下坡,走楼梯等高低不平的路,也可以有形状不规则的墙。这里会获得一个浮点数的位置,可能会导致不确定性,这里,我们用了数值截断等方式,尽量规避,经过反复测试,没有出现过不一致。但是这种方式,毕竟在逻辑上,存在隐患,更好的方式,是实现一套基于定点数的raycast机制,我们人力有限,就没时间精力去做了。这块,有篇文章讲得更细致一些,大家可以参看 &a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&帧同步:浮点精度测试&/a&。&/p&&ul&&li&&b&帧同步网络协议的实现&/b&&/li&&/ul&&p&在处理好了基础的计算一致性问题后,我们就要考虑网络如何通信。这里,我不谈p2p方式了,我们以下谈的,都是多client,一个server的模式,server负责统一tick,并转发client的指令,通知其他client,可以参看文章&a href=&http://link.zhihu.com/?target=http%3A//www.10tiao.com/html/255/.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网游流畅基础:帧同步游戏开发&/a&。&/p&&p&首先,是网络协议的选择。TCP和UDP的选择,我就不多说了,帧同步肯定要基于UDP才能保证更低的延迟。在UDP的选择上,我看网上有些文章,容易导入一个误区,即,我们是要用可靠传输的UDP,还是冗余信息的UDP。&/p&&p&&b&基于可靠传输的UDP&/b&,是指在UDP上加一层封装,自己去实现丢包处理,消息序列,重传等类似TCP的消息处理方式,保证上层逻辑在处理数据包的时候,不需要考虑包的顺序,丢包等。类似的实现有Enet,KCP等。&/p&&p&&b&冗余信息的UDP&/b&,是指需要上层逻辑自己处理丢包,乱序,重传等问题,底层直接用原始的UDP,或者用类似Enet的Unsequenced模式。常见的处理方式,就是两端的消息里面,带有确认帧信息,比如客户端(C)通知服务器(S)第100帧的数据,S收到后通知C,已收到C的第100帧,如果C一直没收到S的通知(丢包,乱序等原因),就会继续发送第100帧的数据给S,直到收到S的确认信息。&/p&&p&
有些文章介绍的时候,没有明确这两者的区别,但是这两种方式,区别是巨大的。可靠传输的UDP,在帧同步中,个人认为是不合适的,因为他为了保证包的顺序和处理丢包重传等,在网络不佳的情况下,delay很大,将导致收发包处理都会变成类似tcp的效果,只是比TCP会好一些。必须要用冗余信息的UDP的方式,才能获得好的效果。并且实现并不复杂,只要和服务器商议好确认帧和如何重传即可,自己实现,有很大的优化空间。例如,我们的协议定义类似如下:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-a79eca856ce184fd70cd80d_b.jpg& data-size=&normal& data-rawwidth=&607& data-rawheight=&499& class=&origin_image zh-lightbox-thumb& width=&607& data-original=&https://pic2.zhimg.com/v2-a79eca856ce184fd70cd80d_r.jpg&&&figcaption&双方都要通知对方,已经接受哪一帧的通知了,并通过cmd list重发没有收到的指令&/figcaption&&/figure&&p&这里简单说一下,对于这种收发频繁的消息,如果使用protobuf,会造成每个逻辑帧的GC,这是非常不好的,解决方案,要么对&a href=&http://link.zhihu.com/?target=https%3A//www.cnblogs.com/SChivas/p/7898166.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&protobuf做无GC改造&/a&,要么就自己实现一个简单的byte[]读写。无GC改造工程太大,感觉无必要,我们只是在战斗的几个频繁发送的消息,需要自己处理一下byte[]读写即可。&/p&&p&-----------------------------------&/p&&p&此处补充一下,看到KCP作者&a href=&https://www.zhihu.com/people/skywind3000/activities& class=&internal&&韦易笑&/a&在评论区的留言,提到&a href=&http://link.zhihu.com/?target=https%3A//github.com/skywind3000/kcp/wiki/Network-Layer& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&kcp+fec的模式&/a&,可以比冗余方式,有更好的效果,我之前并没有仔细研究过这个模式,不过可以推荐大家看一下,如果有用过朋友分享下结论就更好了。&/p&&p&因为我们项目早期,服务器定下了使用enet,我评估了一下,反正使用冗余包的方式,所以没有纠结enet或kcp,后续其实想改成kcp,服务器不想再动,也就放下了。&/p&&p&enet麻烦的地方是,&a href=&http://link.zhihu.com/?target=https%3A//github.com/lsalzman/enet/pull/73& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&enet的ipv6版本&/a&,是一个不成熟的pull request,enet作者没有merge(并且存在好几个ipv6的pull request),我不确定稳定性,还好看了下commit,加上测试下来,没有太大问题。KCP我没有评估过ipv6的问题,不过github上有C#版本,改一下ipv6支持应该很简单。&/p&&p&------------------------------------&/p&&ul&&li&&b&逻辑和显示的分离&/b&&/li&&/ul&&p&这块很多讲帧同步的文章都提过了。我在前面讲&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&技能编辑器&/a&的时候,也提过,配置的数据和显示要分离,在战斗中,战斗的逻辑,也要和显示做到分离。&/p&&p&
例如,最基本,我们动作切换的逻辑,是基于自己抽象的逻辑帧,而不是基于animator中一个clip的播放。比如一个攻击动作,当第10帧的时候,开始出现攻击框,并开始检测和敌人受击框的碰撞,这个时候的第10帧,必须是独立的逻辑,不能依赖于animator播放的时间,或者AnimatorStateInfo的normalizedTime等。甚至,当我们不加载角色的模型,一样可以跑战斗的逻辑。如果抽离得好,还可以放到服务器跑,做为战斗的验证程序,王者荣耀就是这样做的。&/p&&ul&&li&&b&联机如何做到流畅战斗&/b&&/li&&/ul&&p&
前面所有的准备,最终的目的,都是为了战斗的流畅。特别是我们这种Act游戏,或者格斗类游戏,对按键以后操作反馈的即时性,要求非常高,一点点延迟,都会影响玩家的手感,导致玩家的连招操作打断,非常影响体验。我们对延迟的敏感性,甚至比MOBA类游戏还要高,我们要做到好的操作手感,还要联机战斗(PVP,组队PVE),都需要把帧同步做到极致,不能因为延迟卡住或者操作反馈出现变化。&/p&&p&
因为这个原因,我们不能用lockstep的方式,lockstep更适合网络环境良好的内网,或者对操作延迟不敏感的类型(例如我听过还有项目用来做卡牌类的帧同步)。&/p&&p&
我们也不能用缓存服务器确认操作的方式,也就是一些游戏做的指令buffer。具体描述,&a href=&http://link.zhihu.com/?target=http%3A//youxiputao.com/articles/11842& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&王者荣耀的分析文章&/a&,讲得很具体了。这也是他们说的模式,这个模式能解决一些小的网络波动,对一些操作反馈不需要太高的游戏,例如有些游戏攻击前会有一个比较长的前摇动作,这类游戏,用这种方式,应该就能解决大部分问题。但是这种方式还是存在隐患,即使通过策略能很好地动态调整buffer,也还是难以解决高延迟下的卡顿和不流畅。王者荣耀优化得很好,他们说能让buffer长度为0,文章只提到通过平滑插值和逻辑表现分离来优化,更细节的没有提到,我不确定他们是否只是基于这个方式来优化的。目前也没有看到更具体的分析。&/p&&p&
指令buffer的方式,也不能满足我们的需求,或者说,我没有找到基于此方式,能优化到王者荣耀的效果的办法。我也测试过其他moba和act,arpg类游戏的联机,在高延迟,网络波动情况下,没有比王者表现更好的了。&/p&&p&
最后,在仔细研究了我们的需求后,找到一篇指导性的文章,非常适合我们。&/p&&p&
就是&a href=&http://link.zhihu.com/?target=http%3A//mauve.mizuumi.net//understanding-fighting-game-networking/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Understanding Fighting Game Networking&/a&,这篇文章非常详细地介绍了各种方式,最终回滚逻辑(rollback)是终极的解决方案,国内也有文章提到过,即&a href=&http://link.zhihu.com/?target=http%3A//www.skywind.me/blog/archives/1343%23more-1343& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Skywind Inside & 再谈网游同步技术&/a&里面提到的Time Warp方式,我理解回滚逻辑,和Time Warp是一个概念。&/p&&ul&&li&&b&游戏逻辑的回滚&/b&&/li&&/ul&&p&
回滚逻辑,就是我们解决问题的方案。可以这样理解,客户端的时间,领先服务器,客户端不需要服务器确认帧返回才执行指令,而是玩家输入,立刻执行(其他玩家的输入,按照其最近一个输入做预测,或者其他更优化的预测方案),然后将指令发送给服务器,服务器收到后给客户端确认,客户端收到确认后,如果服务确认的操作,和之前执行的一样(自己和其他玩家预测的操作),将不做任何改变,如果不一样(预测错误),就会将游戏整体逻辑回滚到最后一次服务器确认的正确帧,然后再追上当前客户端的帧。&/p&&p&
此处逻辑较为复杂,我尝试举个例子说明下。&/p&&p&
当前客户端(A,B)执行到100帧,服务器执行到97帧。在100帧的时候,A执行了移动,B执行了攻击,A和B都通知服务器:我已经执行到100帧,我的操作是移动(A),攻击(B)。服务器在自己的98帧或99帧收到了A,B的消息,存在对应帧的操作数据中,等服务器执行到100帧的时候(或提前),将这个数据广播给AB。&/p&&p&
然后A和B立刻开始执行100帧,A执行移动,预测B不执行操作。而B执行攻击,预测A执行攻击(可能A的99帧也是攻击),A和B各自预测对方的操作。&/p&&p&
在A和B执行完100帧后,他们会各自保存100帧的状态快照,以及100帧各自的操作(包括预测的操作),以备万一预测错误,做逻辑回滚。&/p&&p&
执行几帧后,A,B来到了103帧,服务器到了100帧,他开始广播数据给AB,在一定延迟后,AB收到了服务器确认的100帧的数据,这时候,AB可能已经执行到104了。A和B各自去核对服务器的数据和自己预测的数据是否相同。例如A核对后,100帧的操作,和自己预测的一样,A不做任何处理,继续往前。而B核对后,发现在100帧,B对A的预测,和服务器确认的A的操作,是不一样的(B预测的是攻击,而实际A的操作是移动),B就回滚到上一个确认一样的帧,即99帧,然后根据确认的100帧操作去执行100帧,然后快速执行101~103的帧逻辑,之后继续执行104帧,其中(101~104)还是预测的逻辑帧。&/p&&p&
因为客户端对当前操作的立刻执行,这个操作手感,是完全和pve(不联网状态)是一样的,不存在任何delay。所以,能做到绝佳的操作手感。当预测不一样的时候,做逻辑回滚,快速追回当前操作。&/p&&p&
这样,对于网络好的玩家,和网络不好的玩家,都不会互相影响,不会像lockstep一样,网络好的玩家,会被网络不好的玩家lock住。也不会被网络延迟lock住,客户端可以一直往前预测。&/p&&p&
对于网络好的玩家(A),可以动态调整(根据动态的latency),让客户端领先服务器少一些,尽量减少预测量,就会尽量减少回滚,例如网络好的,可能客户端只领先2~3帧。&/p&&p&
对于网络不好的玩家(B),动态调整,领先服务器多一些,根据latency调整,例如领先5帧。&/p&&p&
那么,A可能预测错的情况,只有2~3帧,而网络不好的B,可能预测错误的帧有5帧。通过优化的预测技术,和消息通知的优化,可以进一步减少A和B的预测错误率。对于A而言,战斗是顺畅的,手感很好,少数情况的回滚,优化好了,并不会带来卡顿和延迟感。&/p&&p&
重点优化的是B,即网络不好的玩家,他的操作体验。因为客户端不等待服务器确认,就执行操作,所以B的操作手感,和A是一致的,区别只在于,B因为延迟,预测了比较多的帧,可能导致预测错,回滚会多一些。比如按照B的预测,应该在100帧击中A,但是因为预测错误A的操作,回滚重新执行后,B可能在100帧不会击中A。这对于B来说,通过插值和一些平滑方式,B的感受是不会有太大区别的,因为B看自己,操作自己都是及时反馈的,他感觉自己是平滑的。&/p&&p&
这种方式,保证了网络不好的B的操作手感,和A一致。回滚导致的一些轻微的抖动,都是B看A的抖动,通过优化(插值,平滑等),进一步减少这些后,B的感受是很好的。我们测试在200~300毫秒随机延迟的情况下,B的操作手感良好。&/p&&p&
这里,客户端提前服务器的方式,并且在延迟增大的情况下,客户端将加速,和&a href=&http://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/cOGn8-rHWLIxdDz-R3pXDg& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&守望先锋的处理方式&/a&是一样的。当然,他们肯定比我做得好很多。&/p&&p&
希望我已经大致讲清楚了这个逻辑,大家参看几篇链接的文章,能体会更深。&/p&&p&
这里,我要强调的一点是,我们这里的预测执行,是真实逻辑的预测,和很多介绍帧同步文章提到的预测是不同的。有些文章介绍的预测执行,只是view层面的预测,例如前摇动作和位移,但是逻辑是不会提前执行的,还是要等服务器的返回。这两种预测执行(View的预测执行,和真实逻辑的预测执行)是完全不是一个概念的,这里需要仔细地区分。&/p&&p&
这里有很多的可以优化的点,我就不一一介绍了,以后可能零散地再谈。&/p&&ul&&li&&b&游戏逻辑的快照(snapshot)&/b&&/li&&/ul&&p&我们的逻辑之所以能回滚,都是基于对每一帧状态可以处理快照,存储下每一帧的状态,并可以回滚到任何一帧的状态。在&a href=&http://link.zhihu.com/?target=http%3A//mauve.mizuumi.net//understanding-fighting-game-networking/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Understanding Fighting Game Networking&/a& 文章和&a href=&http://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/cOGn8-rHWLIxdDz-R3pXDg& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&守望先锋网络&/a& 文章中,都一笔带过了快照的说明。他们说的快照,可能略有不同,但是思路,都是能保存下每一帧的状态。如果去处理快照(Understanding那篇文章做的是模拟器游戏,可以方便地以内存快照的方式来做),是一个难点,这也是我&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&前面文章&/a&提到ECS在这个方式下的应用,云风的解释:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-dd9ed3cab5_b.jpg& data-size=&normal& data-rawwidth=&737& data-rawheight=&87& class=&origin_image zh-lightbox-thumb& width=&737& data-original=&https://pic2.zhimg.com/v2-dd9ed3cab5_r.jpg&&&figcaption&云风博客截图,地址https://blog.codingnow.com/2017/06/overwatch_ecs.html&/figcaption&&/figure&&p&ECS是一个好的处理方式,并且我找到&a href=&http://link.zhihu.com/?target=https%3A//www.kisence.com//guan-yu-zheng-tong-bu-de-xie-xin-de/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&一篇文章&/a&,也这样做了(我看过他开源的demo,做得还不够好,应该还是demo阶段,不太像是一个成型的项目)。这篇文章的思路是很清晰的,并且也点到了一些实实在在的痛点,解决思路也基本是正确的,可以参看。&/p&&p&这块,我做得比较早了,当时守望先锋的文章还没出,我的战斗也没有基于ECS,所以,在处理快照上,只有自己理顺逻辑来做了。&/p&&p&我的思路是,通过一个回滚接口,需要数据回滚的部分,实现接口,各自处理自己的保存快照和回滚。就像我们序列化一个复杂的配置,每个配置各自序列化自己的部分,最终合并成一个序列化好的文件。&/p&&p&首先,定义接口,和快照数据的reader和writer&/p&&figure&&img src=&https://pic2.zhimg.com/v2-c12b7e87d2f452b29fdef61_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&388& data-rawheight=&185& class=&content_image& width=&388&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-b666f214abd2a804ebcc119b_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&407& data-rawheight=&499& class=&content_image& width=&407&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-2f49a68d6fdbdf3ffdfb283_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&470& data-rawheight=&483& class=&origin_image zh-lightbox-thumb& width=&470& data-original=&https://pic4.zhimg.com/v2-2f49a68d6fdbdf3ffdfb283_r.jpg&&&/figure&&p&然后,就是每个模块,自己去处理自己的takeSnapshot和rollback,例如:&/p&&figure&&img src=&https://pic2.zhimg.com/v2-96bbeff404d_b.jpg& data-size=&normal& data-rawwidth=&400& data-rawheight=&254& class=&content_image& width=&400&&&figcaption&简单的数值回滚&/figcaption&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-eeec5b5d8e7e663a8e06f487_b.jpg& data-size=&normal& data-rawwidth=&700& data-rawheight=&597& class=&origin_image zh-lightbox-thumb& width=&700& data-original=&https://pic4.zhimg.com/v2-eeec5b5d8e7e663a8e06f487_r.jpg&&&figcaption&复制的列表回滚和调用子模块回滚&/figcaption&&/figure&&p&思路理顺以后,就可以很方便地处理了,注意write和read的顺序,注意处理好list,就解决了大部分问题。当然,在实现逻辑的过程中,时刻要注意,一个模块如何回滚(例如获取随机数也需要回滚)。&/p&&p&有一个更简单的方式,就是给属性打Attribute,然后写通用的方法。例如,我早&b&期的实现方案&/b&:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-05fee97a51c743b54d8dcaf_b.jpg& data-size=&normal& data-rawwidth=&471& data-rawheight=&340& class=&origin_image zh-lightbox-thumb& width=&471& data-original=&https://pic4.zhimg.com/v2-05fee97a51c743b54d8dcaf_r.jpg&&&figcaption&给属性打标签&/figcaption&&/figure&&p&根据标签,通用的读写方法,通过反射来读写,就不需要每个模块自己去实现自己的方法了:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-c2adc282fe621f2357e3_b.jpg& data-size=&normal& data-rawwidth=&649& data-rawheight=&375& class=&origin_image zh-lightbox-thumb& width=&649& data-original=&https://pic4.zhimg.com/v2-c2adc282fe621f2357e3_r.jpg&&&figcaption&部分代码&/figcaption&&/figure&&p&这种方法,能很好地解决大部分问题,甚至前面提到的&a href=&http://link.zhihu.com/?target=https%3A//github.com/suzuke/TrueSync/tree/master/Assets/TrueSync/Engine/Math& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Truesync&/a&,也是用的这种方式来做。&/p&&p&但是这种方法有个难以回避的问题,就是GC,因为基于反射,当我们调用field的GetValue和SetValue的时候,GC难以避免。并且,因为全自动,不方便处理一些特殊逻辑,调试优化也不方便,最后改成了现有的方式,虽然看起来笨重一些,但是可控性更强,我后续做的很多优化,都方便很多。&/p&&p&关于快照,也有很多可以优化的点,无论是GC内存上的,还是运行效率上的,都需要优化好,否则,可能带来性能问题。这块优化,有空另辟文章再细谈吧。&/p&&p&当我们有了快照,就可以支持回滚,甚至跳转。例如我们要看战斗录像,如果没有快照,我们要跳到1000帧,就需要从第一帧,根据保存的操作指令,一直快速执行到1000帧,而有了快照,可以直接跳到1000帧,不需要执行中间的过程,如果需要在不同的帧之间切换,只需要跳转即可,这将带来巨大的帮助。&/p&&ul&&li&&b&自动测试&/b&&/li&&/ul&&p&由于帧同步需要测试一致性的问题,对我们来说,回滚也是需要大量测试的问题。自动测试是必须要做的一步,这块没有什么特别的点,主要就是保存好操作,快照,log,然后对不同客户端的数据做比对,找到不同的地方,查错改正。&/p&&p&我们现在做到,一步操作,自动循环战斗,将每一盘战斗数据上传内网log服务器。&/p&&p&当有很多盘战斗的数据后,通过工具自动解析比对数据,找到不同步的点。也是还可以优化得更好,只是现在感觉已经够用了。经过大量的内部自动测试,目前战斗的一致性,是很好的。&/p&&ul&&li&&b&总结&/b&&/li&&/ul&&p&我们现在的帧同步方案,总结下来,就是预测,快照,回滚。当把这些有机地结合起来,优化好,就有了非常不错的帧同步联网效果,无论网络速度如何,只要不是延迟大到变态,都保证了非常好的操作手感。&/p&&p&快照回滚的方式,也不是所有游戏都适用,例如&a href=&http://link.zhihu.com/?target=http%3A//www.skywind.me/blog/archives/1343%23more-1343& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Skywind Inside & 再谈网游同步技术&/a&文章中对此模式(Time warp或Rollback)的缺点,也说明了。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-fb6abdadfb1ce4ce31ec6_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&651& data-rawheight=&106& class=&origin_image zh-lightbox-thumb& width=&651& data-original=&https://pic3.zhimg.com/v2-fb6abdadfb1ce4ce31ec6_r.jpg&&&/figure&&p&如图所述,这种模式不适合太多人的联网玩法,例如MOBA,可能就不太适用。我们最多三人联机,目前优化测试下来,效果也没有太大问题。但是联机人数越多,预测操作的错误可能性越大,导致的回滚也会越多。&/p&&p&&br&&/p&&p&一篇文章,难以讲得面面俱到,很多地方可能描述也不一定明确,并且,个人能力有限,团队人员有限(3个客户端)的情况下,必定有很多设计实现不够好的地方,大家见谅。后续有空,再补充一些细节和优化等,这里同样是希望抛砖引玉,希望看到更多好的方案。&/p&&p&最后,也要感谢我们项目的服务器哥们的技术支持和帮助。&/p&&p&一些有帮助的文章再列一下:&/p&&ul&&li&&a href=&http://link.zhihu.com/?target=http%3A//mauve.mizuumi.net//understanding-fighting-game-networking/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Understanding Fighting Game Networking&/a& &/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//www.skywind.me/blog/archives/1343%23more-1343& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Skywind Inside & 再谈网游同步技术&/a& &/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/cOGn8-rHWLIxdDz-R3pXDg& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《守望先锋》回放技术:阵亡镜头、全场最佳和亮眼表现&/a& &/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//youxiputao.com/articles/11842& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&《王者荣耀》技术总监复盘回炉历程&/a& &/li&&li&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&帧同步:浮点精度测试&/a&&/li&&li&&a href=&http://link.zhihu.com/?target=https%3A//www.gamereplays.org/overwatch/portals.php%3Fshow%3Dpage%26name%3Doverwatch-a-guide-to-understanding-netcode& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&A guide to understanding netcode&/a& &/li&&li&&a href=&http://link.zhihu.com/?target=http%3A//www.10tiao.com/html/255/.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网游流畅基础:帧同步游戏开发&/a& &/li&&/ul&&p&最后啰嗦一句,如最开始所述,帧同步有很多变种和实现方式,优化方向。有时候,可能不同文章提到帧同步这个术语的时候,里面的意思,可能都有区别,大家需要仔细理清和区分。&/p&
终于要写帧同步这块了,这块很难讲清楚,细枝末节有很多优化点,也有一些不同的优化方向,根据不同项目类型,对操作手感的要求,对联机玩家的个数等,会有不同的难点和痛点。不同的优化方向,优化手法的差异,可能导致一些争论。并且,帧同步,本身也有很多…
&p&在中国的游戏环境下,反挂已经成为了游戏开发的重中之重,甚至能决定一款游戏的生死,吃鸡就是一个典型的案例。&br&&br&目前参与了了一款动作射击的MOBA类游戏的开发,同步方案上选择了帧同步技术(LockStep而非snapshots以下同)。那么就有很多人担心起来,客户端会跑全部逻辑帧同步该如何反外挂,和状态同步有什么区别呢?&br&&br&首先我们来分析一下手游的风险和外挂的分类,这里推荐腾讯游戏安全中心的文章,有着非常详细深入的介绍。&br&手游的风险:&br& o 静态修改文件:将游戏解包修改资源 ,配置,代码等之后再重新打包&br&
○ 修改资源,例如替换游戏的贴图做广告,修改玩家碰撞资源 或删除部分关键资源使玩家可以作弊等&br&
○ 修改代码,直接修改游戏代码,实现无敌,免CD,无限伤害等等&br&
○ 修改配置,修改策划配表等&br& o 动态篡改逻辑:通过注入和钩子的方式,在游戏运行时修改游戏代码,修改游戏内存等&br&
○ 修改代码,运行时注入进程直接修改游戏代码或者钩住关键逻辑函数修改逻辑,实现无敌,免CD,无限伤害等等&br&
○ 修改内存,例如烧饼,葫芦侠等修改器,在游戏运行时修改堆栈和全局变量等&br& o 游戏协议&br&
○ 篡改游戏协议,直接修改协议的内容,修改结算结果,修改伤害数值,修改血量等等&br&
○ 重复游戏协议,例如多次重复伤害协议&br& o 其他,按键精灵。脚本宏,盗号,恶意发言,打金工作室等,这些和同步技术无关,暂不做详细讨论&br&&br&外挂的分类 :&br&&/p&&figure&&img data-rawheight=&332& src=&https://pic4.zhimg.com/v2-4bdc7289acd48b9f18e404_b.jpg& data-size=&normal& data-rawwidth=&642& class=&origin_image zh-lightbox-thumb& width=&642& data-original=&https://pic4.zhimg.com/v2-4bdc7289acd48b9f18e404_r.jpg&&&/figure&&p&&a href=&https://link.zhihu.com/?target=http%3A//gslab.qq.com/portal.php%3Fmod%3Dview%26aid%3D94& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&摘自腾讯游戏安全实验室&/a&&br&&br&从上文可以看出外挂的主要方式还是修改客户端的资源,代码,和内存。因此反外挂的手段也不外乎以下几种:&br& o 服务器计算关键逻辑。例如一些MMO战斗逻辑泡在服务端&br& o 服务器验证客户端逻辑。包括通过完整战斗逻辑验证和数值范围验证,例如早期的酷跑(可能误杀牛逼的玩家)&br& o 包体加密加签名加验证,防止破解包体。例如一些第三方加固,Unity的MonoDll加密,代码混淆等&br& o 加密本地保存的一些文件。例如对加密PlayerPrefs文件&br& o 加密和扰动运行时内存中关键数据(例如血量数据等)。例如崩3等&br& o 防注入检测(杀死注入进程或者发现注入之后杀死自己)&br& o 虚拟机加密&br& o 加速检测,防止修改本地时间的变速齿轮&br& o 穿墙检测,客户端对关键碰撞做校验&br& o 集成守护进程以及守护进程的自我加密更新&br& o 鼠标宏,按键精灵等进程检测,防止玩家使用这些工具&br& o 增加举报系统查证封号&br& o 通过暴力机关严厉打击外挂制作者(个人感觉非常有效)&br& o 其他&br&&br&但很遗憾,因为理论上再牛逼的客户端也是可以破解的,所以客户端的东西都是不可信任的。就像市面上也有很多第三方的加固工具,反作弊插件等,但不管用什么eye,什么火眼精睛,该作弊的还是作弊。因此反外挂的核心还是在于是否服务器是否计算了关键逻辑,就像Unreal老大说的The Server Is The Man。而和同步技术和客户端是否跑完整逻辑关系不大(严格说是有一点关系)。不管是状态同步还是帧同步,只要做到了服务器有完整逻辑并验证,绝大部分外挂都可以防掉(例如锁血挂,穿墙挂,加速挂等)。&br&&br&对于状态同步来说关键逻辑在服务器的比重越高反外挂就越完美。最极端的例子就是就是云游戏,服务器计算所有逻辑和画面,客户端只是显示图像,基本上杜绝了所有其他外挂(除了按键精灵,鼠标宏,手速挂等可以模拟玩家操作,捕捉像素计算操作,只能通过进程检测,举报,法律打击等其他方案)。&br&&br&而对于帧同步来说,我们同样可以在服务器验证完整的战斗逻辑。一般分为两种:&br& 1. 实时验证。例如战斗实时运行战斗逻辑和客户端不断同步验证关键数据的hash,和状态同步类似。但这种方案服务器负载较高,运维成本高昂;&br& 2. 离线验证。这是帧同步的优势,战斗结束后服务器收集整场的操作序列,然后加速播放战斗(几十上百倍),最后校验结果,例如刀塔传奇。这个好处是服务器不用实时跑战斗,只需在结束时花几百ms即可验证一场战斗,大幅降低服务器成本。&br&如果是这种验证方式帧同步也一样能防掉绝大部分外挂,但是会多一个弱点就是全图挂。因为客户端有了所有玩家的位置信息,所以无法防掉全图挂。&br&&br&那么如果这么说,只要服务器跑逻辑就行了,为什么外挂还这么泛滥呢?其实因为种种原因很多游戏服务器并没有完整的逻辑和校验,对于绝大部分游戏使用状态同步来说有以下一些原因:&br& 1. 性能问题。服务器运行完整逻辑开销很高(特别是一些复杂运算,例如物理弹道等),因此将部分逻辑放在客户端分布运算&br& 2. 因为开发效率和开发能力的限制。例如开发技能,如果所有逻辑都在客户端开发就会简单很多,响应也非常及时。如果要涉及服务器和客户端同步,就会多很多工作量特别是一些位移技能,很多逻辑可能还要写两份(帧同步更高效更容易实现打击感也是这个原因,很多动作游戏,MOBA游戏也会选择帧同步)&br& 3. 经验问题。一些公司在反外挂上经验不足重视程度不够,特别是国外游戏环境较好法律健全&br& 4. 为了极致的体验。例如为了降低网络延迟,很多游戏会让客户端预表现和加入延迟补偿,在一定范围内信任客户端(特别是FPS游戏,状态同步在延迟感上有较优势)&br& 5. 为了弱网体验。为了让玩家在网络极差甚至断线的情况下也能玩,将绝大部分逻辑都放在客户端&br& 6. 多种原因混合,其他一些个别问题。&br&&br&但是以上的问题对于帧同步来说不也一样吗?如果为了成本和快速开发,服务器不跑逻辑不也一样抓瞎吗?其实帧同步会更简单一些。对帧同步来说有以下几种情况:&br&1.基于RelayServer多人PVP。这种会相对简单很多,因为每个客户端都计算了完整逻辑,作弊玩家修改的只是本地数据无法影响其他玩家,只能自嗨。最终结果服务器只要简单的比较投票就可以找到作弊者,除非作弊的玩家多余非作弊的玩家并且作弊玩家还要修改一样的数据(有点比特币算力的意思:),另外也可以在游戏运行时不断生成关键数据的hash码,随时校验;&br&2.基于P2P的多人PVP。和RS差不多但是无法防主机作弊了,参考魔兽争霸,但网游基本不会使用;&br&3.双人PVP和单机。这就没办法了,只能服务器做校验;&br&&br&综上所述,因为天然的客户端强一致性,总体来说帧同步在防外挂上甚至会更简单一些(参考王者荣耀)。但成也萧何败也萧何,正因为这个机制的问题,无法完全防住全图挂,也因此甚至有MOBA游戏,同时使用两种同步机制来保证线上赛和线下赛的公平和体验。&/p&
在中国的游戏环境下,反挂已经成为了游戏开发的重中之重,甚至能决定一款游戏的生死,吃鸡就是一个典型的案例。 目前参与了了一款动作射击的MOBA类游戏的开发,同步方案上选择了帧同步技术(LockStep而非snapshots以下同)。那么就有很多人担心起来,客户端…
&figure&&img src=&https://pic1.zhimg.com/v2-ccbd13d0ae5eafda22b714_b.jpg& data-rawwidth=&1100& data-rawheight=&733& class=&origin_image zh-lightbox-thumb& width=&1100& data-original=&https://pic1.zhimg.com/v2-ccbd13d0ae5eafda22b714_r.jpg&&&/figure&&p&之前有网友问游戏服务器和网站服务器之间区别的问题,用我以前写的一篇讲座PPT整理后作出了回答,反响还不错。今天特将原文整理如下,以飨网友。&/p&&h2&前言&/h2&&p&这节讲座里,我们将从游戏服务器发展的简单历程出发,鸟瞰一下目前大多数的游戏服务器架构。&/p&&p&这里尽可能的避免陷入细节的技术问题,而是从技术进化的结果状态,反推原始问题是什么。希望能通过这个过程,解释清楚游戏服务器是在解决什么问题,痛点到底在哪里。&/p&&h2&一、早期网游服务器。&/h2&&p&蛮荒时期的游戏服务器框架我们一笔带过,那时的游戏服务器和一个小Web服务没有区别。&/p&&p&蛮荒时代的服务器只负责存储玩家账号、数据、转发场景内其他玩家的行为。很多移动、使用技能等关键逻辑在服务器上根本没有。随意就能用变速齿轮改变游戏速度。&/p&&p&从《传奇》的时代开始,游戏服务器就不再是简单的上传存档、下载存档、访问页面而已。游戏服务器内部出现了游戏逻辑,既能用于同步每个玩家看到的世界,又能让逻辑与客户端分离,避免早期的网络游戏那种毫无防范的逻辑体系(对外挂防御能力为0)。&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-d0d7eed73b05dea8c621adcc_b.jpg& data-rawwidth=&1011& data-rawheight=&535& class=&origin_image zh-lightbox-thumb& width=&1011& data-original=&https://pic4.zhimg.com/v2-d0d7eed73b05dea8c621adcc_r.jpg&&&/figure&&p&&br&&/p&&p&如图,客户端通过某种形式验证登陆以后,就和服务器通过TCP直接相连了。这种服务器的承载能力不高,但那时在游戏逻辑上也务求简化,把负载减少到极致。&/p&&p&· 例如:1、玩家看不到怪物的血量,或者只能看到正在打的怪物的血量。2、地图有格子的概念,每个格子只能有一个单位,极大限制了同屏人数。&/p&&p&由于逻辑尽量简化,虽然这时的服务器逻辑服务都是单进程单线程的,但是也足够表现交互的感受。&/p&&p&这种架构奇怪的地方是处理网络连接数据传输的压力和逻辑处理的压力在同一个服务器上(存储模块可能也在同一个进程),就算逻辑处理压力为0,承载人数也高不到哪去。&/p&&p&虽然这时的游戏服务器设计很简陋,但是网游第一次给了玩家真实世界的感受。单服人数不足的问题可以靠开多组服务器实现,所以曾经出现了几百上千组服务器的辉煌时代。&/p&&h2&二、早期游戏服务器的改进版本&/h2&&p&当开发者们有了初步经验以后,新作品的开发,自然而然的过渡到了如下的形式:&/p&&p&&br&&/p&&figure&&img src=&https://pic4.zhimg.com/v2-4c91aeee6a9e00f8ef834a_b.jpg& data-rawwidth=&1112& data-rawheight=&680& class=&origin_image zh-lightbox-thumb& width=&1112& data-original=&https://pic4.zhimg.com/v2-4c91aeee6a9e00f8ef834a_r.jpg&&&/figure&&p&&br&&/p&&p&游戏逻辑服务依然是在一台服务器上,单进程(逻辑处理本身肯定是在一个线程中,可以有子线程负责内网通信)。但是我们自然的想到,存储负载和网络连接负载可以从逻辑服上拆出来。&/p&&p&连接服务器负责把客户端和服务器之间的消息转化为服务器之间的消息,可以顺便做一些加解密的工作。&/p&&p&这一点小改动极大提高了单服连接人数的上限。但是玩家要求提高了,空出来的性能很快被丰富的游戏系统吃掉了。&/p&&p&由于连接服务器本身没有时序性,很容易做分布式的(其实大部分游戏还是只用一个连接服),存储服务不要求高实时性,高峰期存盘间隔可以稍长一些,不会对游戏服造成影响。&/p&&h2&三、成熟形态的服务器框架&/h2&&p&逻辑服务器的负载均摊方法一:按照功能划分多个服务器进程&/p&&p&&br&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-83d176b88c6ffcfba9d842_b.jpg& data-rawwidth=&1154& data-rawheight=&657& class=&origin_image zh-lightbox-thumb& width=&1154& data-original=&https://pic3.zhimg.com/v2-83d176b88c6ffcfba9d842_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&逻辑服务器的负载均摊方法二:按照场景划分多个服务器进程&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-3c87d414d04a2ab57c24f6bb78af5d45_b.jpg& data-rawwidth=&1139& data-rawheight=&654& class=&origin_image zh-lightbox-thumb& width=&1139& data-original=&https://pic2.zhimg.com/v2-3c87d414d04a2ab57c24f6bb78af5d45_r.jpg&&&/figure&&p&&br&&/p&&p&对游戏服务器历史有了基本了解后,成熟形态的游戏服务器很容易理解。简单来说,就是把逻辑服务器单个进程的压力分摊到多个服务器。&/p&&p&难点在逻辑的设计上,要像做手术一样把本来是一体的功能切开,并抽象出若干个API来保持联系(服务器之间是TCP连接)。&/p&&p&在分解时,&b&要找联系相对最薄弱的环节入手&/b&,比如场景和场景之间分开、单独抽出聊天服务、组队服务、好友服务。&/p&&p&无论如何分解,最终结果只能是有限个服务。而且分解的越细,开发难度就越大。因为跨服务器逻辑是把简单的同步逻辑变成了异步Callback逻辑,而且容易出现时序问题等不易测试的问题。&/p&&p&单个场景服务几乎是无法分解的。分解单个场景难度巨大以至于出现了BigWorld引擎来专门的解决场景分割问题,后面会谈到。&/p&&p&&br&&/p&&p&这种成熟形态的游戏服务器已经能满足现实中99%的频繁交互类网游需求,是大型MMO端游、页游的主流形式。&/p&&p&当然有实力的公司在这个基础上会做很多改动,实现动态开辟副本、相位技术等等,但是万变不离其宗,其本质和上图没有什么区别。&/p&&p&&br&&/p&&h2&附:开房间式的网络游戏&/h2&&p&开房间式的网络游戏也是游戏的一个重要分支,英雄联盟、DOTA、很多手游例如皇室战争、王者荣耀等等。&/p&&p&这种游戏房间之间几乎没有交互,只有大厅内有交互,可以理解为原始形态的游戏服务器的平行扩展。&/p&&p&房间式游戏扩展难度较小,只是需要根据玩家数量动态扩展游戏房间的数量、服务器数量。很像网站的架构。&/p&&p&&br&&/p&&figure&&img src=&https://pic2.zhimg.com/v2-e465c2a9d2_b.jpg& data-rawwidth=&1143& data-rawheight=&650& class=&origin_image zh-lightbox-thumb& width=&1143& data-original=&https://pic2.zhimg.com/v2-e465c2a9d2_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&这种游戏架构最最适合放在云平台上,设计合理的话,它可能遇到的问题和大型网站几乎一模一样。不需要特别的讨论它们。&/p&&p&只是,&b&毕竟游戏不都是开房间的玩法&/b&。&/p&&p&&br&&/p&&h2&小结:游戏服务器框架特点&/h2&&p&1、真正的数据都在内存中,数据库性能不那么重要&/p&&p&· 注:很多大型游戏采用了共享内存,避免宕机时损失过大。&/p&&p&2、单CPU性能比CPU数量重要的多。&/p&&p&3、目前有很多游戏,特别是手游,使用Redis读写代替内存读写,甚至也有用Mongo的。&/p&&p&4、开新服、旧区合服的情况,非常适合云平台。&/p&&h2&五、先进服务器框架&/h2&&p&&b&· 先进服务器框架1
BigWorld&/b&&/p&&p&BigWorld引擎的代表作:&/p&&p&· 中国:《天下贰 》《天下叁》等等数十款,网易对BigWorld的实用化贡献很大。&/p&&p&· 国际:《魔兽世界》早期版本,《坦克世界》,《战争雷霆》&/p&&p&BigWorld的核心理念,要回到上面讲过的场景分割问题。&/p&&p&BigWorld利用平面切分的原理,将场景划分为小块,不同的块可以运行在不同的服务器上。而且块的划分是动态的,根据玩家密集程度、数量动态调整块的大小。。&/p&&p&具体技术上,使用了Actor模型,要求每个对象都是独立的Entity,对象之间只能通过消息协作,严格限制对象之间的直接交互。&/p&&p&后来随着手游的崛起、端游的衰落、网游玩法向多元化发展,这一系列的变化,导致BigWorld引擎很快就衰落了。&/p&&p&BigWorld引擎从曾经的大红大紫,到现在的无人问津,反映出游戏服务器技术的发展趋势。BigWorld的强制Actor模型,实际上是牺牲了开发效率,换取了服务器可扩展性。&/p&&p&理论上单服承载人数可以达到百万级别。但是游戏的业务逻辑的修改很频繁,开发效率低下是游戏设计师不能承受之重。&/p&&p&这种架构天生就是为云计算准备的,而且单个物理机承载量十分有限,每个游戏大区都需要大量实体机。&/p&&p&如果BigWorld成功…… 可惜的是,它和实际市场的发展趋势背道而驰了。&/p&&p&&b&游戏开发相比电商系统,项目规模小几个数量级,但是相对的,迭代速度要快几倍。项目之间如果类型不同或是玩法有差异,能复用的代码并不多。&/b&&/p&&p&聊聊十万行代码。游戏服务器开发速度受美术资源制作速度、客户端开发速度制约。近几年我猜测服务器方面并不会有大的技术革新。&/p&&p&游戏开发未来的趋势是多元化、低门槛化、大众化。很长一段时间内BigWorld这种大怪兽级别的引擎不会再崛起。&/p&&p&分布式框架的崛起时间点,无论如何,也在VR技术成熟之后了。&/p&&p&&br&&/p&&p&&b&· 先进服务器框架2、Skynet&/b&&/p&&p&Skynet是新兴的一种通用型服务器框架(完全开源),它游走在传统不易分布服务器和分布式服务器之间。&/p&&p&它是一种泛用型框架,不仅能很好的作为游戏服务器框架使用,而且用来搭建HTTP服务也具有惊人的性能(几百行代码的简单HTTP实现,能达到nginx 60%的性能)。&/p&&p&矛盾的是,由于它对脚本虚拟机做了一些重要的Hack,导致它完全绑定在了Lua这一种语言上。&/p&&p&Skynet原理阐述:&/p&&p&把服务抽象为微服务,一个系统内可以建立成千上万个微服务,Skynet调度m个线程(m=CPU核心数)、处理n个微服务各自的事件。&/p&&p&由于n个微服务在同一个进程内,可以达到0延迟的内部通信(极端情况下无拷贝)&/p&&p&同时Lua虚拟机又提供了沙盒机制,微服务之间的Lua逻辑代码不会有任何干扰,必要的时候又可以在C语言层面、Lua沙盒之外共享数据。&/p&&p&由于服务本身有良好的隔离性,可以较为方便的把服务部署到多物理机上(考虑到性能问题,不能像BigWorld那样任意部署)。&/p&&p&Skynet这种架构已经在Lua体系的游戏公司内大量使用(以网易系为代表),悄无声息的渗透到其他公司里。(和Lua语言当年的情况有点像,是金子总会发光的。)&/p&&p&&br&&/p&&h2&六、先进服务器框架3、以Go语言为主的其他框架&/h2&&p&Go语言的goroutine特性,给游戏开发者带来巨大的想象空间。&/p&&p&在Go语言的基础上,很容易出现更好的房间式游戏框架、类似Skynet的框架、改进型的传统框架。&/p&&p&但是可以大胆预测,最终实现的效果不会超过erlang、skynet这类框架的范围。这是因为游戏业务本身的特性决定的。&/p&&p&&br&&/p&&h2&结束语&/h2&&p&本文简要探讨了十几二十年来,主流服务器框架的发展脉络,以MMO-RPG这种最具代表性的网游类型为主(同时MMO对服务器架构的挑战也是最大的),兼谈到一些其他类型的游戏。由于游戏类型多种多样,各个国家和地区的开发商所偏好的架构方式也大有不同,文中难免挂一漏万,但不太影响整体脉络,也不影响对网游服务器的核心问题的总结——逻辑拆分。&/p&&p&期待读者们提出批评和建议。&/p&&p&&br&&/p&&p&————————————————————————————————&/p&&p&对游戏开发感兴趣的同学,欢迎围观我们:【皮皮关游戏开发教育】 线下教育自不必说,还会定期更新各种教程,干货。在你学习进步的路上,有皮皮关陪你!~&/p&&p&我们的官网地址:&a href=&https://link.zhihu.com/?target=http%3A//levelpp.com/& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&levelpp.com/&/span&&span class=&invisible&&&/span&&/a&&/p&&p&&br&&/p&&p&我们的游戏开发技术交流群:&/p&&p&我们的微信公众号:levelpp&/p&
之前有网友问游戏服务器和网站服务器之间区别的问题,用我以前写的一篇讲座PPT整理后作出了回答,反响还不错。今天特将原文整理如下,以飨网友。前言这节讲座里,我们将从游戏服务器发展的简单历程出发,鸟瞰一下目前大多数的游戏服务器架构。这里尽可能的…
&figure&&img src=&https://pic3.zhimg.com/v2-faefb881cd_b.jpg& data-rawwidth=&992& data-rawheight=&550& class=&origin_image zh-lightbox-thumb& width=&992& data-original=&https://pic3.zhimg.com/v2-faefb881cd_r.jpg&&&/figure&&p&(编注:这篇文章跟读者时互动的,你想看到渲染哪方面,留言告诉我。在写作会偏向你需要的Y(^_^)Y)&br&&/p&&p&&br&&/p&&p&为了保证通用性,我这里尽量不去以任何一种渲染器的习惯作为前提假设,而是尽量地用物理和常识来描述图像的组成元素。&/p&&blockquote&&b&渲染系列文章:&/b&&br&&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&基于物理的渲染(一):什么是渲染?&/a&&/blockquote&&p&首先要强调一点就是,无论是几种相同和不同的光源产生的光,还是拆分成下面的组成部分,在合成环节把他们混合成最终灯光效果的时候,它们之间的混合方式只有一种:&b&相加! &/b&&/p&&p&光不应该也不能用其他的混合方式混合,用其他方式去混合灯光会造成能量失衡,导致最终画面光感不准确。&/p&&figure&&img data-rawheight=&720& src=&https://pic4.zhimg.com/v2-1d9de54f7b2b9e98c67704_b.jpg& data-rawwidth=&1280& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic4.zhimg.com/v2-1d9de54f7b2b9e98c67704_r.jpg&&&/figure&&p&&br&&/p&&p&&b&按照光线在物体的不同位置交互,从原理和易操作性上来划分我们有下面几个组成部分:&/b&&/p&&p&&br&&/p&&p&&b&- 反射,包括漫反射,和高光反射。&/b&&/p&&p&&br&&/p&&p&&b&- 折射,包括模糊折射,和清晰折射。&/b&&/p&&p&&br&&/p&&p&&b&- 散射,包括无表面的散射,和次表面散射。&/b&&/p&&p&&br&&/p&&p&&b&- 自发光,包括产生光子的自发光,和不产生光子的自发光。&/b&&/p&&figure&&img data-rawheight=&853& src=&https://pic3.zhimg.com/v2-db777ef21e7f5f01e30fb_b.jpg& data-rawwidth=&1280& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic3.zhimg.com/v2-db777ef21e7f5f01e30fb_r.jpg&&&/figure&&p&&br&&/p&&p&每个渲染器完成这些光照元素的方式都不完全一致,每个公司自己开发的Shader也有不同的处理方式,但是万变不离其宗,他们最终试图去描述的内涵都是一致的:&/p&&p&漫反射,高光反射,模糊折射和清晰折射的亮度加在一起的总和不超过入射进来的光线。为了保持能量守恒,一个属性的增强势必导致另外其他的属性减弱。&/p&&p&他们根据美学要求可以继续往下细分,比如ILM的高光就经常使用两个不同锐度的高光反射。&/p&&figure&&img data-rawheight=&636& src=&https://pic4.zhimg.com/v2-fb2a80172b84acabfbf44b00_b.jpg& data-rawwidth=&949& class=&origin_image zh-lightbox-thumb& width=&949& data-original=&https://pic4.zhimg.com/v2-fb2a80172b84acabfbf44b00_r.jpg&&&/figure&&p&&br&&/p&&p&漫反射和高光反射在某些时候是无法区分的,它们本质上也是一样的光照原理。反射角很大的高光反射,范围可能会变得和漫反射一样大,在这种情况下他们可以互换。&/p&&p&但取决于渲染器的设计,用高光反射的功能实现漫反射的效果可能会导致渲染效率下降。&/p&&figure&&img data-rawheight=&508& src=&https://pic2.zhimg.com/v2-b20d0fb77da_b.jpg& data-rawwidth=&600& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&https://pic2.zhimg.com/v2-b20d0fb77da_r.jpg&&&/figure&&p&&br&&/p&&p&折射也是一样的道理,清晰折射是物体表面光滑,内部清澈的情况下会产生的效果。当物体表面变得粗糙,光线被表面上许多微小的切面折射到不同方向,宏观上看折射开始变得模糊。&/p&&p&如果物体内部开始变得浑浊,光线在内部便会开始与内部的杂质颗粒进行交互,宏观上产生了次表面散射现象。&/p&&p&杂质越大越密集,光线穿透材料的可能性就越低,我们看到的画面就越多被次表面散射层占据,折射层的含量就越少。&/p&&figure&&img data-rawheight=&533& src=&https://pic2.zhimg.com/v2-aed51d4f33bf4ce96ff3f04_b.jpg& data-rawwidth=&800& class=&origin_image zh-lightbox-thumb& width=&800& data-original=&https://pic2.zhimg.com/v2-aed51d4f33bf4ce96ff3f04_r.jpg&&&/figure&&p&&br&&/p&&figure&&img data-rawheight=&288& src=&https://pic2.zhimg.com/v2-c4dc580b6ef666c5b8b040_b.jpg& data-rawwidth=&600& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&https://pic2.zhimg.com/v2-c4dc580b6ef666c5b8b040_r.jpg&&&/figure&&p&&br&&/p&&figure&&img data-rawheight=&636& src=&https://pic4.zhimg.com/v2-3ca4694d64fed1bd0dcf58be7a4692b7_b.jpg& data-rawwidth=&600& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&https://pic4.zhimg.com/v2-3ca4694d64fed1bd0dcf58be7a4692b7_r.jpg&&&/figure&&p&&br&&/p&&figure&&img data-rawheight=&480& src=&https://pic2.zhimg.com/v2-9b5edf06a1e7eaeed7a4abb_b.jpg& data-rawwidth=&852& class=&origin_image zh-lightbox-thumb& width=&852& data-original=&https://pic2.zhimg.com/v2-9b5edf06a1e7eaeed7a4abb_r.jpg&&&/figure&&p&&br&&/p&&p&有些物体自身有发光性质,我们称作自发光。CG中的纯光源只是一个具有自发光性质但本身不被渲染的物体。火焰即有自发光,又包含可被渲染的介质。&/p&&p&在CG中,有些物体具有自发光性质,但是不产生光子照亮其他物体,这种物体通常被用来制作全景环境图供其他物体反射或折射。&/p&&p&如果一个场景中只有特效模拟的火焰一种发光物体,那这个火焰便会作为一个渲染物体,它产生的光子作为一个光源存在。在PBR的场景里,任何物体都可能会影响任何其他物体。&/p&&figure&&img data-rawheight=&371& src=&https://pic1.zhimg.com/v2-6bdb7ecb_b.jpg& data-rawwidth=&660& class=&origin_image zh-lightbox-thumb& width=&660& data-original=&https://pic1.zhimg.com/v2-6bdb7ecb_r.jpg&&&/figure&&p&&br&&/p&&p&一般我们也用不产生光子的自发光来渲染物体本身的固有色层,比如一张具有木纹的桌子,固有色层如决定单独输出,我们可以用这样的方式将它渲染出来。&/p&&p&在合成阶段它应该和漫反射层相乘得到具有固有色的漫反射层,高光反射保持和光源颜色一致。(导电的材料的高光反射也会继承材料本身的颜色,比如黄金等,高光颜色要和材料颜色一致。)&/p&&figure&&img data-rawheight=&1024& src=&https://pic3.zhimg.com/v2-597bc42cf08fa41948d72d_b.jpg& data-rawwidth=&1024& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic3.zhimg.com/v2-597bc42cf08fa41948d72d_r.jpg&&&/figure&&p&&br&&/p&&p&在&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&前一篇文章&/a&说过,散射根据是否有一个明确表面的内部,我们会将他们分为无表面散射,和次表面散射。他们的计算原理差异不大,区别在于这一层光照存储在什么位置和怎么去使用他们。次表面散射将光照存储在物体的表面,无表面散射将光照存在连续的透光介质中(Participating media)。&/p&&figure&&img data-rawheight=&720& src=&https://pic2.zhimg.com/v2-803cedfa5805b09bbc61af_b.jpg& data-rawwidth=&1280& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic2.zhimg.com/v2-803cedfa5805b09bbc61af_r.jpg&&&/figure&&p&&br&&/p&&p&散射层可以当作一个十分模糊的折射层,或者一个自发光层来看待(但是要保证能量守恒)。散射甚至可以用模糊的折射或者一个模糊的自发光层来粗略模拟。&/p&&p&比如比较薄的物体内部产生的瓷表面散射,和它模糊折射的光源差异不大。&/p&&p&一个爆炸的烟雾模拟在渲染的时候也可以把火做模糊处理,作为烟的自发光层加入到最终渲染里,这样可以很好地模拟多次计算的散射效果,而效率确是真实计算的上百倍之高。&/p&&figure&&img data-rawheight=&720& src=&https://pic3.zhimg.com/v2-7ca7db5de12e_b.jpg& data-rawwidth=&1280& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic3.zhimg.com/v2-7ca7db5de12e_r.jpg&&&/figure&&p&&br&&/p&&p&散射和折射除了背光尤其明亮,过渡比较通透除外,通常很显著的效果是光在介质内部反弹的时候颜色会产生变化。&/p&&p&海水吸收红色光较多,所以光线到海底越深的位置剩下的光就越偏向蓝绿色。&/p&&p&燃烧产生的烟通常会吸收蓝色光,导致越厚的烟雾越会偏向橙黄色。&/p&&p&粒子十分细密(低于光波长)的烟雾反而会被留下蓝色光,比如香烟产生的烟雾,这种现象被称作Rayleigh Scattering,属于现实常见但渲染里不常见的效果,通常靠手动调整得到。&/p&&p&&br&&/p&&figure&&img data-rawheight=&640& src=&https://pic1.zhimg.com/v2-ddf71ec32c1f737f73bbde6d_b.jpg& data-rawwidth=&1024& class=&origin_image zh-lightbox-thumb& width=&1024& data-original=&https://pic1.zhimg.com/v2-ddf71ec32c1f737f73bbde6d_r.jpg&&&/figure&&p&&br&&/p&&figure&&img data-rawheight=&615& src=&https://pic4.zhimg.com/v2-eb480cf230_b.jpg& data-rawwidth=&820& class=&origin_image zh-lightbox-thumb& width=&820& data-original=&https://pic4.zhimg.com/v2-eb480cf230_r.jpg&&&/figure&&p&&br&&/p&&p&一些表面纹理奇异的物体,通常因为有多层可以折射光线的薄膜所致,会产生彩虹色的反射或者折射。&/p&&p&肥皂泡上的彩虹色纹理就是最常见的例子。要想模拟这种纹理,我们需要深入到把光线分离成不同频率分别使用不同的折射率去折射的方法,但这种方法需要一些开发工作和更长的渲染时间,也不一定便于艺术家控制,所以大家也经常采用作假的方式去实现这种效果。&/p&&p&一个很普遍的方式就是通过把彩虹色的纹理根据物体上Fresnel数值映射到表面上来实现。但这些作假的方式不会适用所有范围,比如模拟光线在钻石内部的多次折射产生的昂贵彩虹色就无法实现。(钻石这种东西呢,该买就得买真的。)&/p&&p&&br&&/p&&figure&&img data-rawheight=&510& src=&https://pic1.zhimg.com/v2-a48df3c60aea19ba39109df_b.jpg& data-rawwidth=&900& class=&origin_image zh-lightbox-thumb& width=&900& data-original=&https://pic1.zhimg.com/v2-a48df3c60aea19ba39109df_r.jpg&&&/figure&&p&&br&&/p&&figure&&img data-rawheight=&995& src=&https://pic4.zhimg.com/v2-25a212edffb37_b.jpg& data-rawwidth=&1280& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic4.zhimg.com/v2-25a212edffb37_r.jpg&&&/figure&&p&&br&&/p&&figure&&img data-rawheight=&462& src=&https://pic4.zhimg.com/v2-37ae492980eee5e040ae2de6c35c82ec_b.jpg& data-rawwidth=&822& class=&origin_image zh-lightbox-thumb& width=&822& data-original=&https://pic4.zhimg.com/v2-37ae492980eee5e040ae2de6c35c82ec_r.jpg&&&/figure&&p&&br&&/p&&p&&br&&/p&&p&&b&多次反弹光: 间接光照&/b&&/p&&p&上述的所有光照的分解元素,在PBR渲染器渲染的时候光线都会在各自的轨迹中反弹多次。&/p&&p&月球上物体的纯黑色阴影是因为没有大气产生的

我要回帖

更多关于 电信volte丢包 的文章

 

随机推荐