GFramework.Game
GFramework.Game 是 GFramework 面向游戏项目的运行时层。
它建立在 GFramework.Core 与 GFramework.Game.Abstractions 之上,提供可直接落地的实现与基类,覆盖静态内容配置、数据与存档、设置、场景路由、UI 路由、序列化、文件存储、状态机扩展等常见游戏运行时需求。
如果你的项目只需要“契约”而不想带入实现,请依赖 GFramework.Game.Abstractions。如果你的项目需要真正可运行的默认实现或基类,请依赖本包。
包定位
- 面向使用者的默认运行时实现层,不是纯接口包。
- 适合作为游戏项目启动层、基础设施层、引擎适配层之上的通用运行时底座。
- 当前最成熟、最明确的能力集中在:
- 静态内容配置:
Config/ - 数据与存档:
Data/ - 设置系统:
Setting/ - 场景与 UI 路由基类:
Scene/、UI/ - 序列化与文件存储:
Serializer/、Storage/
- 静态内容配置:
与相邻包的关系
GFramework.Core- 本包直接依赖它。
- 提供架构、上下文注入、事件、日志、系统/模型/utility 生命周期等底层能力。
GFramework.Game.Abstractions- 本包的上游契约层。
- 本包中的
FileStorage、SettingsModel<TRepository>、SaveRepository<TSaveData>、YamlConfigLoader、SceneRouterBase、UiRouterBase等都在实现这里定义的接口。
GFramework.Game.SourceGenerators- 主要与配置系统配合使用。
- 当你需要 schema 驱动的 YAML 配表时,运行时包是
GFramework.Game,生成时代码由 source generators 补齐。
- 引擎适配包或项目内适配层
- 本包提供的是“引擎无关”的核心逻辑和基类。
- 真正和 Godot、Unity、MonoGame 等引擎对象打交道的工厂、根节点、资源注册表,通常在相邻引擎包或游戏项目内实现。
- 仓库内
ai-libs/下的只读参考实现通常也是这样接入:配置文件 IO 由GFramework.Godot.Config适配, UI / Scene factory 与 root 由项目自己提供。
子系统地图
Config/
面向静态游戏内容的只读配置系统。
YamlConfigLoader- 从文件系统根目录加载 YAML 配置表,并注册到
IConfigRegistry
- 从文件系统根目录加载 YAML 配置表,并注册到
ConfigRegistry- 运行时配置表注册表
GameConfigBootstrap- 非
Architecture场景下的官方配置启动入口
- 非
GameConfigModuleArchitecture场景下的官方配置接入模块
InMemoryConfigTable<TKey, TValue>- 配置表默认只读承载
YamlConfigHotReloadOptions- 开发期热重载控制
这个子系统通常与 GFramework.Game.SourceGenerators 一起使用,而不是手写大量注册代码。
对应文档:
Data/
面向可写业务数据、设置持久化与存档槽位的仓库实现。
DataRepository- 一条
IDataLocation对应一份持久化对象
- 一条
UnifiedSettingsDataRepository- 把多个设置 section 聚合到单一文件中
SaveRepository<TSaveData>- 面向槽位存档,支持版本迁移链
SaveConfiguration- 槽位目录、文件名、前缀等约定
ai-libs/ 下已验证参考实现的常见接法:
- 设置持久化使用
UnifiedSettingsDataRepository - 存档使用
SaveRepository<GameSaveData> - 两者共用同一个底层存储 utility
对应文档:
Setting/
设置生命周期编排层。
SettingsModel<TRepository>- 管理
ISettingsData实例、迁移、加载、保存、重置 - 编排 applicator 的
Apply
- 管理
SettingsSystem- 面向业务代码暴露更直接的系统级入口
Setting/Events/*- 设置初始化、应用、保存、重置相关事件
ai-libs/ 下已验证参考实现的常见接法:
- 在模型模块中创建
SettingsModel<ISettingsDataRepository> - 注册多个 applicator
- 启动时先
InitializeAsync(),再ApplyAll() - 退出时统一
SaveAll()
对应文档:
Storage/
面向本地文件系统的基础存储。
FileStorage- 基于目录与文件的
IStorage实现 - 负责路径清洗、细粒度锁、原子写入、层级 key 到目录结构的映射
- 基于目录与文件的
ScopedStorage- 为底层存储增加前缀作用域
这部分能力经常被 DataRepository、SaveRepository<TSaveData>、UnifiedSettingsDataRepository 复用。
对应文档:
Serializer/
JsonSerializer- 当前默认序列化实现
- 同时可作为
ISerializer与IRuntimeTypeSerializer
它通常先于存储和数据仓库被注册。
对应文档:
Scene/ 与 UI/
面向游戏导航的可复用基类,不直接绑定具体引擎。
SceneRouterBase- 依赖
ISceneFactory、ISceneRoot - 提供栈式场景路由与转换处理管道
- 依赖
UiRouterBase- 依赖
IUiFactory、IUiRoot - 提供页面栈、Overlay/Modal/Toast 等层级 UI、输入动作分发、暂停联动
- 依赖
Scene/Handler/*、UI/Handler/*- 默认转换处理器基类与日志处理器
ai-libs/ 下已验证参考实现的常见接法:
- 项目自定义
SceneRouter : SceneRouterBase - 项目自定义
UiRouter : UiRouterBase - 工厂、注册表、root 都由项目或引擎适配层提供
对应文档:
Routing/ 与 State/
Routing/RouterBase<TRoute, TContext>- Scene/UI 路由共享基类
State/GameStateMachineSystem- 对核心状态机系统的游戏向封装
这两部分一般被上层子系统消费,不是多数项目的第一接入点。
XML 覆盖基线
下面这份 inventory 记录的是 2026-04-23 对 GFramework.Game 做的一轮轻量 XML 盘点结果:只统计公开 /
内部类型声明是否带 XML 注释,用来建立运行时阅读入口;成员级参数、返回值、异常和生命周期说明仍需要在后续 API 波次继续细化。
| 子系统 | 基线状态 | 代表类型 | 阅读重点 |
|---|---|---|---|
Config/ |
26/26 个类型声明已带 XML 注释 |
YamlConfigLoader、ConfigRegistry、GameConfigBootstrap、YamlConfigSchemaValidator |
看 YAML 加载、schema 校验、模块接入与热重载边界 |
Data/ Storage/ Serializer/ |
8/8 个类型声明已带 XML 注释 |
DataRepository、SaveRepository<TSaveData>、UnifiedSettingsDataRepository、FileStorage、JsonSerializer |
看持久化布局、槽位存档、统一设置文件和底层序列化 / 存储实现 |
Setting/ |
9/9 个类型声明已带 XML 注释 |
SettingsModel<TRepository>、SettingsSystem、SettingsAppliedEvent<T> |
看初始化、应用、保存、重置等设置生命周期编排 |
Scene/ UI/ Routing/ |
10/10 个类型声明已带 XML 注释 |
SceneRouterBase、UiRouterBase、SceneTransitionPipeline、UiTransitionPipeline、RouterBase<TRoute, TContext> |
看路由基类、转换处理器和项目层需要自己提供的 factory / root 边界 |
Extensions/ Internal/ State/ |
3/3 个类型声明已带 XML 注释 |
DataLocationExtensions、VersionedMigrationRunner、GameStateMachineSystem |
看辅助扩展、内部迁移执行逻辑和游戏态状态机封装 |
最小接入路径
下面按最常见的四种接入目标给出最短路径。
1. 只想先拿到文件存储
using GFramework.Core.Abstractions.Serializer;
using GFramework.Core.Abstractions.Storage;
using GFramework.Game.Serializer;
using GFramework.Game.Storage;
var serializer = new JsonSerializer();
IStorage storage = new FileStorage("GameData", serializer);
await storage.WriteAsync("player/profile", new { Name = "Alice", Level = 3 });
这里的 JsonSerializer 建议在组合根只创建并配置一次;如果需要自定义 JsonSerializerSettings 或 converters,请在把它注册给 IStorage、DataRepository 或架构 utility 之前完成。
如果你需要逻辑隔离,再包一层 ScopedStorage:
var settingsStorage = new ScopedStorage(storage, "settings");
2. 接入设置和存档
运行时最小拼装顺序通常是:
- 注册
JsonSerializer - 注册一个
IStorage实现 - 注册
ISettingsDataRepository - 创建并注册
SettingsModel<ISettingsDataRepository> - 注册 applicator
- 注册
SettingsSystem - 注册
ISaveRepository<TSaveData>
示意代码:
var serializer = new JsonSerializer();
var storage = new FileStorage("GameData", serializer);
architecture.RegisterUtility(serializer);
architecture.RegisterUtility<IStorage>(storage);
architecture.RegisterUtility<ISettingsDataRepository>(
new UnifiedSettingsDataRepository(
storage,
serializer,
new DataRepositoryOptions { BasePath = "settings", AutoBackup = true }));
architecture.RegisterModel(
new SettingsModel<ISettingsDataRepository>(
new MySettingsLocationProvider(),
architecture.Context.GetUtility<ISettingsDataRepository>())
.RegisterApplicator(new MyAudioSettingsApplicator()));
architecture.RegisterSystem<ISettingsSystem>(new SettingsSystem());
architecture.RegisterUtility<ISaveRepository<MySaveData>>(
new SaveRepository<MySaveData>(
storage,
new SaveConfiguration
{
SaveRoot = "saves",
SaveSlotPrefix = "slot_",
SaveFileName = "save.json"
}));
启动时:
await settingsModel.InitializeAsync();
await settingsSystem.ApplyAll();
退出前:
await settingsSystem.SaveAll();
ai-libs/ 下的只读参考实现目前也是按这个思路接入,只是底层存储换成了 Godot 适配实现。
3. 接入静态 YAML 配置
如果你不走 Architecture 生命周期,直接使用 GameConfigBootstrap:
var bootstrap = new GameConfigBootstrap(
new GameConfigBootstrapOptions
{
RootPath = contentRootPath,
ConfigureLoader = static loader =>
{
loader.RegisterAllGeneratedConfigTables();
}
});
await bootstrap.InitializeAsync();
var registry = bootstrap.Registry;
如果你走 Architecture,优先使用 GameConfigModule,并在较早阶段安装。
这一能力几乎总是与 source generators 绑定使用。目录、schema、生成器与热重载约定请直接看:
4. 接入 Scene / UI 路由
这里的最小前提不是“直接 new 一个 router”,而是先补齐运行时依赖:
ISceneFactory/IUiFactoryISceneRoot/IUiRoot- 具体页面或场景行为实现
然后让项目自己的 router 继承基类:
public sealed class MySceneRouter : SceneRouterBase
{
protected override void RegisterHandlers()
{
RegisterHandler(new LoggingTransitionHandler());
}
}
public sealed class MyUiRouter : UiRouterBase
{
protected override void RegisterHandlers()
{
RegisterHandler(new GFramework.Game.UI.Handler.LoggingTransitionHandler());
}
}
这类 router 适合作为你的项目层或引擎适配层代码,而不是直接修改本包。
ai-libs/ 里的参考接入线索
当前仓库内的只读参考实现,对本包的使用大致分成三层:
- 配置
- 项目级配置宿主类型使用生成表元数据与 YAML loader 完成配置注册
- 设置与存档
- 项目层 utility 模块注册序列化器、底层存储、
UnifiedSettingsDataRepository、SaveRepository<GameSaveData> - 项目层 model 模块创建
SettingsModel<ISettingsDataRepository>并注册 applicator
- 项目层 utility 模块注册序列化器、底层存储、
- 路由
- 项目自定义
SceneRouterBase/UiRouterBase的派生类型
- 项目自定义
这说明本包更适合做“游戏基础设施层”,而不是把所有引擎对象耦死在包内部。
文档入口
什么时候不该直接依赖本包
以下场景优先考虑只依赖 GFramework.Game.Abstractions:
- 你在做纯领域层、协议层或可复用 feature 包,只想引用接口和数据契约
- 你已经有自己的配置、存储、路由实现,只想复用统一契约
- 你不希望业务程序集带入
Newtonsoft.Json、YamlDotNet等运行时依赖