Games104_02_引擎分层架构
a). 引擎架构分层简介
- Tool Layer
- 打开一个游戏引擎会直接看到各种类型的编辑器。这个直接和开发者进行交互的层称为工具层(tool layer);
- Function Layer
- 在工具层下面包含功能层(function layer),用来实现游戏的渲染、动画、交互等不同类型的功能;
- Resource Layer
- 在此基础上还需要资源层(resource layer)来管理各种各样的场景美术资源;
- Core Layer
- 再下一层是核心层(core layer),它包括支持游戏渲染、动画、物理系统、内存管理等不同系统的核心代码;
- Platform Layer
- 最底层是平台层(platform layer),一般包括各种图形API、输入设备支持以及不同游戏平台的底层代码;
b). Resource Layer
b.1). Asset and importing
导入素材,转换为引擎便于使用的高效类型(如PNG、JPG转换为DDS)。素材转换为Asset,如几何模型、纹理、声音、动画等。同时,也会有相应的Composite Asset定义资产间的引用关系(类似Unity的Prefab)。资产会有相应的GUID(全局唯一标识符,Globally Unique Identifier)进行识别和管理。
b.2). Runtime Asset Manager
- 资源层需要对各类资产进行动态实时的管理,该功能通过handle(Link to ?)系统实现。
资源层核心:管理资产生命周期(Life Cycle)。
策略:
- GC(Garbage Collection);
- 动态/延迟加载;
c). Function Layer
功能层用来实现游戏的核心玩法。某种意义上讲功能层的作用类似于一个时钟(tick)用来控制整个游戏世界的运行,在每个时钟周期内功能层需要完成整个游戏系统的全部运算。
Tick会依次调用两个函数:tickLogic()
以及tickRender()
来分别更新系统的状态和并把图像绘制到屏幕上。这里需要注意逻辑的计算是严格早于渲染的,编程时也要注意不要把它们混到一起。
为了提升游戏引擎的计算效率现代游戏引擎往往会通过多核的方式来充分利用CPU计算的资源。未来的游戏引擎架构一定会向多核并行的方向上发展,因此在设计引擎时最好从多核的角度进行思考。当然如何管理计算任务之间的依赖仍然是一个难点。
d). Core Layer
核心库:包括高效的数学库、数据结构、内存管理(Memory Management)等。
核心层的数学库和通用数学库的一大区别在于游戏引擎对于计算的实时性要求更高,有时我们甚至可以牺牲一些计算精度来换取计算效率的提升。同时核心层数学库还大量使用了CPU的SIMD指令,这样可以极大地加速矩阵和向量的计算速度。
数学库之外核心层还需要包含各种常用数据结构的实现。
核心层最重要的功能是实现内存管理(memory management),使得运行时内存碎片尽量少,访问效率尽量高,从这个角度看游戏引擎的功能非常类似于操作系统。在游戏运行时往往会直接申请一大片内存空间然后通过引擎而不是操作系统进行管理,这样可以提升系统的运行效率。
- 数据尽可能存放在一起(Memory Pool)
- 数据尽可能顺序排布,顺序读取(Reduce cache miss)
- 数据的读写尽量批量进行(如通过Memory alignment)
e). Platform Layer
为了克服不同平台对于代码的限制,我们需要平台层来提供对不同操作系统和硬件平台的支持。这样我们就只需要一套代码就可以在不同的平台上运行程序。
不同的平台往往使用了不同的图形接口,为了统一代码游戏引擎的平台层提供了RHI(render hardware interface, 如SRP)作为通用的图形编程API。
RHI包含了统一套程序在不同图形API(Vulkan、DX11、DX12等)上的实现,这样上层的图形应用中就可以使用统一的一套API进行编程。
f). Tool Layer
除了游戏引擎自己的开发工具外一般还需要导入其它软件和开发工具的资产,这就需要Asset conditioning pipeline(起到如导入导出的作用)来提供不同资源导入游戏引擎的统一管线。可以说编辑器和asset conditioning pipeline共同构成了游戏引擎的工具层。
g). Why Layered Architecture?
- 上层可调动下层,下层无法调动上层;