1. 从构建目录到真正的责任边界#
RAGE 的 Base、Framework、Suite 是源码组织层;RageCore、RageGraphics、RagePhysics 等又是链接/工程模块。两者并非逐目录一一对应。Base 内已有完整动画基础、图形资源和物理;Suite 也包含底层计算密集代码,不能简单解释成“Base 纯工具、Suite 纯玩法”。
| 层 | 设计职责 | 与上下层的连接 |
|---|---|---|
| Platform/System | 平台宏、线程、内存、时钟、输入、设备 | 以统一接口包裹各平台实现和条件能力 |
| Base runtime | 数学/容器、文件/资源、图形、物理、音频、网络 | 提供可单独使用的机制,较少直接表达 GTA 玩法 |
| Framework | 应用骨架、实体、场景、Store、streaming、脚本/网络适配 | 管理跨系统生命周期及游戏接入契约 |
| Suite | Clip/Move、粒子、破碎、布料、植被、过场等 | 将基础计算组合成内容系统 |
| Middleware | NaturalMotion、Scaleform、Bink 等 | 接入专门能力,受独立版本/平台/生命周期约束 |
| GTA 原生游戏 | CApp/CGame、角色、车辆、任务和在线规则 | 配置预算、安排更新顺序、定义产品行为 |
| SanScript | 任务、环境活动与在线玩法 | 通过 Native 接口调用原生能力 |
| 离线工具 | 编辑、导出、schema、资源构建和打包 | 将灵活编辑表示转成紧凑运行时表示 |
图表示主要依赖方向,省略回调与部分直接使用。实际源码存在兼容宏、项目特例和跨层接口,因此不是严格无环、完全独立的现代 package 图。
2. 应用、游戏和会话是不同生命周期#
fwApp 承担应用运行和状态管理,GTA CApp 继承它;fwGame/gameSkeleton 负责游戏子系统注册;GTA 会话状态机控制登录、载入、地图与会话切换。
gameSkeleton 区分 init/shutdown mode 与 dependency level。Init、Shutdown 都按各自注册的依赖层级和顺序调用,不是简单自动把 Init 顺序倒过来。Update 不使用这些 dependency levels,而按更新类型和注册组织执行。把初始化依赖误当成每帧 Job DAG 会得到错误结论。
系统数据同时记录 init/shutdown function、类型掩码、各自依赖 level 和名称;update groups 可嵌套并附 timebar budget。生命周期注册因此兼具调度、可观测性和开发依赖测试功能。
3. 顺序是一种共享契约#
游戏 Core/game.cpp 集中注册 streaming、脚本、实体更新、镜头前后阶段及异步 placement 提交。模块自己的 Update() 只能说明内部逻辑;调用所在阶段才决定它读到上一帧还是这一帧的数据、能否删除对象、是否允许重新进入装载过程。
这套集中组织便于检查时序与插入性能标记,但模块数增加后也形成人工维护的隐式依赖图。新系统若引入自动任务图,不应只翻译函数列表;要补齐读写资源、阶段发布、外部设备完成和关闭协议。
4. 平台抽象保留了硬件差异#
源码中的 __PS3/__SPU/__XENON/RSG_PC/RSG_ORBIS/RSG_DURANGO 等宏影响任务结构、内存布局、资源分配和图形路径。CPU/协处理器数据搬运、GPU 可访问内存、cache coherency 和 endian 不是完全隐藏的细节,而是上层某些结构必须遵守的约束。
这种抽象的好处是允许为固定主机硬件做深入优化;代价是配置空间大,类名相同也可能有不同能力/成本。文件或宏分支存在,只能证明“代码库提供该实现”,不能证明当前目标实际链接或启用。
新项目可借鉴“统一语义、允许平台专门化”的思路,但应尽量把能力查询、资源限制和测试矩阵集中,减少上层到处判断设备型号。跨平台只验证能编译,不足以证明异步生命周期和性能一致。
5. 贯穿引擎的四个模式#
- 定义与实例分离:archetype/entity、skeleton data/skeleton、clip/player、network definition/network,支持共享与独立状态。
- 离线布局换运行时成本:资源 construction、指针 fixup、PSO in-place、压缩动画和 BVH,减少运行时解析/分配。
- 有限工作集与显式预算:pools、bounded queues、scratch、load slots;可预测性优先于无上限容器。
- 阶段发布与延迟清理:读盘不等于 Loaded,Update 不等于 Compose,渲染列表引用延长资源寿命,取消不等于完成。
这些共同支撑“大量内容、有限活跃集合”的世界,而不只是一项渲染或流式算法。
6. 能迁移什么,必须重做什么#
资源身份、生命周期所有权、数据布局预算和工具验证值得迁移。固定亲和性、SPU scratch 数字、光盘寻道启发式、旧图形后端假设则应按新硬件重新评估。
新项目应从产品约束反推框架:目标帧时、内存、最高移动速度、同时模拟人数、网络权威模型、是否需要回滚、可接受装载等待、编辑迭代周期。缺少这些约束,复刻 RAGE 的容量和阶段只会继承复杂度,未必继承收益。
7. 源码证据#
| 文件 | 关键入口 |
|---|---|
| game.makefile | 引擎库、中间件依赖 |
| fwApp、fwGame | 可复用应用/游戏接口 |
| gameskeleton.h | 37–41 目标;62–134 注册与顺序语义 |
| gameskeleton.cpp | Init/Shutdown/Update 实际遍历 |
| 游戏 app.cpp | 1344 起帧边界与渲染协作 |
| 游戏 game.cpp | REGISTER_UPDATE_CALL 和初始化/关闭注册 |
| platform.h | 平台封装入口,需结合构建定义阅读 |