package
0.0.1
Repository: https://github.com/yxinyi/ycserver.git
Documentation: pkg.go.dev

# README

无缝大地图设计

无缝大地图服务器与非无缝大地图设计区别

对于 普通的MMO 玩法来说, 往往有一个 map 对象来承载地图上数据,在每帧内对这些数据进行处理来完成地图上需要发生的逻辑,玩家其实也就是挂在对象上的一个数据,在地图切换时,往往玩家行走至地图上一个传送点上开始切图,如果发生了地图A切换到地图B的情况,从内存角度来说,也只不过是将 mapA 上的玩家对象剪切至 mapB 对象上。

那么对于无缝地图来说,在地图切换这部分,其实也没有太大区别,可以理解成传送点变成了传送区域,地图A的边界的所有边缘都可以进行地图切换,从mapA到mapB的过程中也是通过剪切内存来处理玩家的数据。

但是与非无缝大地图不同的是,当玩家处于 mapA与mapB的边缘时,虽然玩家数据在mapA上,但是mapB上的玩家也必须能看到处于mapA的玩家,且 mapA 地图上的玩家与 mapB地图上的玩家也可以像在一张地图上一样进行交互,战斗。

而这个跨进程交互就是无缝大地图的难点了。

从单进程说起

在mmo的地图逻辑中,玩家需要与当前场景的对象进行交互,比如 NPC ,怪物,场景物品,且这些对象往往是对全地图的玩家开放,也就意味着,一个对象的状态发生改变时,也需要对全地图的玩家进行广播,才能让发起主动交互玩家外的玩家获取被交互对象的最新的正确状态,基于此来实现各种效果,如 怪物死亡,NPC移动,场景物品的掉落拾取,技能释放等逻辑。

那么在上述需求的前提下,我们要怎么进行同步呢?

最简单方法是,当一个对象发生变化时,可以遍历当前地图的所有玩家对他们进行消息同步来实现我们的目的,但是显而易见我们可以想象到这个方案的弊处,如果一个地图大小为1000X1000,玩家屏幕大小为10X10 那么当玩家处于地图左上角时,右下角其他玩家的对象操作,其实我们是不关心的,但是却依然进行了同步我们在进行游戏行为时更关心的是我们当前屏幕能看到的对象,且一个地图如果有100个玩家,每个玩家1秒钟都要进行一次行为,那么一秒钟的消息数量即为 100 * 100 达到1万条,这也显然是有很大的优化空间的。所以有了AOI的说法。

AOI 即 arena of interests ,感兴趣的区域,其实现方案不在本文的讨论范围内,主要有 灯塔,九宫格,十字链表 法三种,各有优劣,但说到底,这些都是手段,我们还是要探究为什么能解决上一段提出的优化,简单的了解思路后即使不进行实现,我们也可以知晓其原理,其会将地图进行分割,并只找出自己感兴趣的区域,在一个对象发生变化后,也只同步给周围的对象,虽然从复杂度来说也算是 n^2,但是由于同步的玩家变少了,从原来的 100*100 缩减成 5*5 * N甚至更低,有一个数量级的优化,也就能提高单地图的逻辑承载上限。

不过即使有各种优化,包括多线程级优化,却永远无法突破物理机的限制,即使单进程实现了1000张地图逻辑,那他也会在第1001张地图的时候表现出瓶颈,因为无论是多么高的配置,单机的承载能力是有上限的。在此限制前提下,也就是意味着使用单进程来实现无边界的无缝地图的服务器逻辑是不可行的。

那如何完成我们的无缝大地图的服务器框架,我曾在一段时间内反复思考这个问题,有想出一些方案似乎能解决,但没有时间去实现,且也想更深入的思考,直到最近看了kbengine 的设计思路后,才发现自己的方案已经有人实践并证明了其可行性。

核心点就2个,一个是分布式AOI,另一个是主从数据

由于单进程的物理限制,一个可以无限扩展的无缝大地图一定会发生两张相邻的地图可能被部署在两台物理机上的情况,也就以为着当玩家在两张地图边缘时,要怎么处理其行为,以及如何让边缘的玩家知道他的动作。

需要解决的问题

先试想一下玩家在地图边缘时需要做些什么事情

一个是玩家的视野,在两张地图边缘处也是要有玩家视野控制的逻辑,也就是我们的AOI逻辑需要独立在地图逻辑之外,也就是一个AOI可以控制多张地图逻辑。

一个是玩家间的交互,在边缘时玩家间的战斗处理,如果两个进程的玩家发生交互该如何处理,该哪个进程处理,该如何通知.

分布式AOI

GHOST