概念页
引擎配置系统
Engine Configuration
游戏引擎总会积累大量可配置选项:有的通过选项菜单暴露给玩家(画质、音量、手柄设置),有的只供开发团队使用、发售前隐藏或去除(如玩家最大行走速度在开发期可调、发售前改成硬编码)。GEA 讨论选项的存取方式(文本文件、压缩二进制、注册表、命令行、环境变量、在线档案)、全局与每用户选项,以及 Quake cvar、OGRE、Naughty Dog 三个真实例子。
选项的加载与保存(卷 I 6.5.1)
选项本身可以简单地做成全局变量或单例的成员,但只有能被配置、保存到存储介质并读回时才有用。
| 方式 | 说明 | GEA 的评价 |
|---|---|---|
| 文本配置文件 | 最常见;格式因引擎而异但通常很简单。Windows INI(OGRE 使用)是按节分组的扁平键值对;JSON 也常用;XML 可行 | 多数开发者认为 JSON 比 XML 简洁易读 |
| 压缩二进制文件 | 自 SNES 以来的主机都配有专用可读写记忆卡,选项常与存档一起存在卡上 | 卡上空间有限,首选压缩二进制 |
| Windows 注册表 | 全局选项数据库,树形:内部节点(注册表键)像文件夹,叶子节点存键值对 | 不推荐:单体数据库,易损坏、重装 Windows 会丢失、易与文件系统不同步 |
| 命令行 | 扫描命令行参数;可控制全部或一小部分选项 | — |
| 环境变量 | Windows、Linux、MacOS 的 PC 上有时使用 | — |
| ↳ 原书问题 | GEA 称「自 SNES 以来的所有主机」都配有专用可移动记忆卡。SNES 本身没有记忆卡:其存档写在卡带内由电池供电的 SRAM 里(Wikipedia「Super Nintendo Entertainment System」);Neo Geo 等早期主机才使用记忆卡(Wikipedia「Memory card」) | 结论「存储空间有限时用压缩二进制」不受影响 |
| 在线用户档案 | 如 Xbox Live 档案保存成就、购买与解锁内容、游戏选项等,存于中央服务器,有网络即可访问 | — |
全局选项与每用户选项(卷 I 6.5.2)
- 多数引擎区分全局选项与每用户选项:玩家可按喜好配置;开发期每个程序员、美术、设计师也能定制自己的工作环境而不影响他人。
- 每个玩家只应「看到」自己的选项。主机上通常把进度和每用户选项(如手柄偏好)一起保存在记忆卡或硬盘的「槽位」里,槽位通常就是介质上的文件(存档见 存档系统)。
- Windows:每个用户在
C:\Users下有文件夹,其中隐藏的AppData子文件夹按应用存放每用户信息。也有游戏把每用户配置存在注册表HKEY_CURRENT_USER下——它其实是HKEY_USERS下当前登录用户子树的别名。
真实引擎的例子(卷 I 6.5.3)
Quake 的 cvar(控制台变量)
- cvar 就是浮点或字符串全局变量,可在游戏内控制台查看和修改,部分可存盘并在下次读回。
- 运行时所有 cvar 在一个全局链表中;每个是动态分配的
cvar_t,含名字、字符串或浮点值、一组标志位和 next 指针。Cvar_Get()访问(不存在则创建),Cvar_Set()修改。标志位CVAR_ARCHIVE决定是否保存到config.cfg,从而跨多次运行保留。
OGRE
- 一组 Windows INI 格式文本文件,默认三份,与可执行文件同目录:
plugins.cfg(启用哪些插件及其位置)、resources.cfg(资产搜索路径)、ogre.cfg(使用 DirectX 还是 OpenGL、视频模式、屏幕尺寸等)。 - 开箱不支持每用户选项,但源码开放,很容易改为在用户主目录查找配置文件;
Ogre::ConfigFile便于读写新的配置文件。
Naughty Dog(《神秘海域》《最后生还者》系列)
- 游戏内菜单:强大的游戏内菜单系统,让开发者控制全局选项、调用命令。选项类型须较简单(主要是布尔、整数、浮点),但已有数以百计的选项。每个选项是全局变量或单例结构/类的成员;创建菜单项时传入变量地址,菜单项直接控制其值。书中例子
CreateRailVehicleMenu()为轨道载具(沿样条行驶的简单载具,几乎每部 Naughty Dog 游戏都有,从《神秘海域:德雷克船长的宝藏》的吉普车追逐到《神秘海域 4》的卡车车队追逐)创建两个布尔项和一个范围 0–1、步长 0.1/0.01 的浮点项,组成子菜单。 - 按项保存:选中菜单项时按 DualShock 的圆圈键即可标记保存;保存的设置写入 INI 风格的文本文件,跨运行保留。未保存的选项取程序员指定的默认值——程序员修改默认值后所有人都会看到新值,除非某人为该项保存了自定义值。这种「逐项决定是否保存」非常有用。
- 命令行参数:扫描一组预定义的特殊选项,如要加载的关卡名等常用参数。
- Scheme 数据定义:引擎和游戏的绝大部分配置用类 Lisp 语言 Scheme 编写。专有数据编译器把 Scheme 数据结构编译成引擎可加载的二进制文件,并生成对应的 C 结构体头文件,让引擎能正确解释二进制数据。二进制文件可以即时重新编译并热重载,修改立即可见——只要不增删数据成员(那需要重新编译引擎)。例:
(deftype simple-animation () ((name string) (speed float :default 1.0) (fade-in-seconds float :default 0.25) (fade-out-seconds float :default 0.25))),再用define-export导出anim-walk、anim-walk-fast、anim-jump三个实例;生成的头文件含struct SimpleAnimation { const char* m_name; float m_speed; float m_fadeInSeconds; float m_fadeOutSeconds; };;游戏中用模板函数LookupSymbol<SimpleAnimation*>(SID("anim-walk"))按 string id 取数据(见 字符串与唯一标识符)。Scheme 符号允许连字符,所以simple-animation是一个符号。该系统用于定义详细的动画树、物理参数、玩家操控机制等,从简单选项到复杂嵌套互连的数据结构都能表达(数据管线见 资产管线与工具链)。
与 UE5 的对照
配置文件系统(UE 5.8 官方文档)描述的是分层 .ini:引擎 Base → 项目 Default → 平台 → 用户文件,后加载覆盖先加载,并可通过 UCLASS(config=...) + UPROPERTY(Config) 自动读入类属性。对照 GEA 的分类:UE 属于「文本配置文件」路线,用户层文件对应 GEA 的「每用户选项」,UPROPERTY(Config) 自动绑定则类似 Naughty Dog 菜单项「直接绑定变量地址」的思路,但借助反射完成。
取舍小结
| 需求 | 做法 |
|---|---|
| 人可读、易合并 | 文本文件(INI / JSON) |
| 存储空间紧张 | 压缩二进制 |
| 开发期快速调参 | 游戏内调试菜单 / 控制台变量,按项保存 |
| 复杂结构化数据 | 数据定义语言 + 数据编译器 + 生成头文件,支持热重载 |
| 避免 | Windows 注册表(易损坏、易丢失、易不同步) |
出处
- Game_Engine_Architecture_4Ed_-_Jason_Gregory.pdf
- Jason Gregory《Game Engine Architecture》第 4 版(2026)卷 I 第 6 章 6.5 节
相关页面
游戏开发 · UE5配置文件系统Configuration FilesUE 的 .ini 配置按类别(Engine、Game、Input……)分层加载:从引擎 Base 文件到项目 Default 文件,再到平台文件和用户文件,后加载的同名键覆盖先加载的。数组可以用 +、-、! 等运算符跨层增删。UCLASS(config=X) 加上 UPROPERTY(Config) 可以让类的默认值从 ini 自动读取;命令行 -ini: 可以临时覆盖。游戏开发子系统启动与关闭Subsystem Start-Up & Shut-Down游戏引擎由许多相互依赖的子系统组成,启动时必须按依赖顺序初始化(B 依赖 A,则先启动 A),关闭时通常反序。C++ 全局/静态对象的构造与析构顺序不可预测,「首次调用时构造」的函数静态单例也无法控制析构顺序且时机不可控。GEA 推荐最朴素的方案:单例管理器的构造/析构函数什么也不做,提供显式的 startUp() / shutDown(),在 main() 里按顺序手动调用。游戏开发字符串与唯一标识符Strings & Unique Identifiers字符串在 C/C++ 中只是字符数组,变长意味着要么硬编码长度上限、要么动态分配;比较和复制都是 O(n)。引擎内部大量用字符串做资源名和对象 ID,处理不当会严重拖慢游戏。GEA 的建议:运行时代码尽量避免字符串类,若用则了解其成本并按引用传递;路径类是值得专门做的例外;对象与资产的唯一标识用哈希字符串 ID(string id),兼得字符串的可读性与整数的比较速度。游戏开发游戏本地化与 UnicodeGame Localization & Unicode本地化(国际化,I18N)是把软件改编为其他语言版本,最好从第一天起规划并贯穿每个开发步骤。GEA 介绍了 Unicode 与 UTF-32/UTF-8/UTF-16/UCS-2 编码、char 与 wchart、Windows 的字符串 API 约定、主机上的选择,字符串之外的本地化问题,以及核心基础设施——字符串数据库 + 按 ID 查找当前语言字符串的运行时函数,并以 Naughty Dog 的本地化工具为例。游戏开发资产管线与工具链Asset Conditioning Pipeline & Tools游戏引擎的输入数据来自美术使用的数字内容创作 (DCC) 工具,但 DCC 格式几乎从不直接用于游戏,必须经过资产调理管线 (Asset Conditioning Pipeline, ACP) 导出、处理并按平台打包。围绕它还有世界编辑器、记录资产元数据的资源数据库,以及几种工具架构(独立工具、与引擎共享底层、编辑器内嵌于引擎、Web 界面),各有取舍。游戏开发 · UE5存档系统SaveGameUE 的存档围绕自定义的 USaveGame 子类进行:保存时把需要持久化的数据从游戏世界拷进 SaveGame 对象,再用 UGameplayStatics 写入某个存档槽(槽名 + 用户索引);读档时反过来。官方推荐用 AsyncSaveGameToSlot 异步保存,避免掉帧,也避免某些平台的认证问题。游戏开发游戏内调试工具In-Game Debugging Tools各子系统(渲染、动画、碰撞、物理、音频、网络、玩家机制、AI……)都有大量配置项,能在游戏运行时调整而无需改代码、重新编译链接再运行,可大幅节省调试和搭建关卡/玩法的时间。GEA 介绍支撑这一点的几类游戏内工具:游戏内菜单(及 Dear ImGui 等第三方 GUI)、游戏内控制台、调试摄像机与暂停/慢动作、作弊功能、截图与录像。(卷 I 10.3–10.7 节)游戏开发动画管线与动作状态机Animation Pipeline & Action State Machines低层动画管线把片段和混合规格变成局部姿势、全局姿势和蒙皮矩阵调色板;其上的动作状态机 (ASM) 给游戏代码提供"按状态驱动动画"的接口。每个状态是任意复杂的片段混合,跟踪当前所有片段的方式有扁平加权平均和混合树两种;过渡用数据驱动的过渡矩阵描述,控制参数通过节点搜索、命名变量或控制结构体暴露给代码(GEA4 卷 II 13.9–13.10)。游戏开发数据驱动与游戏世界编辑器Data-Driven Engines & Game World Editors当游戏行为可以部分或全部由美术和策划提供的数据控制,而不只由程序员写的代码控制时,引擎就是数据驱动的。它能提高团队效率、缩短迭代时间,但工具、健壮的运行时和预览手段都要花大量成本,过度设计反而降低生产力,所以要权衡并坚持 KISS。玩法领域里对应 DCC 工具的是游戏世界编辑器:创建世界块并放入静态和动态元素、设定对象初始状态和行为。GEA 列出了它的典型功能,并比较了不同引擎在何时做平台相关优化上的取舍(GEA4 卷 II 16.3–16.4)。