内容工具、Schema、诊断与平台服务边界
本文仅阅读源码、接口和工程组织,未启动编译器、资源构建器、编辑器或随附工具。入口:Summary。
1. 运行时能力由内容生产约束支撑#
RAGE 的资源布局、量化 BVH、动画压缩、物理分组、导航网格和 shader 都依赖离线准备。运行时能在有限内存和时间内处理大量内容,不只是因为循环优化,更因为工具提前决定了数据形状、依赖和合法范围。
图表示生产闭环;不意味着本仓库的所有外部服务和工具依赖都已具备或可运行。
2. Parser/Schema 让编辑表示与运行时类型保持联系#
parser/parsercore 提供结构元数据、输入输出格式、LoadFromStructure、SaveFromStructure、CreateAndLoadAnyType 和 AddWidgets。大量 .psc 及生成结构将内容字段、序列化和调试编辑关联起来;具体格式和运行时布局在资源管线展开。
这种集中描述减少手写多份解析/编辑器代码,也使字段默认值、版本、指针所有权成为长期协议。数据结构改动若只修改 C++ 类型而未同步 schema/资源版本,会让布局匹配与内容兼容失效。
__DECLARESTRUCT、__RESOURCECOMPILER、__BANK 等配置把类型信息、构建能力与运行时精简组合起来。不能假定发行包保留所有反射名称或任意类型的动态编辑能力。
3. Resource builder 构造可重定位内存镜像#
pgRscBuilder 的目标是生成可重载、可重定位的资源堆。BeginBuild 期间将 new 路由到 grow-only heap;delete 不立即回收,临时对象需切到 temporary allocation scope。首遍用于确定分配大小,次遍可据此选择 chunk size;virtual/physical 分配可通过填充避免跨 chunk 边界。
这不是普通文件格式“字段逐个写出”的唯一模式,而是让离线构造过程产出接近运行时布局的对象图。好处是运行时减少解析和大量细粒度分配;成本是构造过程受目标平台尺寸、对齐、类型声明和版本约束。
SaveBuild 保存版本及重定位所需信息,文件扩展中的平台标识和 endian 转换参与构建。必须先 SaveBuild 再 EndBuild;资源根对象是本次堆最先分配对象也有检查。工具里的生命周期错误会固化进资源,不能指望运行时 loader 自动纠正。
4. RageBuilder 与专用工具分工#
Framework tools/src/cli/ragebuilder 包含 scriptgeneral/scriptgta/scriptrage、纹理转换、平台实现和 RPF builder。Rpf7Builder 明确从 raw resources 构造 pack file,说明“构建单资源”与“归档打包”是不同阶段。
游戏 tools 中有 NavMeshGenerator、AudMeshGenerator、RoadPathsGenerator、GeometryCollectorTool、AssetAnalysisTool、TextureCompressionTests 等专用入口。它们的目录存在说明内容生产职责分工;本文没有执行这些工具,也不由名字推断全部算法实现或项目实际流水线配置。
同一产物可能依赖输入内容、schema、工具版本、平台配置和压缩选项。新项目的增量缓存键应覆盖这些因素,不能只按源文件时间戳判断“无需重建”。打包顺序还影响设备寻址和依赖请求;旧光盘优化目标与现代 SSD 的最佳布局可能不同。
5. Bank 是可操作的工程可观测性#
bkBank 组织 group/widget,支持创建/销毁回调和每帧 Update;它与 parser 的 AddWidgets、模块自己的 AddWidgets 接口连接。相比只有日志,开发者可在运行现场查看计数、切换功能和调整参数。
Bank 并非免费:回调、遍历、字符串和绘制可能影响采样;修改参数还可能要求资源重建或安全发布。头文件对动态 SetCurrentGroup 的限制和不推荐使用也表明旧接口存在维护债务。
新项目应将可调参数分为即时标量、下一帧提交、资源重建和重启生效,调试 UI 展示生效条件。否则对运行时对象直接改值可能绕过 invariants,造成难复现状态。
6. 性能系统按配置提供不同观察能力#
pfProfiler 管理 group/page/timer/value,帧末 FlipElapsedTimes;!__STATS 时类可退化成空接口。Timebars 通过回调桥接,RageCore 的回调默认 no-op,由 RageGraphics 安装实际实现;detail timebars 又受 DEV/BANK 条件控制。
因此源码里存在 PF 标记,并不证明某个执行包已经采集到数据。更具体地,stream_profiler.h 的 USE_PROFILER_IO 定义含 & 0,该头文件的 DeviceProfiler 路径在当前定义下关闭;不能把这条 IO profiler 当作已启用能力,也不能据此说所有其他 IO 统计都不存在。
stalldetection 提供单独 worker 和超时栈诊断;其他 profile/grprofile 代码有 CPU、GPU、trace 和图形标记入口。它们提供发现问题的基础设施,如何对应帧 ID、跨线程事件与 GPU 完成时间仍需统一协议。详见性能专题。
7. 构建、QA 与第三方边界#
projgen、各模块 makefile/vcxproj、平台 forceinclude、unity 工程和预编译库共同描述构建空间;base/tools/test、rage/qa、samples 提供测试/演示入口。存在工程和二进制,不证明 SDK、许可证、网络服务和内部部署环境齐备。
第三方库应按职责区分:图像/压缩实现,Scaleform/Bink/NaturalMotion 集成,以及平台 SDK、通信/在线服务封装。报告重点分析接入语义,不把第三方示例或工具库算成游戏实时路径,也不从依赖目录推断软件供应链状态。
8. 持久化、账号与平台服务:异步生命周期的外围#
游戏 SaveLoad 有 CSavegameQueue,以固定容量队列组织 queued operations,提供 Update、Push、ExistsInQueue、Remove 操作;这一产品层机制建立在 Base 文件设备及平台服务之上。存档操作不等于将整份 streaming 资源堆原样保存:玩法状态、用户/设备选择、平台结果和内容资源是不同问题。
framework/fwcommerce、Suite rgsc/snet/snu、rage/rockon 及 Base security 承担商城、服务接入或相关基础能力。这些在本报告中为职责/目录级覆盖,未审计认证、支付、加密算法和完整在线服务。不能由客户端接口证明服务端架构、事务一致性或安全性。
对新项目可迁移的通用原则是:平台异步操作拥有稳定请求身份、显式取消/失败状态、用户切换时的归属和结果提交窗口。重试与可恢复存档需要单独定义,不应借用渲染资源的“Loaded”状态替代业务完成。
9. 面向新项目的生产管线建议#
| 生产阶段 | 建议提前验证的契约 |
|---|---|
| 导入 | 单位、坐标、骨架、材质和碰撞复杂度 |
| Schema | 默认值、字段范围、版本迁移、引用身份 |
| 目标构建 | 对齐、位宽、量化误差、资源页和 scratch 上限 |
| 世界构建 | 依赖深度、每格内容密度、导航/声学接缝 |
| 打包 | 冷装载与随机读取、重复资源、包版本和可追溯性 |
| 运行诊断 | 内容 ID 到耗时/内存/队列事件的映射 |
| 回归 | 极端内容、装卸 churn、取消、低内存和长时运行 |
这些为建议检查,本次仅完成文档静态校验,不执行工程测试。
10. 源码证据#
| 文件/目录 | 入口 |
|---|---|
| parser manager.h | AddWidgets、Load/SaveFromStructure、格式注册 |
| rscbuilder.h | 47–50 目标;100–175 构建和保存契约 |
| Rpf7Builder.h | 16–28 归档构建接口 |
| 游戏工具目录 | 导航/声学/纹理等专用工具职责 |
| bank.h | 49–117 widget/group 生命周期 |
| profiler.h | 29–40 空实现;48 起 group/page 管理 |
| timebars.h | 28–35 配置与回调;78–86 budget 标记 |
| stream_profiler.h | 14 当前关闭的 DeviceProfiler 条件 |
| stalldetection.h | stall worker 与配置退化 |
| savegame_queue.h | 操作队列与固定容量 |