Home

Awesome

SGMemory

这是一个用来实现内存快照同步的技术方案。

这个项目是一个验证项目,其中逻辑并不是完整可商用的状态(商用级逻辑也不大可能开源哈)。但是正因为如此,它们的逻辑非常精炼简洁,去除了非常多烦杂的细节,方便有兴趣的同学去学习和理解。

1. 基本目的

1.1 对进程A中的一块内存生成快照。

1.2 对该内存快照进行网络传输,或者本地存档。

1.3 在进程B中加载该内存快照,然后恢复内存快照里的所有游戏对象,包括游戏对象之间的依赖关系。

2. 应用场景

2.1 帧同步游戏的断线重连

当客户端断线或者重启时,服务器可以将某个时刻的内存快照下发给客户端。将客户端的逻辑层直接恢复至该时刻,然后再在此基础上追帧到当前帧。

断线重连

2.2 小内存系统的全状态同步

我们知道帧同步在MOBA和FTG游戏中被证明非常有效,但是帧同步的限制也很明显:

在有些情况下,状态同步会比帧同步更友好。但是,状态同步有一个最大的问题就是,你要定义好需要同步的状态,在实现网络同步模块时需要关注业务细节。而状态同步而可以帮助你忽略具体的状态细节。在小规模游戏中,或者某些模块(比如物理模拟)中,其逻辑层对内存的占用比较小,就可以考虑对整块内存进行同步。

全状态同步

2.3 单机游戏本地存档

对于单机游戏而言,本地存档是一个非常重要的功能。很多本地存储方案都是需要收集所需存档的状态,非常繁琐,与具体业务强相关。如果通过对整块逻辑内存进行存档,无疑可以极大简化存档和恢复的逻辑。

全状态同步

3. 基本原理

其基本原理就是对逻辑内存和逻辑对象单独管理。这里需要小心划分逻辑层与表现层的界限,对逻辑层的所有对象构造和内存分配都应该单独管理。所有表现层对逻辑层的依赖,都应该是基于对象模型指定的依赖方式(比如句柄),而非直接指针依赖。而逻辑层对表现层,则不应该有任何依赖(这是最基本的软件工程原则)。

总的来说,整个系统分为2部分:

3.1 内存管理

所有逻辑内存都需要单独管理,与引擎通用内存管理区分开。

为了实现较高的内存管理效能(性能与损耗),可以参考成功且成熟的商业引擎的通用内存管理方案。当然,这些商业的内存管理方案,其基本原理也都可以在《游戏引擎架构》一书中找到。这里无须赘述。

重点是,这里的内存管理,需要考虑到内存恢复时,如何恢复其内存结构。现代内存管理器都会将内存结构信息与待分配的自由内存共用内存块。所以在快照恢复过程中,其原始的内存结构是基于原始进程的,需要恢复成在当前进程有效的内存结构。

3.2 对象管理

内存快照恢复的重点是如何恢复对象实例,使对象实例在新的进程中依然有效。

那么很显然,需要对这些对象中的指针属性进行恢复。并且,需要防止逻辑层之上的表现层通过指针直接依赖逻辑对象。于是,需要实现如下特性:

全状态同步

4. 项目说明

这个项目是基于CMake组织的。建议先对CMake有所了解。

如果不想关注CMake的细节,也可以直接执行Build.bat。

欢迎 Fork & Star.