游戏引擎层级结构
游戏引擎层级结构
概述
工具层 (Tool) 包含各种编辑器,比如动画编辑器、材质编辑器、场景编辑器
功能层 (Function) 涉及到所有使游戏运行和互动的基本功能。这包括渲染(Rendering\Camera\HUD)、动画、物理模拟、用户输入(Input)等。
资源层 (Resource) 主要负责加载、管理和优化游戏使用的各种资源。
核心层 (Core) 是游戏引擎的基础组件,为其他层提供支持。它包括基本数据结构(如列表、哈希表等)、数学运算(如矩阵、向量运算)、内存分配等。
平台层 (Platform) 为不同的操作系统(macOS\Windows\Linux\iOS)、硬件(AMD\Intel\Nvidia)和分发平台(Steam\EPIC\Xbox)提供抽象,使游戏引擎可以在多个平台上运行。
第三方插件层 (Middleware and 3rd Party Libraries Layer) 包含各种第三方的中间件,比如Havok开发包、NVIDIA Physx物理引擎、wwise\criward声音等等。
为什么要采用分层结构(Layered Architecture)?
为了降低复杂度
通过将系统分割成不同的层次,可以使每一层都只关注其特定的功能和职责。
解耦
分层结构确保每一层都只依赖于它下面的层次,而不是横跨多个层次。这减少了层之间的依赖性。
工具层(Tool Layer)
让每一个人都可以开发游戏。是生产力的工具。它允许团队成员在没有编程经验的情况下快速测试和调整游戏的各个方面。
并且游戏引擎的工具需要能够处理和显示各种数字内容,包括模型、纹理、动画、声音等。这些内容通常是在专业的DCC工具(如Maya、3ds Max、Blender、ZBrush、Photoshop等)中创建的。
当美术设计师或其他团队成员使用DCC工具创建内容时,这些内容首先被保存在这些工具的特定格式中(例如,.mb、.max、.psd等)。为了让这些资源能够在游戏引擎中使用,需要有一个工具或插件将它们从DCC格式转换为引擎可以识别和优化的格式。这就是导入器的角色。
虽然游戏引擎的核心通常使用C++编写,以实现最佳性能,但工具层可以使用其他更高级和灵活的语言或框架,如Python、C#、Qt或Web技术。
功能层(Function Layer)
使游戏世界活跃起来。主导着游戏的更新(Update)、渲染(Render)、物理模拟(Physic)和输入处理(Input)等主要功能。
在大多数游戏引擎中,"Tick"是游戏的主循环,它负责更新游戏的所有逻辑和渲染操作。每次循环都会对游戏世界进行一次“Tick”,以确保所有的对象和事件都得到正确的更新。
深入了解Tick:
逻辑层(Logic):逻辑层Tick主要处理游戏逻辑,包括角色的动作、AI决策、游戏事件等。
渲染层(Render):渲染层Tick负责将游戏世界渲染到屏幕上。这包括处理所有的图形和视觉效果,以及确保每个物体都在正确的位置和状态下绘制。
功能层由于其内容的庞大和复杂性,经常会与具体的游戏内容混淆在一起,这导致了边界模糊的情况。例如,引擎内部的相机功能可能仅仅是为了渲染,但游戏设计师可能需要对其进行更多的操作,如添加特定的动画或效果。
早期的游戏引擎多数是单线程的,这意味着所有的任务都在一个主线程上串行执行。现代游戏引擎开始采用多线程技术,将不同的任务分配到不同的线程上并行执行。例如,逻辑和渲染可以在两个不同的线程上并行执行。资源加载也可以放到后台线程中,以避免阻塞主线程。物理模拟和动画更新等也可放在其他线程上。
资源层(Resource Layer)
资源层负责管理和提供游戏所需的所有资源,如模型、贴图、声音和其他内容。
其中就涉及到资源的格式转换。当从各种资源编辑软件中导出数据时,这些数据可能包含很多冗余信息或与游戏无关的内容。资源层负责将这些原始数据转换成为引擎所需的高效格式。例如,一张贴图可能需要从常见的 JPEG 或 PNG 格式转换成为更适合在GPU上使用的 DTS 或其他特定格式。
并且资源之间存在引用关系。例如,一个模型可能引用了特定的材质、网格和骨骼动画等。而这些材质和网格又可能引用了其他的贴图、着色器等。为了维护这种引用关系,每个资源通常都会有一个唯一标识符(GUID)。
一个大型项目需要做到高效的实时资源管理。这涉及到资源的查找、加载、卸载和缓存等操作。
此外还需要管理资源的生命周期。引擎需要确保在资源不再需要时能够及时释放它们,以避免浪费内存。一些游戏引擎采用垃圾回收机制来自动处理不再使用的资源。但这种机制可能会引入性能开销,特别是在需要处理大量资源的游戏中。因此,一些引擎和游戏项目可能选择实现自己的资源管理策略,如"零GC"。
异步加载技术被很多引擎所采用,即在后台线程中加载资源,而不阻塞主线程。
渐进式加载是另一种常见策略,允许资源逐步加载和显示。例如,当加载一个复杂的3D模型时,引擎可能首先加载并显示其低分辨率版本,然后逐渐增加详细信息,直到整个模型完全加载。
核心层(Core Layer)
这一层可以说是引擎的基石,为上层的所有逻辑提供一个基础,如数学库、数据结构和内存管理等。
数学库是其中非常重要的一层。通常,线性代数、三角学、几何和统计学等领域的算法都需要非常高效地运用在游戏引擎中。为了满足游戏实时性的需求,引擎需要使用到一些优化技巧来加速数学计算。例如,Magic Number 是一种快速估算方法,可以在牺牲一定精度的情况下大幅度提高计算速度;SIMD(Single Instruction, Multiple Data) 通过在一个操作中处理多个数据项来提高计算效率。
游戏开发中需要使用到各种数据结构,如数组、链表、队列、堆、树、图、栈和哈希表等。
高效的内存管理是确保游戏流畅运行的关键。一般通过自定义的内存分配器来减少内存碎片,尽量确保相关的数据存储在内存中的相邻位置,以提高缓存的命中率。最后通过一次性处理多个对象的回收和重新分配来提高效率。
核心层需要特别关注效率、稳定性。这一层的代码通常比较稳定,不会频繁修改。它为上层功能和内容提供了必要的支持和服务。这一层的设计和实现要求高度的专业技能和经验,因为任何小的错误或不足都可能对整个引擎的性能和稳定性产生严重影响。
平台层(Platform Layer)
平台层的职责是为引擎其他部分提供与特定硬件或操作系统平台无关的接口。
游戏引擎的目标是跨平台,意味着要在多个硬件和操作系统上运行。不同的平台有各自的特点和限制,例如文件系统、内存管理和输入输出处理等。平台层的作用是为上层提供一个统一和抽象的接口,屏蔽平台之间的差异。例如:Windows 使用反斜杠(\)作为路径分隔符,而 macOS 和 Linux 使用斜杠(/)。
不同的平台支持不同的图形API。例如,Windows 主要支持 DirectX,而 macOS 和 Linux 支持 OpenGL,Android 还支持 Vulkan。Render Hardware Interface (RHI) 是一个中间层,它为引擎提供了一个统一的图形API接口,将具体的图形API(如DirectX或OpenGL)隐藏在这个中间层下面。这使得游戏开发者可以针对一个统一的接口编程,而不用担心底层的图形API细节。
不同的游戏平台有其特定的硬件架构。例如,主机游戏平台如 PS3 有其特定的CPU(PPU)和GPU(SPU)结构。某些硬件可能有专门的硬件单元来执行特定的任务,如音频处理或物理模拟。平台层可以提供接口,允许游戏利用这些专门的硬件单元,从而提高效率。例如,英伟达的光追核心单元。
第三方插件层(Middleware and 3rd Party Libraries Layer)
第三方插件层,也被称为中间件层,主要集成了多种第三方提供的功能模块或库。这些库都是经过大量的优化,非常成熟可以直接应用于游戏引擎中。并且有持续的维护,社区技术讨论与技术文档等,为开发节约时间。
比方说大名鼎鼎的 Havok 和 NVIDIA Physx 物理引擎。使用这些成熟的物理引擎可以避免从零开始开发物理模拟,节省大量的时间和资源。
主流的 Wwise 和 CRI Middleware 提供了音频处理功能,允许开发者创建沉浸式的游戏音效和背景音乐。
一些中间件专注于角色动画和AI的处理,如 MotionBuilder 或 Simplygon。
中间件如 RakNet 或 Photon 提供了多人游戏的网络功能,如客户端-服务器架构、对等网络、聊天和匹配机制等。
有些中间件,如 Telemetry,专门用于监控和分析游戏的性能,帮助开发者找到性能瓶颈。
还有特效与渲染的中间件,例如,SpeedTree 用于创建高质量的树木和植被,而 PopcornFX 专门用于粒子效果。
Reference
GAMES104
https://zhuanlan.zhihu.com/p/485952163