服务器游戏代理服务器

游戏代理服务器  时间:2021-05-09  阅读:()

MMORPG游戏服务器开发之我见wz2/3/2014过年在家无聊,写篇网游服务器开发相关的总结,打发下无聊时间吧,希望年后找一个游戏相关的开发职位,也算是提前准备一下吧.
声明下:这里只谈MMORPG游戏的服务器开发技术,其他类型的游戏服务器开发未涉及.

游戏公司里的技术都是商业机密,网上相关的资料很少,所以本文大部分内容来自于猜想和脑补,肯定有很多不对或被人嗤之以鼻的地方,欢迎拍砖,拍转的时候请给个理由,这样我也可以自我提高一下O(∩_∩)O~.
文中主要讲了如果以我现在的知识储备来开发一个MMORPG游戏,服务器架构应该是怎样为好,技术难点在哪里.
当然架构无所谓好坏,更多的是适合与否,如果有更为实际的需求,会比空想更容易设计也更容易评估怎样做更好些.
当然除了架构之外,剩下的就是如何去实现,将复杂逻辑翻译成代码,这些用到的都是一些通用的编程技术,所以在本文中就不多说了.

目录对游戏服务器开发的认识2MMORPG服务器架构2登陆服务器/Loginserver4排队系统/QueueServer5网关服务器/GateServer6场景管理服务器/世界服务器/Worldserver8逻辑/地图/场景/游戏服务器/Sceneserver9消息广播10AOI(AreaOfInterest)11同步策略13自动寻路算法16NPCAI17数据库18网络框架22lua内嵌脚本24热更新24战斗系统和任务系统25性能优化26游戏测试27对游戏服务器开发的认识网游服务器开发总体上来讲不过十几万到几十万行代码量,算不上是大工程,他跟其他C/S结构的软件工程也没有太大区别,解决问题的方式也是很相似的.
虽然现在很多游戏号称同时在线几百万,但这几百万的在线人数是要被分配到几百个游戏服上,从单个服来讲也就几千或上万的并发用户数而已(EVE单服也不超过10万人同时在线),而且服与服之间是完全隔离的,所以算不上是大规模应用,跟淘宝、百度、QQ那样支持海量用户的应用没法比.

当然反过来说,像淘宝、百度那样的网站,用户之间是弱交互,有天然的伸缩性,容易做分布式部署,所以可以支持很高的并发,但网游的用户之间是强交互的,而且游戏内的场景也不是无限大,为了保证游戏较好的体验,同时在线人数不可能达到很高,想象下如果几万人聚集在一个场景里,也没有好玩可言吧.

总之,MMORPG服务器开发还是挺复杂的,起码逻辑还是挺复杂的,光从上百页的策划来看就说明了这一点,而且在这个外挂漫天飞的时代,服务器的地位越来越重要,很多逻辑操作或计算都放到服务器上来做,即便有些是要客户端来做的,服务器也要做doublecheck.
所以网游服务器开发应该还是很有技术挑战的.
MMORPG服务器架构早期的网游服务器是架设到单机上的,现在为了提高服务器性能,支持更多在线人数、更流畅的用户体验和更炫酷的玩法,网游服务器根据场景或功能划分成多个服务器,采用合理的集群架构分布式部署.
所以现在一个游戏服已经不再是一个物理服务器的概念,而是一组物理服务器的概念了.

现在我们就从大的方面谈谈MMORPG服务器应该怎样架构吧.
架构的设计我们遵循KISS原则(KeepItSimpleAndStupid),尽量做到简单高效.
当我们在面对复杂系统的设计时,总觉得脑子里一团浆糊,一会考虑考虑这一会考虑考虑那,总是理不清,原因是系统的复杂度超过了我们大脑的工作记忆容量,我们的大脑无法模拟和记忆每一个细节,所以我们需要:模块化+接口封装+逐步优化.
将每个能够独立出来的功能模块化,然后定义模块的数据输入输出,封装成接口,将所有模块通过接口组装在一起便成了架构,最后再对每个模块的具体实现细节逐个优化.

引用下面的两段话,我觉得讲的很有道理,可以借鉴到软件系统设计开发上来:"在大刀阔斧进行创新实验的初期阶段,对每一步实验的设计当然要尽量仔细,但一旦按计划开始后对其中间步骤的实验结果不必追求完美,而是应该义无反顾地把实验一步步推到终点,看看可否得到大致与假设相符的总体结果.
如果大体上相符,你才应该回过头去仔细地再改进每一步的实验设计.
如果大体不符,而总体实验设计和操作都没有错误,那你的假设(或总体方向)很可能是有大问题的.
""从1998年开始自己的独立实验室到现在,我告诉所有学生:切忌一味追求完美主义.
我把这个方法论推到极限:只要一个实验还能往前走,一定要做到终点,尽量看到每一步的结果,之后需要时再回头看,逐一解决中间遇到的问题.
"我们的架构设计成下图所示:为了保证服务器达到可伸缩、高可用、高性能、代码实现简单易维护,要试着避免所有事情都在一个地方处理,尽量让系统分布式运行,我们可以将一个组内的服务器简单地分成两类:场景相关的(如:行走、战斗等)以及场景不相关的(如:公会聊天、不受区域限制的贸易等).
为了保证游戏的流畅性,可以将这两类不同的功能分别交由不同的服务器去各自完成.
另外,对于那些在服务器运行中进行的比较耗时的计算(如NPCAI,自动寻路,AOI计算),也将其单独提炼出来,交由单独的进程去完成.
在接下来的几节里我们会分别详细讲一下各个server所承担的工作.
上图中所有的server都是指逻辑意义上的server,也就是说可以将每个server分别部署到一台服务器上,也可以将多个server部署到一台服务器上,比如:为了节省硬件成本提高服务器资源的利用率,可以将多个场景(Sceneserver)放到同一个物理服务器中.
当然上图只是一个较粗粒度的架构,可以根据性能瓶颈进行调整,比如DB有压力,则可以将DB分库或分表.
又比如一台Worldserver可能容易出现单点故障,我们可以用M台,一方面提高了性能另一方面提高了服务可用性.
又比如AOI有压力,我们可以继续将AOI处理模块扩展到多台服务器上等等.
吐槽八卦:Google的项目大部分都是分布式部署的,而且对多线程代码比较谨慎,感觉这个东西还是比较容易出bug,宁愿采用多进程多机运行来提高性能.
你可能会问:现在机子都是多核的,单线程多浪费啊呵呵,这跟Google的集群架构有关了,集群中的每台机器会划分出一部分资源(CPU.
RAM,DISK)供你的项目使用,同一台机器可以同时提供给多个项目使用,所以资源不会浪费掉的.
其实即使没法做到像Google集群架构那么高效,也不应该过度的使用多线程.
对于那些交互比较多的逻辑代码,不适合采用多线程,多线程更多的应该是应用到分割CPU、网络和存储操作上.
来一个当年在Google做的项目的架构图吧(很粗略的)登陆服务器/Loginserver游戏的登陆服务器跟其他应用的登陆服务器没啥区别.
需要解决几个问题:保证认证的安全(账号、密码加密/DDOS检测/黑名单)登陆认证通过之后需要生成一个认证token到Gateserver和client.
更简单的方法是,Gateserver不持有这个token,而是由登陆服务器持有,当用户连接Gateserver时,Gateserver向Loginserver请求token认证.
负载均衡,一般登陆流程是:登陆=>选服=>创建角色=>开玩.
登陆操作在选服之前,所以需要面对海量用户,就可能需要多台服务器,这时我们就需要做简单的负载均衡.
登录服处理的逻辑相对来说比较简单,就是将玩家提交的帐号和密码送到数据库进行验证,和生成会话密钥发送给游戏服和客户端,操作完成后连接就会立即断开,而且玩家在以后的游戏过程中不会再与登录服打任何交道.
这样处理短连接的过程使得系统在大多数情况下都是比较空闲的,单台服务器就能承担很多用户的登陆认证需求.

当然像一些大的游戏公司,游戏很多,不同游戏的账号是可以通用的,也就是说有一个公共的用户认证平台,作为通用service提供用户认证,大大降低了研发工作量.
例如Google所有的应用都是用Googleaccount来做身份认证,腾讯开发的游戏则是用QQ来登录.
吐槽八卦:曾经Google中国竟然搞了一个不用Googleaccount来做用户登录认证的项目"Google时惠",做中国的团购搜索,最后也不了了之了.
排队系统/QueueServer为了避免游戏在开测期间大量用户涌入阻塞服务器,可以采用排队系统.
其实排队系统算是一个鸡肋吧,我们可以用其他手段来阻止用户的大量涌入:比如限量发行测试号、达到服务器负载之后拒绝接入等,但排队系统的做法可能会稍微显得文明些(现在干啥事不排队呢).

其实需求明确的架构设计是很容易做的,难的是那些需求或要求不明确的架构设计,我们需要添加足够多的限制条件让需求明确,但限制条件又必须是合理的,而且又不能过于限制还要保证架构要有足够的通用性和可扩展性.
我们先来看看具体的需求:在游戏服达到人数上限之后登录的用户进入排队系统必须要先登录才能排队,防止恶意排队排队结束之后进入游戏服,先排队者先进入游戏用户可以选择退出排队系统用户关闭客户端后将其从排队系统中清除即时通知排队位置的变化,预估等待时间区分普通用户和会员用户,会员可以插队GM可以不用排队直接进入有了上面的限制我想一个刚毕业的大学生也可以将这个系统做出来吧.
我对好架构的判断标准就是:连刚毕业的大学生都能轻松实现的架构才是好架构.
从上面的需求来看,发现有两个问题:1如果排队人数过多,超过了排队系统能够承担的连接数怎么办2能否支持离线排队就是我排个号,然后关闭客户端,还会保留我的位置,下次登陆之后自动将我放到我之前排队的位置上,而不是重新取号排到末尾.
问题1的解决方法是:如果超过了排队系统能够承担的最大连接数之后拒绝后续玩家进入排队系统,告知排队系统已满.
或者采用多台机器作为排队系统,由一台中心服务器短连接来发排队号,将排队长连接分发到各台排队机器上.

问题2的解决方法是:为每个离线玩家保留一个排队号,用户再次登录排队系统之后,查找原来的排队号,以原来的排队号大小为准,依次进入游戏服务器.
当然我们也可以附加一些条件,如设置一个排队号的有效时间,过期之后作废,又或者如果排队号码被跳过(轮到玩家登入游戏服务器时,而玩家处于离线状态),则排队号作废.

吐槽八卦:关于代码有人写代码喜欢用各种复杂设计模式,把代码写的巨复杂,而且还觉得写出复杂代码才是技术牛逼的体现.
我想说的是思从深而行从简,写代码追求的是简单易懂易维护,高性能可靠易扩展,不要本末倒置.

网关服务器/GateServer接下来我们从下面三个问题来讨论网关服务器:为什么要加个网关服务器呢它都做了哪些工作加了网关服务器之后又会遇到什么问题首先回答第一个问题:为什么要加个网关服务器呢1在服务器组中,最直接影响到性能的是场景服务器,场景服务器的性能直接影响到能支持多少玩家同时在线,所以我们要将尽可能的将工作从场景服务器中分离出来.
场景服务器中,为了保证每个玩家看到的游戏世界是一致的,所以一个玩家的行走、战斗等信息都要广播给其他玩家,所以消息的广播是在场景服务器中很耗资源的关键工作,如果让场景服务器来负责将每个玩家的消息广播到其他玩家,势必会影响到场景服务器的性能.
为此网关服务器就出场了,场景服务器可以将需要广播的消息和广播的玩家列表发给网关服务器,广播工作就隔离到网关服务器上了.

2如果没有网关服务器,场景服务器要保持与n多客户端的长连接,还要做包的接收校验解压解密等一系列工作,一方面场景服务器的逻辑已经够复杂了,另一方面场景服务器已经够忙了,所以完全可以将这部分工作单独放到网关服务器上.
场景服务器只需要维持与网关服务器的连接即可.

3隔离出来的网关服务器可以作为通用结构来复用,在开发其他游戏的时候不用重复开发接下来回答第二个问题:它都做了哪些工作呢1作为网络通信的中转站,负责维护将内网和外网隔离开,使外部无法直接访问内部服务器,保障内网服务器的安全,一定程度上减少外挂的攻击.
2网关服务器负责解析数据包、加解密、超时处理和一定逻辑处理,这样可以提前过滤掉错误包和非法数据包.
3客户端程序只需建立与网关服务器的连接即可进入游戏,无需与其它游戏服务器同时建立多条连接,节省了客户端和服务器程序的网络资源开销.
4在玩家切换场景服务器时,玩家数据在不同场景服务器间的切换不需要断开与网关服务器的连接,而且是内网切换,切换工作瞬问完成,玩家几乎察觉不到延迟,这保证了游戏的流畅性和良好的用户体验.
第三个问题:加了网关服务器之后又会遇到什么问题1.
网关服务器成为高负载情况下的通讯瓶颈问题2由于网关的单节点故障导致整组服务器无法对外提供服务的问题3多了一个网关服务器会不会影响性能会不会增加响应延迟解决方法:网关服务器处理的逻辑比较简单,主要是负责数据包转发,所以可以支持很高的并发,同时网关服务器的功能决定了有很好的伸缩性,可以采用多个网关服务器分流高负载,同时也解决了单点故障导致整个服宕掉的情况.
网关服务器所做的工作像一个路由器,数据包在到达游戏服务器组之前已经经历了很多路由器,也不差这一个,所以性能方面影响不是很大,也不会明显增加响应延迟.

场景管理服务器/世界服务器/Worldserver为了实现众多的场景服务器之间以及场景服务器与非场景服务器之间的数据同步,我们有必要建立一个统一的管理者,这个管理者就是服务器组中的世界服务器.
它的任务主要是在各服务器之间作数据同步.
其最主要的功能还是完成场景切换时的数据同步.
当玩家需要从一个场景A切换到另一个场景B时,场景管理服务器负责将玩家的数据从场景A转移到场景B,并通过协议通知这两个场景数据同步的开始与结束.
所以,为了实现这些内容繁杂的数据同步任务,场景管理服务器通常会与所有的场景服务器和非场景服务器保持socket连接.

如何将玩家的角色信息从一个场景转移到另一个场景呢方法有二:1通过worldserver转发.
将场景A中角色相关的数据传递给worldserver,然后worldserver再传递给场景B2将场景A中的角色相关的数据存入数据库,发送指令通知worldserver,然后worldserver通知场景B读取数据库中角色数据.
除此之外,跟单个场景无关的操作也可以在worldserver上做,如帮会、组队、好友、聊天、邮件、交易等,当然我们也可以将这些操作分割到一个单独的服务器上去做.
吐槽八卦:关于master结构Google的Bigtable也是采用了这种master结构,一个masterserver和多个tabletserver构成的,Google的集群管理系统Borg也是一个Borgmaster多个Borglet.
Masterserver在其中都起资源调配的中心控制器作用.
逻辑/地图/场景/游戏服务器/Sceneserver网游的场景多种多样,但无非是三种:主城、野外、副本.
场景服务器是游戏服务器组中最核心的服务器,他负责整个游戏的逻辑运算,包括角色(包括PC、NPC)在游戏场景中的进入和退出、角色的行走与跑动、角色战斗、任务的认领等.
场景服务器设计的好坏直接影响到整个游戏服务器组的性能,直接影响到单服能承载的最大同时在线人数.
所以为了提高场景服务器的性能,我们需要尽可能将跟场景无关的逻辑运算分割出去,比如自动寻路、NPCAI、组队好友聊天等.
场景服务器应该是编码最复杂的模块,这么复杂的逻辑系统,如何设计架构和组织代码就成了一个很重要的事情,直接影响到代码易读性、易维护行、可扩展性.
场景服务器逻辑的驱动主要有两个:消息包驱动和定时器驱动,通过一个大循环来驱动整个事件逻辑.
游戏的逻辑服务器最好设计成单进程单线程的结构,因为场景服务器里面数据交互复杂,如果设计成多线程势必会涉及到死锁和线程频繁切换问题,代码逻辑反倒会更复杂,而且容易出bug且不容易调试.
为了提高多核cpu的利用率,我们可以将多个游戏场景放到一个服务器上.

有些场景人多,有些场景人少,我们如何做负载均衡除了限制玩家密度之外,我们在技术上有什么解决方法呢我暂时还没想到什么很好的方法,这里就不写了,先留着吧.
游戏中角色如何切换场景对于有缝地图来说一般通过NPC或传送点如何做到无缝地图无缝地图关键在于地图边界玩家数据的同步处理,遵循KISS原则,我们可以限定地图边界只允许行走,不允许战斗(PVP、PVE)行为,这样不同场景服务器之间数据的同步的复杂度就降低了很多.

消息广播场景服务器还要负责的一块比较重要的工作就是消息广播,将游戏世界状态同步给所有的client,保证每个玩家看到的游戏世界是一致的.
消息广播涉及到两个问题:1广播哪些消息2消息广播给谁对于第一个问题,需要广播的消息无非是:玩家或NPC的状态、环境状态等,我们可以拿一些游戏服务器源码(如Mangos、天龙八部源码)自行分析下,这里就不详细说了.
对于第二个问题:消息广播给谁如果每条消息都广播给所有的玩家,消息广播量是巨大的,也是没有必要的.
对于一个玩家来说他所关心的也只是当前屏幕大小的一块场景里的状态变化,所以每个玩家关心的场景是有限的,反过来对于一个场景状态的变化,对此感兴趣的client也有限的,我们将此区域定义为AOI(Areaofinterest),也就是说一个场景状态的变化我们只需要广播给AOI内的client即可.
下一小节会详细的讲一下AOI.
吐槽八卦:Mangos是一个WOW的模拟服务器,就是根据客户端和服务器通信的消息格式模拟WOW写的一个WOW服务器代码,是一开源项目,总代码20多万行.
当年还满怀信心的阅读了一些Mangos代码,但读起来实在太痛苦了,到处都是上万行的类,最大的一个类Player大约有三万行代码.
Mangos用了ACE网络框架,更是坑爹啊,一个ACE代码就20多万行,一帮学生搞出来的,可想而知,不出bug还好,遇到bug估计只有哭的份了.

《天龙八部》的代码我也阅读了一些,这里吐槽下搜狐畅游的《天龙八部》的代码质量:1代码冗余,复用的不好,特别是网络框架;2性能不够优化,有些算法设计的不好,如playerpool中找空闲节点;3可测试性不好,不容易写单元测试,主要是全局变量很多;4代码规范不好,一看就是没有好好codereview.
AOI(AreaOfInterest)所谓AOI(AreaOfInterest),大致有两个用途.
下面是直接引用云风的解释:"一则是解决主动NPC的AI事件触发问题.
游戏场景中有众多的NPC,比PC大致要多一个数量级.
NPC的AI触发条件往往是和其它NPC或PC距离接近.
如果没有AOI模块,每个NPC都需要遍历场景中其它对象,判断与之距离.
这个检索量是非常巨大的(复杂度O(N*N)).
一般我们会设计一个AOI模块,统一处理,并优化比较次数,当两个对象距离接近时,以消息的形式通知它们.
二则用于减少向PC发送的同步消息数量.
把离PC较远的物体状态变化的消息过滤掉.
PC身上可以带一个附近对象列表,由AOI消息来增减这个列表的内容.
在服务器上,我们一般推荐把AOI模块做成一个独立服务.
场景模块通知它改变对象的位置信息.
AOI服务则发送AOI消息给场景.
"怎么来维护一个所有位置动态变化的对象的AOI呢这是一个很好的算法问题,完全可以拿来做面试题了.
最朴素的方法:每次取某个角色A的AOI时,分别与其他角色计算距离,距离小于r的边放到AOI列表中.
所以计算所有角色的AOI的时间复杂度为O(N^2).
也就是每次请求某个角色的AOI的时间复杂度为O(N),如果N不是很大的话,应该可以接受.
N应该包括:PC和NPC和道具.
猜想下估计N就是几万到几十万的级别吧,呵呵,单次AOI计算量不是很大哈,但是我们要知道,AOI的计算是调用频率很密集的请求,所以当有大量调用的时候,性能可能就会成为瓶颈,看来我们还得进一步优化下算法.

为了进一步降低时间复杂度,我们采用打格子的方法,这种方法在李开复的一篇文章里好似提到过,文中还提到了采用树(开复老师指的应该是四叉树或八叉树吧)的方法组织格子.
简单点讲就是将场景分割成很多格子,每个格子维护一个格子里面的角色列表,当一个角色需要计算其AOI时,只需要跟此角色所在的九宫格里的其他角色计算距离即可,将N减到了很小,从而提高AOI计算的速度.
当有角色移动时,保证角色一次移动不会垮2个格子,所以每次只需要计算她是否还在当前的格子里,如果不在,则只需要计算是不是在相邻的另外8个格子里,如果是,则更新原所在格子和现所在格子里的角色列表,所以角色位置更新的整个过程的时间复杂度为O(1).
再优化下,可以加入AOI圆和格子的碰撞检查,9个格子中再去掉没有相交的格子,进一步减小了N的大小.

从上面的算法描述中我们有两个疑问:1格子应该多大为好呢格子太大,则需要计算距离的N比较大,时间复杂度高,如果格子太小,存储需要大量内存,空间复杂度高.
所以根据具体情况适当取舍,如果时间复杂度是瓶颈,我们就让格子小点,如果空间复杂度是瓶颈,我们就让格子大点.

2如果每个角色的AOI半径r都不同怎么办我们选取适当大小的格子存储,对于r比较小的AOI计算,采用九宫格,对于r比较大的AOI计算,采用25宫格,49宫格,以此类推,直到n宫格能够完全覆盖AOI角色列表.
云风还提到了一种"十字链表"的方法,但没有解释怎么做,我个人脑补一下应该是这样的吧:每个角色的位置坐标是两维的x和y(假设服务器存储的是2d地图,如果是3d可以再加一维z),我们将所有角色的位置分别按x和y排序,然后放到x链表和y链表上.
假设我们需要计算角色A(xa,ya)的AOI(AOI的半径为r),我们只需要分别在x链表中找到xa,然后向前向后找距离小于r的节点(节点集合记为listxa),同样在y链表上找到ya,然后向前向后找距离小于r的节点(节点集合记为listya),listxa+listya即为需要跟A比较的角色集合.
这种方法相比于打格子的方法进一步减小了N.
角色移动更新位置的时间复杂度取决于十字链表是怎么存储的,使用链表还是用数组,但不管怎样,只需要对比或移动很有限的几个节点即可(假设每次移动位置都是小距离移动,不存在瞬移).

AOI的计算应该是很影响场景服务器性能的,提高AOI计算的性能应该是很有必要的事.
但是现在就到这里吧,因为没有见到实实在在的性能报告(比如每1000次调用耗时、峰值每秒钟调用多少次、CPU利用率、带宽利用率等),凭空想也没太大意思.

吐槽八卦:关于算法有人说算法一点也没有用,工作中没用到过一个算法.
其实这个问题要看你做什么工作了.
如果写的都是上层业务逻辑代码,当然可能会一点算法都用不上,但如果做基础架构,势必会牵扯到算法.
还有就是有人认为面试面算法很没意义,其实Google的面试考察的基本上都是算法和编码,如果一个人在算法方面能做到极致,我想他其他方面也应该挺牛的,当然你可以说算法不牛的也可能技术很牛,当然没错,但Google追求的是招进来的都是牛人,而不是牛人都招进来.

讲一个我工作中确实遇到的一个问题:找出一个sentence的最优的TOPm个候选翻译.
假设有一个翻译系统,只能做短句的翻译,我们现在有一个长句,如果想得到长句的翻译,我们需要先将长句分割成N份,举例假设是N=3份,分别为ABC,我们分别将A、B、C拿给翻译系统翻译,返回的结果是这样的:A:(a1,0.
8)(a2,0.
7)….
(ax,0.
40)x个翻译结果,每个都有一个可信度(表征翻译质量)B:(b1,0.
9)(b2,0.
8)…(by,0.
45)y个翻译结果C:(c1,0.
85)(c2,0.
8)…(cz,0.
50)z个翻译结果我们如何快速得到长句ABC翻译可信度(所有短句翻译的可信度的和)最高的前m个结果比如可信度最高的翻译应该是a1b1c1,可信度为0.
8+0.
9+0.
85=2.
55,可信度第二高的翻译应该是a1b1c2,可信度为0.
8+0.
9+0.
8=2.
50.

再说一个吧,对象池如何实现才能做到new、delete时间复杂度低如何实现才能做到空间复杂度低有没有折中的办法这其实也是一个数据结构和算法的问题.
同步策略为了保证每个client看到的游戏世界是一直的,玩家的状态是需要在不同客户端之间同步的,其中位置的同步是最重要的一项.
最直接的同步方案就是客户端在每次发生位置改变时都向服务器报告,服务器再转发给周围的其他玩家,其他客户端将对应的游戏角色移动到新的位置上.
但是这样存在一个问题,每个玩家的位置都是自己先开始移动,一段时间之后才在其他玩家的客户端上表现出来.
如果只是希望每个客户端上看到的游戏对象都同时开始移动,那可以让玩家的每一步操作都由服务器确认之后再执行,这样误差将缩减到不同客户端之间的网络延时差.
但是显然的,这样的做法不可能真正被采用,因为这将使得玩家的游戏体验非常的糟糕.
有谁能忍受连每走一步路都要卡一下的游戏呢既然一定存在先后时间差,那就需要一种方法来让不同客户端上看到的玩家位置不至于有太大的误差,尤其是不能有影响到游戏公平性的误差存在.
根据误差出现的直接原因:时间差,我们应该能够想到一个解决方案,那就是让其他客户端设法弥补掉这段时间差内少走的距离.
这样的话也就要求我们的消息包中多带一个开始移动的时间数据,用于其他客户端在收到这个消息包时计算对应的玩家实体已经移动过的时间和距离.
我们以一个实际的例子来说明如何减少这种误差的影响.
假设玩家A以速度V从P1点去到P2点,A的网络延时为T1,在A旁边有个玩家B,他的网络延时为T2.
B收到服务器转发过来的移动包时,A在其自己的客户端上已经移动了T1+T2的时间,在这段时间内他自己已经走过了V*(T1+T2)的距离.
如果这时在B的客户端上开始将实体A从P1移动到P2,那显然两个客户端上看到的A的位置始终存在V*(T1+T2)的误差.

为了使A在B客户端上显示的位置与其实际位置的误差尽可能的缩小,一个简单的做法是直接将A的位置向前拖V*(T1+T2)然后开始移动,这样两者之间的误差便消除了.
但这样会使得客户端的显示的移动太僵硬,要让其看起来平滑一些,我们可以考虑使用一些算法,比如计算出A从当前位置走到P2点还需要的时间,然后加快其速度使其在规定的时间内到达P2点,这样A和B看到的最终时间是相同的,但中间过程还是存在较多误差.
另一种较好的做法是先让A以一个可接受的较快速度移动到其当前应该所在的位置稍前一点的地方,然后以正常速度移动到P2点,这样后面的移动情况与其实际移动情况基本吻合了.
如果我们对一次插值构造的移动路径的平滑度还是不满意,可以使用二次插值,构造一条更平滑的路径走过去.

从上面的同步策略描述中,我们发现还有几个问题需要解答:1采用键盘或虚拟摇杆(手游)移动的游戏如何同步呢上面的同步方案是针对采用鼠标点击来移动的游戏来讲的,因为他每次都必须直到移动到的下一个位置P2.
但是靠键盘或虚拟摇杆(手游)来移动的MMORPG中却没有办法采用.
移动消息都只能向服务器报告当前的坐标、朝向信息、速度、加速度等.
这类移动的位置同步其实也可以采用类似方案,服务器将移动玩家的当前位置信息广播给周围的其他玩家,当然其中也包含了时间戳.
当其他玩家收到这个移动包后,表示的是在过去的某个时间里该玩家移动到了这个位置.
如果只是简单地将其对应的实体移动到这个位置,那同样的,也存在位置误差.

与上一种情况类似,如果我们知道该玩家的移动速度,再通过数据包中的时间戳,假设该玩家还在以相同的速度朝相同的方向移动,那我们也可以预测出该玩家从开始移动到现在这段时间内他走了多远了距离.
我们也可以将其位置做适当的修正,并使其继续移动下去.
在这种情况下,只要没有收到玩家停止移动的消息,其他客户端上都会以最后一次收到的移动包的状态来继续模拟移动.

2如何计算网络延迟采用对时的方法,首先client向server发起对时请求,带上client本地时间t0,然后server收到之后回复当前的server的系统时间t1,最后client收到server的回复数据包,记录时间t2.
这样我们就可以算出client和server单程通信时间为rtt=(t2-t0)/2,client和server的时间差为delta=(t1-t0)-(t2-t0)/2=t1-t0/2-t2/2.
如果client所处的网络环境比较稳定的话,这个rtt和delta是基本可靠的.
client在之后的发包中带上本地的时间戳client_time,server收到client的包的时间为server_time,理论上client_time+delta+rtt应该等于server_time.
如果client_time+delta+rtt大于或者小于server_time,说明客户端的包提前到达或者卡了,当前的网络环境改善或者恶化了,需要重新对时.
可以设定当abs(client_time+delta+rtt–server_time)超过一个阈值时,才需要发起重新对时.
这个阈值设置的太小,会导致在网络稍微波动时,频繁的发起重新对时;如果设置的过大,就失去了网络对时的意义.
所以需要根据游戏的类型和实际情况来选择.
在正式运营的时候,还要考虑到外挂的因素,在server端校验client发包的时间戳,要保证大于之前发包的时间戳,并且与上一次发包的时间戳的时间间隔大于一个预先设定好的最小间隔.

自动寻路算法自动寻路现在应该是网游的标配了吧.
从我接触的网游来看大约有下面几种:1任务的自动寻路2寻找NPC的自动寻路3鼠标点击地图的自动寻路因此和游戏逻辑相关的数据计算都尽可能放在服务器,即使不得不放到客户端,服务器端也必须对这类数据有极其完整的校验措施.
所以自动寻路有两种处理方式:1所有自动寻址逻辑运算都放在服务器端,客户端只发送起始坐标和最终要走到的坐标,由服务器定时发送当前客户端应该走到哪个位置,这样可以完全避免客户端加速/穿墙/瞬移等外挂,但服务器负担很大.

2自动寻址放在客户端,由客户端按每步到达的位置顺序发送请求到服务器,服务器检查当前用户到达的位置是否合法,如果合法则返回一个成功指令;如果不合法则发送一个失败指令(或最后一次合法的坐标).
不过这种模式有一个致命缺点,就是很难控制用户是否使用加速外挂,因为考虑网络传输的不稳定,如果在短于允许的时间间隔收到两个移动指令并不表示就是使用加速而很有可能是网络lag造成的.

至于到底应该将自动寻路放到客户端还是服务器,服务器做多少工作,都应该视具体情况具体游戏来看.
常见的寻路算法有A*、waypoint、navmesh等.
网上有挺多这方面的详细资料的,这里就不做细致阐述了.
Navmesh好似很强大,桥洞、螺旋塔这样的复杂地图结构都能用navmesh算法来寻路.

吐槽八卦:0、1可以代表2d地图,那3d呢其实也可以用0、1,只不过是三维数组了.
当然有很多更高效的存储方式了.
NPCAI网游中玩家很重要的一个玩法就是做任务打怪升级,如果NPC没有一点智能,傻愣傻愣的,那玩起来也太机车,太没意思了.
所以设计智能NPC很重要.
下面我们简单罗列下在网游中的NPCAI:1NPC选择目标:首先获得地图上离该NPC附近的敌人列表.
根据敌人的强弱,敌人的远近,算出代价.
然后选择代价最小的敌人进行主动攻击.
2NPC逃跑:在呼吸事件里面检查自己的HP,如果HP低于某个值的时候,或者如果你是远程兵种,而敌人近身的话,则触发逃跑函数,在逃跑函数里面也是对周围的所有的敌人组织成列表,然后设计Judge()函数,先选择出对你构成威胁最大的敌人,该Judge()函数需要判断敌人的速度,战斗力强弱,最后得出一个主要敌人,然后针对该主要敌人进行路径的Judge()的函数的设计,搜索的范围只可能是和主要敌人相反的方向,然后再根据该几个方向的敌人的强弱来计算代价,做出最后的选择.
3NPC随机走路:这个并不推荐用复杂算法,因为NPC一旦多起来,CPU的消耗是很恐怖的,而且NPC大多不需要长距离的寻路,只需要在附近走走即可,那么,就在附近随机的给几个点,然后让NPC走过去,如果碰到障碍物就停下来,这样几乎无任何负担.

4NPC追随目标:这里有两种方法,一种方法NPC看上去比较愚蠢,一种方法看上去NPC比较聪明,第一种方法就是让NPC跟着目标的路点走即可,几乎没有资源消耗.
而后一种则是让NPC在跟随的时候,在呼吸事件里面判断对方的当前位置,然后走直线,碰上障碍物了用A*绕过去,该种设计会消耗一定量的系统资源,所以不推荐NPC大量的追随目标,如果需要大量的NPC追随目标的话,还有一个比较简单的方法:让NPC和目标同步移动,即让他们的速度统一,移动的时候走同样的路点,当然,这种设计只适合NPC所跟随的目标不是追杀的关系,只是跟随着玩家走而已了.

吐槽八卦:谈谈人工智能!
数据挖掘!
机器学习!
大数据时代到来,人工智能、机器学习、数据挖掘这些技术越来越受IT公司的重视.
这方面的互联网应用也很多,像豆瓣电台和书籍推荐功能、Googlenow(国内有人搞了个类似的叫"出门问问")、亚马逊的商品推荐功能(亚马逊还申请了一项专利是:可以在用户没有下单前就猜测用户会买什么并且提前将快递发出去,你说虎不虎)等等.
而且我发现国内这些出国去国外读计算机博士的大部分也都是读这个专业(起码我同学都是读这个专业),看来这个方向应该在未来几年会很火.
其实在我以前的项目里也是用到过相关方面的技术,下面就讲一讲:背景:有一个英语翻译的问答网站,用户将不知道如何翻译的英文句子放到网站上,期望其他用户帮助翻译.
问题:如何推荐给网站上的用户感兴趣的英文翻译问题这是一个典型的推荐问题,解决方法我使用了协同过滤算法:用户对A问题感兴趣,A问题与B问题具有相似的特征值,则把B问题推荐给他;用户A和用户B兴趣点相同,则将用户B感兴趣的问题推荐给用户A.
数据库根据http://en.
wikipedia.
org/wiki/Five-minute_rule5分钟原则,如果数据访问频率高于5分钟,就该放到内存里,而非硬盘里.
所以游戏里用到的数据都应该先加载到内存中,在内存中操作,所以数据的存储是使用文件还是数据库或使用什么数据库影响应该就不是很大了.

一般MMORPG系统的存盘策略:定时存盘.
就是过一段时间(比如5分钟)把在线有修改过的玩家数据,整个snapshot存下去(数据库也好,文件系统也好).
这样有两个主要问题:一到保存点,IO随机写暴增,数据库过载,玩家卡机;如果系统down机,数据就会有几分钟的回档.
而性能和数据可靠性则是矛盾的,存盘间隔过小,玩家卡机,存盘间隔过大,故障后数据回档时间长.
如何提高存储性能如何做到回档时间尽可能小还不造成数据库过载为了减小存盘间隔又不致使数据库过载,我们可以在数据库前端建立一个内存缓存,所有的存盘工作都在内存缓存中进行,然后均匀平滑的写入后端数据库(如mysql).
内存缓存在其中起到一个削峰和异步提高响应速度的作用.
其中内存缓存有很多了,Redis就是一个不错的选择.
但是当宕机之后,同样会出现内存缓存数据丢失的问题,所以我们将数据库隔离到一台独立的服务器(数据库代理服)上,这样场景服务器的宕机就不会影响到数据库了.
同时数据库代理服保持逻辑尽可能简单,宕机的可能性很小.
除此之外,数据库代理服还可以将sql执行语句抽象成数据库服务,避免了场景服务器中sql满天飞的问题.

说了这么多,其实我们还是没有完美解决场景服务器宕机之后部分数据丢失问题,因为即使存盘间隔再小也不是实时的,所以宕机总会有数据丢失.
技术上我们可以将比较重要的数据单独处理实时存盘(比如某个玩家打出来个nb的装备等),另一方面从运营上讲宕机毕竟是小概率事件,我们可以对用户适当的回档补偿就行了.

如果存储的数据量很大,我们希望进一步提高存储读写性能,我们可以从下面几个方面考虑:1mysql分库master、slaver主从备份,读写分离2mysql分表将过大的表分成多个3采用nosql分布式存储系统如何让玩家创建的角色能跨服玩家在一个服A内创建的角色是不能到另一个服B内玩的,这是现在大部分网游的标配限制.
猜想下原因可能有以下几个:1技术角度上,每一个服对应一个独立的数据库,所以数据无法流通.
如果真需要转服,需要玩家申请,然后由运营人员手动将数据复制过去.
2游戏策划平衡性角度上,这种跨服可能导致游戏世界的不平衡(新手、高手的比例等)3运营角度,如果可以跨服,可能会导致某些服挤爆,而有些服又没有人玩如果只谈技术,要做到角色跨服是很容易的,我们只需要将账号和角色相关的数据都存储在一个公共的数据库中即可.
这个数据库必须要高性能,支持所有玩家的登陆认证、数据存盘等工作,所以分布式数据库可能在这里就比较合适了.

什么是合服如何合服会遇到什么问题呢简单说,就是把2个服务器上的数据库合并在一个数据库,让2个服务器的玩家一起玩.
合服过程会遇到键冲突问题,举例:AB两个数据库,每个数据库有两个表,表结构都一样,分别是X表和Y表,Y的主键是X的一个外键,现在想将两个库中的数据合并成一个库两个表XY,如何做方法有二:重新修改主键和外键用服务器编码做主键的前缀,这种情况比较适合用字符串做主键的情况,例如我的一服表主键外键就是001GMxxxxxxxxxxxxxxxx.
二服就是002GMxxxxxxxxxxxxxxxx.
这样合服的时候,就不需要对数据进行预处理了,直接导入.
如果是用数字做主键的,可以为其中一个服的数据库中表的主键统一加某个值,让两个服的主键落在不同的区间内.
重新生成新的主键统一重新为两个库的表生成新的不重复的主键,并且保存旧的主键与新的主键的对应关系,然后利用这些对应关系再更新外键.
需要注意的事情:备份数据库,这样合并错了还有得救,不然就只剩下哭了写脚本执行而非手动敲代码执行,这样可以避免低级错误日志数据怎么存储游戏中存储的日志数据应该有两种:debug日志和运营日志.
我们需要做到以下几点:1支持海量的日志存储2支持高效的日志存储3具有易于分析的日志存储格式Debug日志采用本地文本文件存储方式,且只存储一周内的Debug日志.
运营日志使用Protobuf结构存储,这样方便之后使用各种编程语言来分析.
如果磁盘IO不是瓶颈,则运营日志采用先预存本地,然后定期通过网络转存到专门的运营日志服务器上.
如果磁盘IO是瓶颈,则运营日志可以直接通过网络发到日志服务器上,不预先存本地.

吐槽八卦:关于存储Google内部的存储系统很多,不下几十个,大部分都有自己特殊的应用场景,像Bigtable、Megastore是比较通用和常用的,其实mysql在Google也是比较常用,因为mysql很好的支持了分布式存储的一个痛点就是事务ACID(原子、一致、隔离、持久).
这也是为什么好多银行、证券交易所还费大价钱使用关系数据库(多为oracle)的原因了.

Google应该是一个对云计算研究的比较深的公司了,光看内部处理分布式问题的工具和框架的数量就知道了.
而且Google对整个互联网行业的技术输出也是比较多的,比如Hadoop就是模仿Google的分布式存储和计算技术架构做出来的,其实就是Bigtable、Mapreduce、Gfs的开源版本,像淘宝和腾讯的Tfs(两家都叫这个名字)其实就是类似于Gfs的东西.
Google在人才培养方面也比较出色,号称互联网行业的黄埔军校,想想Facebook公司的技术应该就是从Google跳槽过去的那些人撑起来的吧.

吐槽八卦:关于工具Google内部有很多工具、框架和库,所以快速学习新东西的能力变得非常非常的重要.
PS:当年花了半天的时间替另一个team的人整合各种工具写pipline还拿了peerbonus.
不只是Google,其实互联网都是如此,新技术层出不穷,掌握的技术过不了3年就过时了,如果不持续学习,90后小娃都能秒杀80后大叔,码农悲催就在此吧.
但是IT技术这么多,我们不能期望掌握所有技术,做技术应该追求的是:打通任督二脉,融会贯通,见招拆招,以无招应有招.
当然这需要多做项目多实践,但光靠工作经验还是不够的,因为做技术毕竟不像是从医那样靠经验吃饭,做技术更像练武功,还需要好的技术基础,内外兼修.
这就是像一些公司(如网易游戏)喜欢招应届生自己培养,不喜欢社招的原因了吧,招应届生可以挑挑拣拣招底子好的,保证质量,自己培养,社招就很难保证质量了.

吐槽八卦:关于宕机没有没有bug的系统,所以宕机是不可能完全杜绝的.
Google内部有一系列监控工具,服务器宕机之后会触发alert.
Team里的每个员工都要轮岗oncall,oncall的人不管周末还是休假都必须机不离手,时刻准备着,当然oncall也是有额外的工资的.

当年Team里的oncall策略是我设计的(用脚本语言写的),每两周一轮换,自动更新,不管新手、老手还是lead都要轮换oncall,每次oncall有三人:primary、secondary、tertiary,primary解决不了的或漏接的oncall,会自动转到secondary,以此类推.
Oncall更多的是责任,而不是任务(PS:没有人喜欢打杂,即便performance再差的员工,所以项目当中给teammember安排工作的时候,lead应该分发责任而不是任务,但有些lead怎么就是不懂呢),接到oncall之后不应该自己闷头去debug去解决,而应该迅速定位问题,交由相应的模块负责人去解决.

网络框架网络框架的好坏直接关系到游戏网络通信的性能,直接影响到单服能够承载的最大玩家同时在线人数,所以我们从下面这几个方面讨论一下游戏中用到的网络框架.
1TCP/UDP选择网游开发到底是使用TCP还是使用UDP,我只能说TCP能做的UDP也能做,UDP能做的TCP不一定做得到啊.
TCP、UDP都是在IP之上做了封装,只不过TCP做了很复杂的封装,保证数据包有序、可靠、拥塞控制的流模式,而UDP做了简单的封装,只保证一个数据包不被分割的完整地发送到对端.
如果不是实时性要求很高的游戏(如射击类游戏),我们完全可以用TCP(费那事用UDP模拟TCP干啥呢),但是如果是实时性要求高的游戏,则TCP就不合适了,要用UDP,为啥呢TCP流模式.
当我们发送小包的时候,它并不立即发送出去,而是将它缓存起来等待组合成一个大包之后一次性发送出去,这样数据包的实时性就很难保证了.
当然我们也可以设置通过"TCP_NODELAY"属性来禁止TCP数据包的缓存,实现实时发送数据包.

TCP丢包重传和保证包有序.
如果有一个数据包在发送过程中丢失,那么在此之前发送的数据包都要缓存起来,直到丢失的数据包重传过来才能一起接收.
有些时候我们可能只关心最新的数据包,这样做就没法保证实时性了.

2消息包格式如果使用TCP协议,为了处理粘包问题,消息包的格式应该是:消息长度+消息码+消息体.
当然如果要做到较好的纠错和容错,可以再加一个消息结束符或分隔符(如"$-$"),这样就可以利用消息结束符或分隔符跳过坏包了.

3传输数据格式数据格式很灵活,只要保证写入读出方便,推荐使用Google的protobuf.
网络传输数据格式有多种:对象序列化如Java中对象实现的Serializable接口,直接将对象作为数据交换格式,要求通信的两端必须使用同一种编程语言,且公用这个对象的类定义.
传输数据效率低.
二进制序列化这种方式传输效率高,但是序列化反序列化麻烦,要自己一点点的解析,繁琐而又容易出错,灵活性和可扩充性也不好.
数据传输格式是序列化后的二进制.
json、xml序列化格式容易定义,跨语言,序列化反序列化简单,但传输效率不高.
protobuf序列化GoogleProtocolBuffers(Protobuf)是一款非常优秀的库,它定义了一种紧凑的可扩展二进制消息格式,特别适合网络数据传输.
一条消息数据,用protobuf序列化后的大小是json的1/10,xml格式的1/20.
protobuf在效率、数据大小、易用性之间取得了很好的平衡.

4网络编程模型网游的网络通信模块是非常重要的,我们可以自己用epoll或iocp去封装自己的网络编程库,当然也可以使用现成的网络编程库,如ACE,libevent等.
不过大公司的话应该有自己比较成熟稳定的网络开发库吧,直接拿来用就好了.

有哪些网络编程模型请看UNP(UNIX网络编程)的第六章和C10K问题(如何让服务器支持高并发问题http://www.
kegel.
com/c10k.
html),总结下就是下面这5种:阻塞IO模型非阻塞IO模型多路复用IO模型信号驱动IO模型异步IO模型最常用的是多路复用IO模型:select/poll/epoll/kqueue/iocp,支持大量并发连接.
5内部不同server之间的调用为了保证足够的伸缩性,内部server(逻辑意义上的)之间的通信使用socket,即使是部署到同一台服务器上的两个server(逻辑意义上的).
当然为了进一步降低编码复杂度,还可以使用RPC或者消息中间件.
lua内嵌脚本在游戏中使用脚本主要是为了避免硬编码,可以实现游戏架构(引擎)和游戏内容的分离.
脚本主要用在npcai,任务系统,伤害计算等逻辑代码的编写上,这样做主要是为了灵活地控制游戏,使开发人员甚至是策划都可以随时改变游戏的逻辑,而不需要重新编译,做到可配置,易扩展,支持热更新.
脚本说白了就是支持较复杂逻辑判断的配置文件.

Lua脚本语言的优点就是小巧,核心代码不过一万多行,运行速度快占用内存少,可以很好地调用c/c++,也可以很容易的被c/c++调用.
所以很多大公司都是用lua脚本语言(如魔兽世界、愤怒的小鸟等).

吐槽八卦:关于编程语言国外的公司(像Google、facebook、twitter、square等)面试很少会考察编程语言方面的东西,大部分都考察算法、编码能力.
而感觉国内的公司正好相反,上来就先看你是用什么语言的,如果你说你不会java,那基本上就跟阿里无缘了.
其实编程语言真没那么重要,更重要的还是解决问题的能力.
打个比方,写小说重要的是文采构思,这跟你是用英语写还是中文、日语写没多大关系吧.

热更新当我们需要一个7*24小时工作的系统时,实现热更新就成了需要注意的要点.
热更新对于游戏这种需求多变,且需要和用户保持长连接的程序是比较重要的.
这样你可以在设计人员不断提出新的需求时,可以在不间断对用户的服务的基础上更新系统.
当然快速修补bug也是个很重要的用途.
做这样的系统,关键是各种服务要拆分开.
使用多进程的设计尤为重要.
当系统中的各个模块以独立进程的子系统形式出现时,我们只需要把子系统隐藏在连接服务器后,不跟玩家直接通讯.
大多数子系统都可以轻易设计成可以动态装卸的.
需要更新的时候只需要重新启动一下即可.
这里,数据服务分离也是很重要的.
绝大部分服务不应持有太多游戏数据,尽量减少重启服务器中内存数据持久化的带来的程序设计复杂度.
函数式编程语言中,热更新通常比较容易实现.
erlang,lisp都把热升级做为核心特性之一.
对于纯粹的请求回应式的服务,做热升级也相对容易.
比如大多数webserver,采用REST风格的协议设计的网站,重启服务器,通常对用户都是透明的.
中间状态保存在数据库中,改写了代码,把旧的服务停掉,启动新版的服务,很少有出错的.
吐槽八卦:关于软件更新Web天然支持热更新,因为代码逻辑是无状态,不保存数据,用户数据都保存在数据库中.
移动应用则不支持热更新,在每次更新代码之后用户必须升级应用才行,但在应用开发的初期代码更新频繁,或者开发者希望临时测试某个feature用户是否喜欢,不支持热更新这就带来了麻烦.
一种解决办法就是使用网页控件在app中内嵌网页,这样就支持热更新了,但是比起原生nativeapp性能和显示效果要差一些.
比如淘宝app首页就是这么做的.
Google一直期望让所有的事情都在网页中搞定,你很少看到Google出客户端应用,所以Google一度十分推崇html5,不过最后也不了了之了,当然还有chromebook.
在移动开发方面,Google几乎所有产品都有适合手机观看的移动版网页,但Google对移动应用的策略也在发生变化,慢慢转向原生移动应用的开发.
战斗系统和任务系统游戏当中的子系统很多:战斗系统、任务系统、技能系统、坐骑系统、宠物系统等,我认为最重要的两个系统就是战斗系统和任务系统,这直接关系到游戏是否好玩.
战斗系统是MMORPG中最复杂和最重要的玩法,在游戏所有的子系统中算是一个比较庞大复杂的模块.
战斗系统主要可以划分为两部分:与战斗属性有关的数值计算.
与战斗动作、特效有关的角色动作播放、特效播放与状态管理.
这两部分分别侧重于服务器和客户端,与数值计算有关的部分多需要放在服务器进行,因为客户端是不可信的,为了防止某些客户端利用外挂对数值进行非法的修改,保证所有玩家的公平游戏的环境,所以所有战斗数值计算都放到服务器进行,然后服务器将计算结果反馈给客户端.
对于战斗系统的第二点,它侧重于客户端的.
因为只有在客户端才需要动作的播放、特效的播放,而服务器时根本不关心此时角色的到底在播放什么样的动作,服务器只关心角色目前所处的是什么状态.
关于状态的类型,有移动、静止、战斗、击晕等等,这些状态将影响到角色的移动和战斗技能释放.
例如某些技能在角色移动时将不允许释放,处于击晕状态下将不恩能够移动或释放技能.

任务系统一般有一条主线多条支线.
主线体现世界观,讲述剧情,历史背景,塑造主角的成长历程.
支线营造世界氛围,烘托世界营造世界环境,以及地区性特点的营造.
按玩法又分为:找人找物、送任务道具NPC、杀怪、杀怪然后得到任务物品等.

吐槽八卦:关于《苍穹之剑》最近一直在玩《苍穹之剑》,在手机上玩mmorpg游戏感觉更爽些,当然有些人对在手机上玩网游嗤之以鼻.
说下《苍穹之剑》好玩的地方:1真3d,720p,中国风,画风好2操作流畅,打击感强3PvP即时PK4手机上玩操纵感更强性能优化1从哪些方面做性能优化服务器四大资源:Cpu,内存,带宽,数据库,所以我们上面四个方面来做性能优化.
首先要找出性能瓶颈,然后从宏观到具体,从架构到算法到代码行,逐步优化.
当然在操作的过程中,经常是反着来的,先优化代码行和算法,然后才是架构,为什么呢因为架构不敢轻易动,动了怕出bug.

下面是网易游戏的开发人员总结的资源消耗排名,优化的时候可以先从排名靠前的开始做:CPU消耗排名:AOI同步,网络发包,技能/BUFF,定时器频率内存占用排名:玩家对象(物品),网络数据包带宽消耗排名:位置信息,对象加载,状态机消息主要的优化方法提示:IO操作:IO操作异步化、线程化数据结构与算法:排序、查找性能、冗余数据结构重复计算:缓存结果即时计算:提前准备2是否可以使用STL不建议使用mapsetlistvector容器的原因是他们使用的内存分配方法allocator容易产生内存碎片.
如果非要用这些容器,最好用支持内存池的allocator替代默认缺省的allocator.
3关于静态池技术关于池化技术,简单点来说,就是提前保存大量的资源,以备不时之需.
对于线程,内存,数据库的连接对象等等,这些都是资源,程序中当你创建一个线程或者在堆上申请一块内存时,都涉及到很多系统调用,也是非常消耗CPU的,如果你的程序需要很多类似的工作线程或者需要频繁的申请释放小块内存,如果没有在这方面进行优化,那很有可能这部分代码将会成为影响你整个程序性能的瓶颈.
池化技术主要有线程池,内存池,连接池,对象池等,提前创建,重复使用.

网游服务器长时间运行,频繁的newdelete会造成大量的内存碎片,而且网游服务器有一个特点:各种对象一般有个上限值,所以我们可以提前分配内存池或对象池,减少内存碎片.
游戏测试游戏的测试名头真多啊(内测、封测、公测、不删档x测、删档x测),感觉很多都失去了原本的意义,更多的是为了宣传.
我们讲讲在未上线之前研发团队要做的哪些测试吧.
1压力测试自己写一些机器人来测试服务器能承载的玩家压力2模拟测试模拟各种网络环境来测试游戏在不同网络环境下的表现3产品测试测试是否跟策划心中要做的游戏效果是一致的4单元测试白盒测试代码bug5黑盒测试测试游戏bug吐槽八卦:关于Google的测试Google内部产品的开发十分看重unittest,覆盖率也有要求,当年我们做的一个项目的unittest覆盖率达到80%,所以有时候写100行代码,要写200行测试代码,烦人啊,不过这样bug确实少了很多,以至于最后launch都不需要专门的测试团队来做测试(当然Google也是有测试团队的,不过他们主要负责测试框架的编写维护吧,不做实际的测试工作).
除此之外,还要写integratetest,不过这个好似不是必须的.
产品在launch之前也要经过内部launch,就是让公司的人先用用试试,然后是可信launch,就是选择部分可控用户来测试,然后才是公开launch.
而且launch的review流程十分长,我们的有个项目年初就准备launch,直到年末还没launch出去.

极光KVM美国美国洛杉矶元/极光kvmCN7月促销,美国CN2 GIA大带宽vps,洛杉矶联通CUVIP,14元/月起

极光KVM怎么样?极光KVM本月主打产品:美西CN2双向,1H1G100M,189/年!在美西CN2资源“一兆难求”的大环境下,CN2+大带宽 是很多用户的福音,也是商家实力的象征。目前,极光KVM在7月份的促销,7月促销,美国CN2 GIA大带宽vps,洛杉矶联通cuvip,14元/月起;香港CN2+BGP仅19元/月起,这次补货,机会,不要错过了。点击进入:极光KVM官方网站地址极光KVM七月...

印象云七夕促销,所有机器7折销售,美国CERA低至18元/月 年付217元!

印象云,成立于2019年3月的商家,公司注册于中国香港,国人运行。目前主要从事美国CERA机房高防VPS以及香港三网CN2直连VPS和美国洛杉矶GIA三网线路服务器销售。印象云香港三网CN2机房,主要是CN2直连大陆,超低延迟!对于美国CERA机房应该不陌生,主要是做高防服务器产品的,并且此机房对中国大陆支持比较友好,印象云美国高防VPS服务器去程是163直连、三网回程CN2优化,单IP默认给20...

RFCHOST - 洛杉矶CN2 GIA VPS季付23.9美元起 100Mbps带宽

RFCHOST,这个服务商我们可能有一些朋友知道的。不要看官网是英文就以为是老外服务商,实际上这个服务商公司在上海。我们实际上看到的很多商家,有的是繁体,有的是英文,实际上很多都是我们国人朋友做的,有的甚至还做好几个品牌域名,实际上都是一个公司。对于RFCHOST商家还是第一次分享他们家的信息,公司成立大约2015年左右。目前RFCHOST洛杉矶机房VPS正进行优惠促销,采用CN2优化线路,电信双...

游戏代理服务器为你推荐
伺服器win7重要产品信息指南支持ipad支持ipadIOJsios8tcpip上的netbios网络连接详细信息上的netbios over tcpip是什么意思?x-routerx-arcsinx的等价无穷小是什么?win7关闭135端口win7下怎么关135和8909端口csshack针对IE6的CSS HACK是什么?win7还原系统win7系统怎么恢复出厂设置
安徽虚拟主机 php空间租用 最好的空间 京东商城双十一活动 微信收钱 bgp双线 服务器是干什么用的 winserver2008r2 最新优惠 西部数码主机 跟踪路由 戴尔主机 qq空间论坛 腾讯qq空间登录首页 qq空间登陆首页 tftp服务器是什么 免费服务器代理 灵动鬼影实录2 汽车摇号申请网站 更多