上文: 网络游戏架构的前世今生——计算篇
3.4 非会话游戏架构
还记得什么是非会话游戏吗?非会话游戏突出的特点就是,这类游戏构造出一个虚拟的世界,这个世界会随着时间的流逝进行演变,RPG(角色扮演类)游戏就属于这个类别。早期的RPG主要以单机虚拟世界为主,后来演化出一个子品类 MMORPG (MMO 即大型多人在线)。MMORPG早从上个世纪末开始就有非常多耳熟能详的作品,热血传奇、魔兽世界、奇迹、暗黑破坏神系列、梦幻西游等,也衍生出大量的端游、手游、页游作品。可以说页游最辉煌的时候,这类游戏占据了大头,直到如今,不少游戏或其衍生品依然在持续运营,玩家群相当广泛。
从技术角度来看,这类游戏的重点是在服务器上构造出一个虚拟的世界,所以世界的内容越多越丰富,就会越多的消耗服务器的CPU和内存资源。当玩家分布在虚拟世界的各个角落时,服务器需要实时计算虚拟世界的演化,并把“结果”传送给不同的玩家客户端。
在MMO游戏中,单个玩家的客户端只需要知道自己需要知道的信息即可,可以理解为“视野”,但这里不是指玩家视觉能看到的区域,而是一个可被感知的范围,称之为 AOI。在主流 AOI 实现的方式内,很容易出现“超距挂”、“透视挂”等客户端作弊手段 ,其本质是更多的解析服务器传来的消息,通过外置渲染将信息绘制在屏幕上,从而让玩家获得游戏设计内不具备的信息,简化游戏难度。
当我们想要构造的虚拟世界内容不多时(地图可以很大,但这里主要看动态的部分),且单服承载的玩家数量不多,我们可以把一台 物理机/虚拟机 与一个游戏服一一对应,这种架构设计起来和上文中很接近,不同点在于,每个服务器的状态信息需要高效的备份存储。在项目组技术力不足或者架设私服时,通常都会采取这种做法。缺点也很明显,内容匮乏与频繁的滚服。
如果我们想要制作一款内容足够丰富的MMORPG,类似于魔兽世界,我们应该怎么做呢?首先应该意识到,采购性能配置更好的物理机也有穷尽的那一天,垂直扩展是会受到当代硬件整体水平影响的,那我们必须迈出水平扩展的那一步,将一个大世界拆分成有限个小世界,分别在不同服务器上进行运算。
看似完美解决了这个问题,但考虑这样一个场景,当玩家在这些小世界中穿梭会发生什么呢?由于这些小世界运行在不同的服务器上,无论程序实现的再怎么完美,都无法避免切换服务器导致的卡顿问题。当然,我们有一些游戏设计的方案,能够降低玩家对这个问题的感知,经典的做法是加载地图。当然加载地图大部分时候是用来解决客户端场景切换设计方面的问题,但加载地图loading界面的时间,足够服务器“瞒天过海”完成切换。
问题又来了,如果我们想要制作的是一款无缝大地图游戏呢?魔兽世界就是这样划时代的作品。我们可以巧妙的切分一张大地图,使得存在幽灵(ghost)区,巧妙的解决上述服务器端遇到的问题。当然如果存在超远距离传送的设计,超远距离传送的前摇需要大于切换服务器的时间。
客户端用来实现无缝大地图涉及的技术更杂更广,本文不做展开,有兴趣的朋友可以自行查阅相关资料。
上述是理论的方案,有成熟的框架可以直接用吗?如果你做过游戏开发,很可能听说过(或是正在用)BigWorld 框架,魔兽世界早期、大量游戏作品都是采用这一框架。而 BigWorld 的核心理念,其实就是上述理论上更进一步,游戏场景分成多个小块(Cell),不同的块运行在不同的服务器上,这些块的划分很可能是不均匀且动态的,根据玩家密集程度动态调整块的大小。从程序实现上,采用了 Actor 模型,将每个游戏对象抽象为一个个独立的 Entity,其他服务器及客户端都是通过消息的方式与这些 Entity 进行交互。
从一个架构师的角度来看,放在如今 BigWorld 也是一个非常优秀的游戏框架,但它有一个很大的问题——开发时间很高,学习成本也相当高。我曾用这个框架写过游戏,开发过程相当复杂,维护这种老项目需要花费数月的前置时间去学习了解(不仅仅是需要学习框架,还需要学习公司内前人对框架的改造和业务实现),才能真正自如的去改动代码增添新功能。这对于当下的“游戏需要高频迭代及优化”的市场需求是背道而驰的。而这份经历也让我越发感受到,什么是一个真正优秀的架构?今天的我认为,能适应市场需求、能落地产出的才是真正优秀的架构。在项目里,我们必须要把理论和实现结合、把理想和现实结合,才能设计出适合项目组开发的架构。
这个专栏写作也是一直本着这种目的。在这里我不分享最佳实践,不分享如何产出顶级的应用,而是能让项目组招三流的程序、写二流的代码、出一流的应用,这也是我研究并实践微服务架构的最终目标。我认为一个项目做到顶级很难,需要起码一流的团队,但完成一个一流的项目却不难。所以很多时候必然会在合乎理论和容易实现间做出妥协。
BigWorld 衍生出一些改进版框架,KBEngine 是我用过的其中一个,做游戏服务器性能上确实没问题,项目最后上线也能承载很多玩家。当然缺点也和 BigWorld 一样,虽然支持了 Python 降低了不少开发难度,同时支持了热更,但实际的学习门槛并没有降低(甚至多了一些 Python 的内容需要掌握),这或许是重量级框架的通病。
这里我原本准备介绍 skynet 框架,skynet 是当前的主流框架之一,大量lua体系游戏公司采用。云风大神的博客给了我不少灵感和领悟,但我本人没有在实践中使用过 skynet,并不能给出实际项目中的评价。感兴趣的朋友可以自行查找资料学习实践。