docs(sidebar): 更新侧边栏导航结构并移除API参考页面

- 调整Core模块导航链接结构,从overview页面改为根路径
- 重构Core模块侧边栏,将原有的6个主要类别扩展为15个详细分类
- 精简Game模块侧边栏,保留场景管理和游戏设置两个主要功能
- 更新Godot集成模块侧边栏,新增协程、信号、存储等功能分类
- 修改源码生成器模块命名,将枚举扩展重命名为枚举生成器
- 新增抽象接口侧边栏,包含Core和Game抽象接口文档
- 调整教程模块顺序,新增入门教程和Godot集成教程分类
- 移除独立的API参考导航项,将其整合到相应模块中
- 修正生成器API文档链接路径错误问题
This commit is contained in:
GeWuYou 2026-02-11 12:05:15 +08:00 committed by gewuyou
parent bc89ff07a1
commit 317eddca9b
18 changed files with 1785 additions and 3539 deletions

View File

@ -41,12 +41,11 @@ export default defineConfig({
nav: [
{ text: '首页', link: '/zh-CN/' },
{ text: '入门指南', link: '/zh-CN/getting-started/installation' },
{ text: 'Core', link: '/zh-CN/core/overview' },
{ text: 'Core', link: '/zh-CN/core/' },
{ text: 'Game', link: '/zh-CN/game/overview' },
{ text: 'Godot', link: '/zh-CN/godot/overview' },
{ text: '源码生成器', link: '/zh-CN/source-generators/overview' },
{ text: '教程', link: '/zh-CN/tutorials/basic-tutorial' },
{ text: 'API参考', link: '/zh-CN/api-reference/core-api' }
],
sidebar: {
@ -65,12 +64,22 @@ export default defineConfig({
{
text: 'Core 核心框架',
items: [
{ text: '概览', link: '/zh-CN/core/overview' },
{ text: '架构组件', link: '/zh-CN/core/architecture/architecture' },
{ text: '命令查询系统', link: '/zh-CN/core/command-query/commands' },
{ text: '事件系统', link: '/zh-CN/core/events/event-bus' },
{ text: '属性系统', link: '/zh-CN/core/property/bindable-property' },
{ text: '工具类', link: '/zh-CN/core/utilities/ioc-container' }
{ text: '概览', link: '/zh-CN/core/' },
{ text: '架构组件', link: '/zh-CN/core/architecture' },
{ text: '命令系统', link: '/zh-CN/core/command' },
{ text: '查询系统', link: '/zh-CN/core/query' },
{ text: '事件系统', link: '/zh-CN/core/events' },
{ text: '属性系统', link: '/zh-CN/core/property' },
{ text: 'IoC容器', link: '/zh-CN/core/ioc' },
{ text: '对象池', link: '/zh-CN/core/pool' },
{ text: '日志系统', link: '/zh-CN/core/logging' },
{ text: '扩展方法', link: '/zh-CN/core/extensions' },
{ text: '工具类', link: '/zh-CN/core/utility' },
{ text: '模型层', link: '/zh-CN/core/model' },
{ text: '系统层', link: '/zh-CN/core/system' },
{ text: '控制器', link: '/zh-CN/core/controller' },
{ text: '规则系统', link: '/zh-CN/core/rule' },
{ text: '环境接口', link: '/zh-CN/core/environment' }
]
}
],
@ -80,10 +89,8 @@ export default defineConfig({
text: 'Game 游戏模块',
items: [
{ text: '概览', link: '/zh-CN/game/overview' },
{ text: '模块系统', link: '/zh-CN/game/modules/architecture-modules' },
{ text: '存储系统', link: '/zh-CN/game/storage/scoped-storage' },
{ text: '资源管理', link: '/zh-CN/game/assets/asset-catalog' },
{ text: '序列化', link: '/zh-CN/game/serialization/json-serializer' }
{ text: '场景管理', link: '/zh-CN/game/scene-management' },
{ text: '游戏设置', link: '/zh-CN/game/setting' }
]
}
],
@ -93,10 +100,11 @@ export default defineConfig({
text: 'Godot 集成',
items: [
{ text: '概览', link: '/zh-CN/godot/overview' },
{ text: '集成指南', link: '/zh-CN/godot/integration/architecture-integration' },
{ text: '节点扩展', link: '/zh-CN/godot/node-extensions/node-extensions' },
{ text: '对象池', link: '/zh-CN/godot/pooling/node-pool' },
{ text: '日志系统', link: '/zh-CN/godot/logging/godot-logger' }
{ text: '协程系统', link: '/zh-CN/godot/coroutine' },
{ text: '节点扩展', link: '/zh-CN/godot/extensions' },
{ text: '信号系统', link: '/zh-CN/godot/signal' },
{ text: '存储系统', link: '/zh-CN/godot/storage' },
{ text: '设置系统', link: '/zh-CN/godot/setting' }
]
}
],
@ -105,21 +113,32 @@ export default defineConfig({
{
text: '源码生成器',
items: [
{ text: '概览', link: '/zh-CN/source-generators/overview' },
{ text: '概览', link: '/zh-CN/source-generators/' },
{ text: '日志生成器', link: '/zh-CN/source-generators/logging-generator' },
{ text: '枚举扩展', link: '/zh-CN/source-generators/enum-extensions' },
{ text: '枚举扩展', link: '/zh-CN/source-generators/enum-generator' },
{ text: '规则生成器', link: '/zh-CN/source-generators/rule-generator' }
]
}
],
'/zh-CN/abstractions/': [
{
text: '抽象接口',
items: [
{ text: 'Core Abstractions', link: '/zh-CN/abstractions/core-abstractions' },
{ text: 'Game Abstractions', link: '/zh-CN/abstractions/game-abstractions' }
]
}
],
'/zh-CN/tutorials/': [
{
text: '教程',
items: [
{ text: '入门教程', link: '/zh-CN/tutorials/getting-started' },
{ text: '基础教程', link: '/zh-CN/tutorials/basic-tutorial' },
{ text: '高级模式', link: '/zh-CN/tutorials/advanced-patterns' },
{ text: '最佳实践', link: '/zh-CN/tutorials/best-practices' }
{ text: 'Godot集成', link: '/zh-CN/tutorials/godot-integration' },
{ text: '高级模式', link: '/zh-CN/tutorials/advanced-patterns' }
]
}
],
@ -131,7 +150,7 @@ export default defineConfig({
{ text: 'Core API', link: '/zh-CN/api-reference/core-api' },
{ text: 'Game API', link: '/zh-CN/api-reference/game-api' },
{ text: 'Godot API', link: '/zh-CN/api-reference/godot-api' },
{ text: '生成器 API', link: '/zh-CN/api-reference/generators-api' }
{ text: '生成器 API', link: '/zh-CN/api-reference/source-generators-api' }
]
}
]

View File

@ -0,0 +1,192 @@
# Core Abstractions
> GFramework.Core.Abstractions 核心抽象接口定义
## 概述
GFramework.Core.Abstractions 包含了框架的所有核心接口定义,这些接口定义了组件之间的契约,实现了依赖倒置和面向接口编程。
## 核心接口
### IArchitecture
应用程序架构接口:
```csharp
public interface IArchitecture
{
void Initialize();
void Destroy();
T GetModel<T>() where T : IModel;
T GetSystem<T>() where T : ISystem;
T GetUtility<T>() where T : IUtility;
void RegisterModel(IModel model);
void RegisterSystem(ISystem system);
void RegisterUtility(IUtility utility);
}
```
### IModel
数据模型接口:
```csharp
public interface IModel
{
void Init();
void Dispose();
IArchitecture Architecture { get; }
}
```
### ISystem
业务逻辑系统接口:
```csharp
public interface ISystem
{
void Init();
void Dispose();
IArchitecture Architecture { get; }
}
```
### IController
控制器接口:
```csharp
public interface IController : IBelongToArchitecture
{
void Init();
void Dispose();
}
```
### IUtility
工具类接口:
```csharp
public interface IUtility
{
}
```
## 事件接口
### IEvent
事件基接口:
```csharp
public interface IEvent
{
}
```
### IEventHandler
事件处理器接口:
```csharp
public interface IEventHandler<TEvent> where TEvent : IEvent
{
void Handle(TEvent event);
}
```
## 命令查询接口
### ICommand
命令接口:
```csharp
public interface ICommand
{
void Execute();
}
```
### IQuery
查询接口:
```csharp
public interface IQuery<TResult>
{
TResult Execute();
}
```
## 依赖注入接口
### IIocContainer
IOC 容器接口:
```csharp
public interface IIocContainer
{
void Register<TInterface, TImplementation>() where TImplementation : TInterface;
void Register<TInterface>(TInterface instance);
TInterface Resolve<TInterface>();
bool IsRegistered<TInterface>();
}
```
## 生命周期接口
### ILifecycle
组件生命周期接口:
```csharp
public interface ILifecycle
{
void OnInit();
void OnDestroy();
}
```
## 使用示例
### 通过接口实现依赖注入
```csharp
public class MyService : IMyService
{
private readonly IArchitecture _architecture;
public MyService(IArchitecture architecture)
{
_architecture = architecture;
}
}
```
### 自定义事件
```csharp
public class PlayerDiedEvent : IEvent
{
public int PlayerId { get; set; }
public Vector2 Position { get; set; }
}
```
---
**相关文档**
- [Core 概述](../core)
- [Architecture](../core/architecture)
- [Events](../core/events)
- [Command](../core/command)
- [Query](../core/query)

View File

@ -0,0 +1,113 @@
# Game Abstractions
> GFramework.Game.Abstractions 游戏模块抽象接口定义
## 概述
GFramework.Game.Abstractions 包含了游戏特定功能的抽象接口,这些接口定义了游戏开发中的通用契约。
## 存档接口
### ISaveSystem
存档系统接口:
```csharp
public interface ISaveSystem
{
void Save(string slotId, SaveData data);
SaveData Load(string slotId);
bool HasSave(string slotId);
void Delete(string slotId);
List<SaveSlotInfo> GetAllSaveSlots();
}
```
### ISaveData
存档数据接口:
```csharp
public interface ISaveData
{
int Version { get; }
DateTime Timestamp { get; }
void Validate();
}
```
## 设置接口
### IGameSettings
游戏设置接口:
```csharp
public interface IGameSettings
{
AudioSettings Audio { get; }
GraphicsSettings Graphics { get; }
InputSettings Input { get; }
void Save();
void Load();
void ResetToDefaults();
}
```
## 场景管理接口
### ISceneManager
场景管理器接口:
```csharp
public interface ISceneManager
{
void SwitchScene<TScene>() where TScene : IScene;
Task SwitchSceneAsync<TScene>() where TScnee : IScene;
void PushScene<TScene>() where TScene : IScene;
void PopScene();
IScene CurrentScene { get; }
}
```
### IScene
场景接口:
```csharp
public interface IScene
{
void OnEnter();
void OnExit();
void OnUpdate(float delta);
}
```
## 资源管理接口
### IAssetManager
资源管理器接口:
```csharp
public interface IAssetManager
{
T Load<T>(string path) where T : Resource;
void Preload<T>(string path) where T : Resource;
void Unload(string path);
bool IsLoaded(string path);
}
```
---
**相关文档**
- [Game 概述](../game)
- [Core Abstractions](./core-abstractions)
- [存档系统](../game/storage)
- [场景管理](../game/scene-management)

File diff suppressed because it is too large Load Diff

View File

@ -1,834 +0,0 @@
# GFramework.Game API 参考
> GFramework.Game 模块的完整 API 参考文档,包含游戏特定功能的详细说明。
## 📋 目录
- [架构模块](#架构模块)
- [资产管理系统](#资产管理系统)
- [存储系统](#存储系统)
- [序列化系统](#序列化系统)
- [数据模型](#数据模型)
- [工具类](#工具类)
## 架构模块
### IArchitectureModule
架构模块接口,定义了模块的基本行为。
#### 方法签名
```csharp
void Install(IArchitecture architecture);
void OnAttach(Architecture architecture);
void OnDetach(Architecture architecture);
void OnPhase(ArchitecturePhase phase, IArchitecture architecture);
```
#### 使用示例
```csharp
public class AudioModule : IArchitectureModule
{
public void Install(IArchitecture architecture)
{
architecture.RegisterSystem(new AudioSystem());
architecture.RegisterUtility(new AudioUtility());
}
public void OnAttach(Architecture architecture)
{
Logger.Info("Audio module attached to architecture");
}
public void OnDetach(Architecture architecture)
{
Logger.Info("Audio module detached from architecture");
}
public void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
{
switch (phase)
{
case ArchitecturePhase.Ready:
// 架构准备就绪,可以开始播放背景音乐
PlayBackgroundMusic();
break;
case ArchitecturePhase.Destroying:
// 架构正在销毁,清理音频资源
CleanupAudioResources();
break;
}
}
}
```
### AbstractModule
抽象模块基类,实现了 IArchitectureModule 接口。
#### 构造函数
```csharp
public AbstractModule();
```
#### 可用方法
```csharp
// 发送事件
protected void SendEvent<T>(T e) where T : new();
protected void SendEvent<T>(T e);
// 获取模型
protected T GetModel<T>() where T : class, IModel;
protected T GetSystem<T>() where T : class, ISystem;
protected T GetUtility<T>() where T : class, IUtility;
// 发送命令
protected void SendCommand(ICommand command);
protected TResult SendCommand<TResult>(ICommand<TResult> command);
// 发送查询
protected TResult SendQuery<TResult>(IQuery<TResult> query);
```
#### 使用示例
```csharp
public class SaveModule : AbstractModule
{
private Timer _autoSaveTimer;
public override void Install(IArchitecture architecture)
{
architecture.RegisterSystem(new SaveSystem());
architecture.RegisterUtility(new SaveUtility());
}
public override void OnAttach(Architecture architecture)
{
// 创建自动保存计时器
_autoSaveTimer = new Timer();
_autoSaveTimer.WaitTime = 300; // 5分钟
_autoSaveTimer.Timeout += OnAutoSave;
// 这里无法使用 AddChild因为不是 Node
// 在具体的模块实现中处理
}
public override void OnDetach(Architecture architecture)
{
_autoSaveTimer?.Stop();
_autoSaveTimer = null;
}
public override void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
{
switch (phase)
{
case ArchitecturePhase.Ready:
Logger.Info("Save module ready");
break;
case ArchitecturePhase.Destroying:
Logger.Info("Save module destroying");
break;
}
}
private void OnAutoSave()
{
var saveSystem = GetSystem<SaveSystem>();
saveSystem.SaveAutoSave();
}
}
```
## 资产管理系统
### IAssetCatalogUtility
资产目录工具接口,定义了资产管理的基本行为。
#### 方法签名
```csharp
// 场景资产注册
void RegisterSceneUnit(string key, string scenePath);
void RegisterScenePage(string key, string scenePath);
void RegisterAsset<T>(string key, string path) where T : Resource;
void RegisterAsset(string key, Type type, string path);
// 映射资产注册
void RegisterSceneUnit(string key, AssetMapping mapping);
void RegisterScenePage(string key, AssetMapping mapping);
void RegisterAsset(string key, AssetMapping mapping);
// 查询方法
bool HasSceneUnit(string key);
bool HasScenePage(string key);
bool HasAsset<T>(string key);
bool HasAsset(string key, Type type);
// 获取方法
T GetScene<T>(string key) where T : PackedScene;
T GetScenePage<T>(string key) where T : PackedScene;
T GetAsset<T>(string key) where T : Resource;
T GetAsset(string key, Type type);
// 元数据获取
AssetCatalogMapping GetAssetMetadata(string key);
```
#### AssetCatalogMapping
资产映射数据类。
#### 属性
```csharp
public string Key { get; set; }
public string Path { get; set; }
public Type Type { get; set; }
public Dictionary<string, object> Metadata { get; set; }
public DateTime RegisteredAt { get; set; }
```
#### 使用示例
```csharp
public class GameAssetCatalog : AbstractAssetCatalogUtility
{
public override void Initialize()
{
// 注册场景资产
RegisterSceneUnit("Player", "res://scenes/Player.tscn");
RegisterSceneUnit("Enemy", "res://scenes/Enemy.tscn");
RegisterScenePage("MainMenu", "res://ui/MainMenu.tscn");
RegisterScenePage("GameUI", "res://ui/GameUI.tscn");
// 注册通用资产
RegisterAsset<Texture2D>("PlayerTexture", "res://textures/player.png");
RegisterAsset<Texture2D>("EnemyTexture", "res://textures/enemy.png");
RegisterAsset<AudioStream>("ShootSound", "res://audio/shoot.wav");
RegisterAsset<AudioStream>("ExplosionSound", "res://audio/explosion.wav");
// 使用元数据注册
var playerMapping = new AssetMapping
{
Key = "Player",
Path = "res://scenes/Player.tscn",
Type = typeof(PackedScene),
Metadata = new Dictionary<string, object>
{
["category"] = "character",
["tags"] = new[] { "player", "hero", "controlled" },
["health"] = 100,
["speed"] = 5.0f
}
};
RegisterSceneUnit("Player", playerMapping);
}
protected override bool ValidateAsset(string key, string path)
{
if (!FileAccess.FileExists(path))
{
GD.PrintErr($"Asset file not found: {path}");
return false;
}
if (string.IsNullOrWhiteSpace(key))
{
GD.PrintErr("Asset key cannot be empty");
return false;
}
return true;
}
protected override void OnAssetLoaded(string key, object asset)
{
GD.Print($"Asset loaded: {key} of type {asset.GetType().Name}");
// 对特定资产进行额外处理
if (key == "Player" && asset is PackedScene playerScene)
{
PreloadPlayerComponents(playerScene);
}
}
private void PreloadPlayerComponents(PackedScene playerScene)
{
// 预加载玩家组件到内存
playerScene.Instantiate(); // 实例化以加载子节点
}
// 获取资产
public PackedScene GetPlayerScene() => GetScene<PackedScene>("Player");
public PackedScene GetEnemyScene() => GetScene<PackedScene>("Enemy");
public Texture2D GetPlayerTexture() => GetAsset<Texture2D>("PlayerTexture");
public AudioStream GetShootSound() => GetAsset<AudioStream>("ShootSound");
}
```
### AbstractResourceFactoryUtility
抽象资源工厂工具基类。
#### 抽象方法
```csharp
protected abstract void RegisterFactories();
protected abstract T CreateFactory<T>(string path, Dictionary<string, object> metadata = null) where T : class;
```
#### 使用示例
```csharp
public class GameResourceFactory : AbstractResourceFactoryUtility
{
protected override void RegisterFactories()
{
RegisterFactory<PlayerData>("res://data/players/{id}.json");
RegisterFactory<WeaponConfig>("res://data/weapons/{id}.json");
RegisterFactory<LevelData>("res://data/levels/{id}.json");
}
public PlayerData CreatePlayer(string playerId)
{
var playerPath = $"res://data/players/{playerId}.json";
return CreateFactory<PlayerData>(playerPath);
}
public WeaponConfig CreateWeapon(string weaponId)
{
var metadata = new Dictionary<string, object>
{
["weaponId"] = weaponId,
["loadTime"] = DateTime.Now
};
return CreateFactory<WeaponConfig>($"res://data/weapons/{weaponId}.json", metadata);
}
public LevelData CreateLevel(string levelId)
{
return CreateFactory<LevelData>($"res://data/levels/{levelId}.json");
}
protected override PlayerData CreateFactory<PlayerData>(string path, Dictionary<string, object> metadata)
{
if (!FileAccess.FileExists(path))
{
return new PlayerData(); // 返回默认数据
}
try
{
var json = FileAccess.Open(path, FileAccess.ModeFlags.Read).GetAsText();
var data = JsonConvert.DeserializeObject<PlayerData>(json);
// 如果有元数据,可以用来修改数据
if (metadata != null)
{
data.LastLoadedAt = metadata.GetValueOrDefault("loadTime", DateTime.Now);
data.LoadCount = metadata.GetValueOrDefault("loadCount", 0) + 1;
}
return data;
}
catch (Exception ex)
{
GD.PrintErr($"Failed to load player data from {path}: {ex.Message}");
return new PlayerData();
}
}
}
```
## 存储系统
### IStorage
存储接口,定义了数据持久化的基本行为。
#### 方法签名
```csharp
// 读写操作
void Write<T>(string key, T data);
T Read<T>(string key, T defaultValue = default);
Task WriteAsync<T>(string key, T data);
Task<T> ReadAsync<T>(string key, T defaultValue = default);
// 存在检查
bool Has(string key);
void Delete(string key);
void Clear();
```
#### IScopedStorage
作用域存储接口,支持命名空间隔离。
#### 构造函数
```csharp
public ScopedStorage(IStorage storage, string scope, string delimiter = ".");
```
#### 使用示例
```csharp
// 创建根存储
var rootStorage = new FileStorage("user://data/");
// 创建分层存储
var playerStorage = new ScopedStorage(rootStorage, "player");
var saveStorage = new ScopedStorage(rootStorage, "saves");
var settingsStorage = new ScopedStorage(rootStorage, "settings");
// 使用分层存储
playerStorage.Write("profile", playerProfile);
playerStorage.Write("inventory", inventory);
playerStorage.Write("stats", playerStats);
saveStorage.Write("slot_1", saveData);
saveStorage.Write("slot_2", saveData);
settingsStorage.Write("graphics", graphicsSettings);
settingsStorage.Write("audio", audioSettings);
// 读取数据
var profile = playerStorage.Read<PlayerProfile>("profile", new PlayerProfile());
var inventory = playerStorage.Read<Inventory>("inventory", new Inventory());
// 使用完整路径
playerStorage.Write("savegames/auto", autoSaveData); // 写入 player/savegames/auto.json
```
### FileStorage
文件存储实现,基于 Godot 的 FileAccess。
#### 构造函数
```csharp
public FileStorage(string rootPath, bool createDirectoryIfNotExists = true);
```
#### 使用示例
```csharp
// 创建文件存储
var storage = new FileStorage("user://saves");
// 基础用法
storage.Write("player", playerData);
var loadedPlayer = storage.Read<Player>("player", new Player());
// 异步用法
await storage.WriteAsync("player", playerData);
var loadedPlayer = await storage.ReadAsync<Player>("player");
// 检查存在性
bool hasPlayerData = storage.Has("player");
storage.Delete("old_save");
storage.Clear();
```
### JsonStorage
JSON 存储实现,使用 Newtonsoft.Json 进行序列化。
#### 构造函数
```csharp
public JsonStorage(IFileStorage fileStorage, JsonSerializerSettings settings = null);
```
#### 使用示例
```csharp
var fileStorage = new FileStorage("user://saves");
var settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Populate
};
var storage = new JsonStorage(fileStorage, settings);
// 自定义序列化
storage.Write("player", playerData, customSerializer);
// 压缩缩存储
storage.Write("player", playerData, serializer: new JsonSerializer
{
Formatting = Formatting.None
});
```
### CachedStorage
缓存存储实现,提高频繁访问的性能。
#### 构造函数
```csharp
public CachedStorage(IStorage innerStorage, TimeSpan cacheExpiry = default);
```
#### 使用示例
```csharp
var fileStorage = new FileStorage("user://saves");
var cachedStorage = new CachedStorage(fileStorage, TimeSpan.FromMinutes(5));
// 第一次读取会从存储加载
var player1 = cachedStorage.Read<Player>("player");
// 第二次读取会从缓存返回(如果未过期)
var player2 = cachedStorage.Read<Player>("player");
// 手动清除缓存
cachedStorage.ClearCache();
// 检查缓存状态
var playerInCache = cachedStorage.IsCached("player");
```
## 序列化系统
### JsonSerializer
JSON 序列化工具类,基于 Newtonsoft.Json。
#### 构造函数
```csharp
public JsonSerializer(JsonSerializerSettings settings = null);
```
#### 方法
```csharp
// 基础序列化
public string Serialize<T>(T data);
public void SerializeToFile<T>(string path, T data);
// 反序列化
public T Deserialize<T>(string json);
public T DeserializeFromFile<T>(string path, T defaultValue = default);
// 异步序列化
public Task<string> SerializeAsync<T>(T data);
public Task<T> DeserializeAsync<T>(string json, T defaultValue = default);
// 压缩序列化
public string SerializeCompressed<T>(T data);
public T DeserializeCompressed<T>(string compressedJson);
```
#### 使用示例
```csharp
var serializer = new JsonSerializer();
// 基础序列化
var json = serializer.Serialize(playerData);
var loadedPlayer = serializer.Deserialize<Player>(json);
// 文件操作
serializer.SerializeToFile("player.json", playerData);
var loadedFromFile = serializer.DeserializeFromFile<Player>("player.json");
// 异步操作
var json = await serializer.SerializeAsync(playerData);
var loadedAsync = await serializer.DeserializeAsync<Player>(json);
// 压缩操作
var compressed = serializer.SerializeCompressed(playerData);
var decompressed = serializer.DeserializeCompressed<Player>(compressed);
```
### ISerializable
可序列化接口。
#### 使用示例
```csharp
public class PlayerData : ISerializable
{
public string PlayerId { get; set; }
public int Level { get; set; }
public int Score { get; set; }
public Vector2 Position { get; set; }
[JsonProperty("last_saved_at")]
public DateTime LastSavedAt { get; set; }
[JsonProperty("inventory_items")]
public List<InventoryItem> Inventory { get; set; }
// 自定义序列化方法
[OnSerializing]
public void OnSerializing()
{
// 序列化前的处理
LastSavedAt = DateTime.Now;
}
[OnDeserialized]
public void OnDeserialized()
{
// 反序列化后的处理
if (LastSavedAt == default)
{
LastSavedAt = DateTime.Now;
}
}
}
```
## 数据模型
### SaveData
存档数据类。
#### 属性
```csharp
public string Version { get; set; } = "1.0.0";
public DateTime SavedAt { get; set; }
public Dictionary<string, object> PlayerData { get; set; } = new();
public Dictionary<string, object> GameData { get; set; } = new();
public Dictionary<string, object> SystemData { get; set; } = new();
public Dictionary<string, object> ModuleData { get; set; } = new();
public Dictionary<string, object> SettingsData { get; set; } = new();
```
### PlayerData
玩家数据类。
#### 属性
```csharp
[JsonProperty("player_id")]
public string PlayerId { get; set; }
[JsonProperty("player_name")]
public string PlayerName { get; set; }
[JsonProperty("level")]
public int Level { get; set; }
[JsonProperty("experience")]
public long Experience { get; set; }
[JsonProperty("health")]
public int Health { get; set; }
public int MaxHealth { get; set; }
[JsonProperty("position")]
public Vector3 Position { get; set; }
[JsonProperty("inventory")]
public InventoryData Inventory { get; set; }
[JsonProperty("skills")]
public List<SkillData> Skills { get; set; }
}
```
### GameData
游戏数据类。
#### 属性
```csharp
[JsonProperty("current_level")]
public int CurrentLevel { get; set; }
[JsonProperty("high_score")]
public int HighScore { get; set; }
[JsonProperty("total_play_time")]
public float TotalPlayTime { get; set; }
[JsonProperty("enemies_defeated")]
public int EnemiesDefeated { get; set; }
[JsonProperty("achievements_unlocked")]
public List<string> AchievementsUnlocked { get; set; }
```
### InventoryData
背包数据类。
#### 属性
```csharp
[JsonProperty("slots")]
public List<InventorySlot> Slots { get; set; } = new();
[JsonProperty("equipment")]
public Dictionary<string, string> Equipment { get; set; } = new();
```
### InventorySlot
背包槽位类。
#### 属性
```csharp
[JsonProperty("item_id")]
public string ItemId { get; set; }
[JsonProperty("quantity")]
public int Quantity { get; set; }
[JsonProperty("durability")]
public int Durability { get; set; }
[JsonProperty("metadata")]
public Dictionary<string, object> Metadata { get; set; } = new();
```
## 工具类
### StorageUtility
存储工具类,提供高级存储功能。
#### 构造函数
```csharp
public StorageUtility(IStorage storage, IVersionMigrationManager migrationManager = null);
```
#### 方法
```csharp
// 自动保存
public void EnableAutoSave(IArchitecture architecture, float intervalMinutes = 5.0f);
public void DisableAutoSave();
// 存档管理
public void CreateSave(int slotId, SaveData data);
public SaveData LoadSave(int slotId);
public List<SaveSlotInfo> GetSaveSlots();
public void DeleteSave(int slotId);
// 数据迁移
public void RegisterMigration<T>(int fromVersion, int toVersion, Func<T, T> migrator);
```
#### 使用示例
```csharp
[ContextAware]
[Log]
public partial class GameManager : Node, IController
{
private StorageUtility _storageUtility;
protected override void OnInit()
{
_storageUtility = Context.GetUtility<StorageUtility>();
// 注册数据迁移
_storageUtility.RegisterMigration<PlayerData>(1, 2, MigratePlayerDataV1ToV2);
_storageUtility.RegisterMigration<PlayerData>(2, 3, MigratePlayerDataV2ToV3);
// 启用自动保存
_storageUtility.EnableAutoSave(Context, 5.0f);
// 监听存档相关事件
this.RegisterEvent<SaveRequestEvent>(OnSaveRequest);
this.RegisterEvent<LoadRequestEvent>(OnLoadRequest);
}
private void OnSaveRequest(SaveRequestEvent e)
{
var saveData = CreateSaveData();
_storageUtility.CreateSave(e.SlotId, saveData);
}
private void OnLoadRequest(LoadRequestEvent e)
{
var saveData = _storageUtility.LoadSave(e.SlotId);
if (saveData != null)
{
RestoreGameData(saveData);
}
}
private SaveData CreateSaveData()
{
var playerModel = Context.GetModel<PlayerModel>();
var gameModel = Context.GetModel<GameModel>();
return new SaveData
{
Version = "1.0.0",
SavedAt = DateTime.Now,
PlayerData = new Dictionary<string, object>
{
["player"] = playerModel.GetData(),
["statistics"] = playerModel.GetStatistics()
},
GameData = new Dictionary<string, object>
{
["game"] = gameModel.GetData()
}
};
}
private PlayerData MigratePlayerDataV1ToV2(PlayerData v1Data)
{
return new PlayerData
{
PlayerId = v1Data.PlayerId,
PlayerName = v1Data.PlayerName,
Level = v1Data.Level,
Experience = v1Data.Experience,
Health = v1Data.Health,
MaxHealth = Math.Max(100, v1Data.MaxHealth), // V2 新增最大生命值
Position = v1Data.Position,
Inventory = v1Data.Inventory,
Skills = v1Data.Skills // V1 的 Kills 字段在 V2 中重命名为 Skills
};
}
private PlayerData MigratePlayerDataV2ToV3(PlayerData v2Data)
{
return new PlayerData
{
PlayerId = v2Data.PlayerId,
PlayerName = Versioning.GetVersionString(v2Data.Version),
Level = v2Data.Level,
Experience = v2Data.Experience,
Health = v2Data.Health,
MaxHealth = v2Data.MaxHealth,
Position = v2Data.Position,
Inventory = v2Data.Inventory,
Skills = v2Data.Skills,
Achievements = v2Data.Achievements ?? new List<string>() // V3 新增成就系统
};
}
}
```
---
**文档版本**: 1.0.0
**更新日期**: 2026-01-12

View File

@ -1,951 +0,0 @@
# GFramework.Godot API 参考
> GFramework.Godot 模块的完整 API 参考文档,包含 Godot 特定扩展和集成的详细说明。
## 📋 目录
- [架构集成](#架构集成)
- [Node 扩展方法](#node-扩展方法)
- [信号系统](#信号系统)
- [节点池化](#节点池化)
- [资源管理](#资源管理)
- [日志系统](#日志系统)
- [池化管理](#池化管理)
- [音频系统](#音频系统)
## 架构集成
### AbstractArchitecture
Godot 特定的架构基类,继承自 Core.Architecture。
#### 新增方法
```csharp
// Godot 模块安装
protected void InstallGodotModule(IGodotModule module);
protected void InstallGodotModule<T>() where T : IGodotModule, new();
```
#### 使用示例
```csharp
public class GameArchitecture : AbstractArchitecture
{
protected override void Init()
{
RegisterModel(new PlayerModel());
RegisterSystem(new CombatSystem());
RegisterUtility(new StorageUtility());
}
protected override void InstallModules()
{
InstallGodotModule(new AudioModule());
InstallGodotModule(new InputModule());
}
}
```
### IGodotModule
Godot 模块接口,继承自 IArchitectureModule。
#### 属性
```csharp
Node Node { get; }
```
#### 方法
```csharp
void Install(IArchitecture architecture);
void OnAttach(Architecture architecture);
void OnDetach(Architecture architecture);
void OnPhase(ArchitecturePhase phase, IArchitecture architecture);
```
#### 使用示例
```csharp
public class AudioModule : AbstractGodotModule
{
// 模块节点本身
public override Node Node => this;
private AudioStreamPlayer _musicPlayer;
public override void Install(IArchitecture architecture)
{
// 注册音频系统
architecture.RegisterSystem(new AudioSystem());
architecture.RegisterUtility(new AudioUtility());
}
public override void OnAttach(Architecture architecture)
{
// 创建音频播放器
_musicPlayer = new AudioStreamPlayer();
AddChild(_musicPlayer);
Logger.Info("Audio module attached");
}
public override void OnDetach(Architecture architecture)
{
// 清理音频播放器
_musicPlayer?.QueueFree();
Logger.Info("Audio module detached");
}
public override void OnPhase(ArchitecturePhase phase, IArchitecture architecture)
{
switch (phase)
{
case ArchitecturePhase.Ready:
PlayBackgroundMusic();
break;
}
}
private void PlayBackgroundMusic()
{
var music = GD.Load<AudioStream>("res://audio/background.ogg");
_musicPlayer.Stream = music;
_musicPlayer.Play();
}
}
```
### AbstractGodotModule
Godot 模块抽象基类,实现了 IGodotModule 接口。
#### 使用示例
```csharp
[ContextAware]
[Log]
public partial class SaveModule : AbstractGodotModule
{
private Timer _autoSaveTimer;
public override void Install(IArchitecture architecture)
{
architecture.RegisterSystem(new SaveSystem());
architecture.RegisterUtility(new SaveUtility());
}
public override void OnAttach(Architecture architecture)
{
// 创建自动保存计时器
_autoSaveTimer = new Timer();
_autoSaveTimer.WaitTime = 300; // 5分钟
_autoSaveTimer.Timeout += OnAutoSave;
AddChild(_autoSaveTimer);
_autoSaveTimer.Start();
Logger.Info("Save module attached with auto-save enabled");
}
private void OnAutoSave()
{
var saveSystem = Context.GetSystem<SaveSystem>();
saveSystem.SaveGame("autosave");
Logger.Debug("Auto-save completed");
}
}
```
## Node 扩展方法
### 安全节点获取
#### GetNodeX<T>()
安全获取子节点,自动类型转换和 null 检查。
```csharp
public static T GetNodeX<T>(this Node node, string path) where T : class;
```
#### 使用示例
```csharp
// 安全获取节点
var player = GetNodeX<Player>("Player");
var healthBar = GetNodeX<ProgressBar>("UI/HealthBar");
// 如果节点不存在或类型不匹配,会抛出异常
// 使用时不需要额外的 null 检查
```
#### GetChildX<T>()
安全查找子节点,支持递归查找。
```csharp
public static T GetChildX<T>(this Node node, string path) where T : class;
```
#### 使用示例
```csharp
// 递归查找子节点
var player = FindChildX<Player>("Player");
var sprite = FindChildX<Sprite2D>("Enemy/Sprite");
```
### 节点验证
#### IsValidNode()
检查节点是否有效且在场景树中。
```csharp
public static bool IsValidNode(this Node node);
```
#### IsInvalidNode()
检查节点是否无效或不在场景树中。
```csharp
public static bool IsInvalidNode(this Node node);
```
#### 使用示例
```csharp
Node someNode = GetNode("SomeNode");
if (IsValidNode(someNode))
{
someNode.DoSomething();
}
if (IsInvalidNode(someNode))
{
// 节点无效,需要重新获取
}
```
### 安全节点操作
#### AddChildX()
安全添加子节点,包含验证。
```csharp
public static void AddChildX(this Node parent, Node child, bool forceReadableName = false, InternalMode internalMode = 0);
```
#### QueueFreeX()
安全销毁节点,包含验证。
```csharp
public static void QueueFreeX(this Node node);
```
#### FreeX()
立即销毁节点,谨慎使用。
```csharp
public static void FreeX(this Node node);
```
#### 使用示例
```csharp
// 创建并添加子节点
var bullet = bulletScene.Instantiate<Bullet>();
AddChildX(bullet);
// 安全销毁节点
bullet.QueueFreeX();
// 立即销毁(谨慎使用)
tempNode.FreeX();
```
### 异步节点操作
#### WaitUntilReady()
等待节点准备就绪。
```csharp
public static async Task WaitUntilReady(this Node node);
```
#### WaitUntil()
等待条件满足。
```csharp
public static async Task WaitUntil(this Node node, Func<bool> condition);
```
#### WaitUntilTimeout()
等待指定时间或条件满足。
```csharp
public static async Task WaitUntilTimeout(this Node node, float timeoutSeconds);
```
#### 使用示例
```csharp
// 等待节点准备就绪
await this.WaitUntilReady();
// 等待条件满足
await this.WaitUntil(() => SomeCondition());
// 等待 2 秒
await this.WaitUntilTimeout(2.0f);
```
### 场景树操作
#### GetParentX<T>()
安全获取父节点。
```csharp
public static T GetParentX<T>(this Node node) where T : class;
```
#### ForEachChild()
遍历所有子节点。
```csharp
public static void ForEachChild<T>(this Node node, Action<T> action) where T : Node;
```
#### 使用示例
```csharp
// 获取父节点
var parent = GetParentX<GameLevel>();
// 遍历所有子节点
this.ForEachChild<Node>(child => {
if (child is Sprite2D sprite)
{
ProcessSprite(sprite);
}
});
```
## 信号系统
### SignalBuilder
信号构建器,提供流畅的信号连接 API。
#### 构造函数
```csharp
public SignalBuilder(Node node);
```
#### 连接方法
```csharp
public SignalBuilder Connect(Callable callable);
public SignalBuilder Connect<T1>(Callable<T1> callable);
public SignalBuilder Connect<T1, T2>(Callable<T1, T2> callable);
public SignalBuilder Connect<T1, T2, T3>(Callable<T1, T2, T3> callable);
public SignalBuilder Connect<T1, T2, T3, T4>(Callable<T1, T2, T3, T4> callable);
```
#### 配置方法
```csharp
public SignalBuilder WithFlags(ConnectFlags flags);
public SignalBuilder CallImmediately();
```
#### 生命周期方法
```csharp
public SignalBuilder UnRegisterWhenNodeExitTree(Node node);
public SignalBuilder AddToUnregisterList(IUnRegisterList unregisterList);
```
#### 使用示例
```csharp
// 基础连接
this.CreateSignalBuilder(Button.SignalName.Pressed)
.Connect(OnButtonPressed)
.UnRegisterWhenNodeExitTree(this);
// 带标志的连接
this.CreateSignalBuilder(Timer.SignalName.Timeout)
.WithFlags(ConnectFlags.OneShot)
.Connect(OnTimerTimeout);
// 立即调用连接
this.CreateSignalBuilder(CustomSignal.SignalName.CustomEvent)
.CallImmediately()
.Connect(OnCustomEvent);
// 多参数连接
this.CreateSignalBuilder()
.AddSignal(SignalName.Parameter1, OnParameter1)
.AddSignal(SignalName.Parameter2, OnParameter2)
.AddSignal(SignalName.Parameter3, OnParameter3)
.UnRegisterWhenNodeExitTree(this);
```
### SignalExtension
信号扩展方法,简化信号创建。
#### CreateSignalBuilder()
创建信号构建器。
```csharp
public static SignalBuilder CreateSignalBuilder(this Node node, string signalName);
```
#### ConnectSignal()
直接连接信号。
```csharp
public static IUnRegister ConnectSignal(this Node node, string signalName, Callable callable);
public static IUnRegister ConnectSignal<T1>(this Node node, string signalName, Callable<T1> callable);
```
#### 使用示例
```csharp
// 创建信号构建器连接
this.CreateSignalBuilder(Button.SignalName.Pressed)
.Connect(OnButtonPressed);
// 直接连接信号
this.ConnectSignal(Button.SignalName.Pressed, Callable.From(OnButtonPressed));
// 多参数信号连接
this.ConnectSignal(ComplexSignal.SignalName.DataChanged,
Callable.From(OnDataChanged));
```
### 信号与框架事件桥接
#### SignalEventBridge
信号事件桥接器,将 Godot 信号转换为框架事件。
#### 使用示例
```csharp
[ContextAware]
[Log]
public partial class GameController : Node, IController
{
public override void _Ready()
{
// Godot 信号 -> 框架事件
this.CreateSignalBuilder(Button.SignalName.Pressed)
.Connect(() => {
Context.SendEvent(new ButtonClickEvent { ButtonId = "start" });
})
.UnRegisterWhenNodeExitTree(this);
// 框架事件 -> Godot 信号
this.RegisterEvent<PlayerHealthChangeEvent>(OnPlayerHealthChange)
.UnRegisterWhenNodeExitTree(this);
}
private void OnPlayerHealthChange(PlayerHealthChangeEvent e)
{
// 更新 Godot UI
var healthBar = GetNode<ProgressBar>("UI/HealthBar");
healthBar.Value = (float)e.NewHealth / e.MaxHealth * 100;
// 发送 Godot 信号
EmitSignal(SignalName.HealthUpdated, e.NewHealth, e.MaxHealth);
}
[Signal]
public delegate void HealthUpdatedEventHandler(int newHealth, int maxHealth);
}
```
## 节点池化
### AbstractNodePoolSystem<TKey, TNode>
节点池化系统基类TNode 必须是 Node。
#### 抽象方法
```csharp
protected abstract TNode CreateItem(TKey key);
protected abstract void OnSpawn(TNode item, TKey key);
protected abstract void OnDespawn(TNode item);
protected abstract bool CanDespawn(TNode item);
```
#### 公共方法
```csharp
public TNode Spawn(TKey key);
public void Despawn(TNode item);
public void DespawnAll();
public int GetActiveCount(TKey key);
public int GetTotalCount(TKey key);
```
#### 使用示例
```csharp
public class BulletPoolSystem : AbstractNodePoolSystem<string, Bullet>
{
private readonly Dictionary<string, PackedScene> _scenes = new();
public BulletPoolSystem()
{
_scenes["player"] = GD.Load<PackedScene>("res://scenes/PlayerBullet.tscn");
_scenes["enemy"] = GD.Load<PackedScene>("res://scenes/EnemyBullet.tscn");
}
protected override Bullet CreateItem(string key)
{
if (_scenes.TryGetValue(key, out var scene))
{
return scene.Instantiate<Bullet>();
}
throw new ArgumentException($"Unknown bullet type: {key}");
}
protected override void OnSpawn(Bullet item, string key)
{
item.Reset();
item.Position = Vector2.Zero;
item.Visible = true;
item.SetCollisionLayerValue(1, true);
item.SetCollisionMaskValue(1, true);
}
protected override void OnDespawn(Bullet item)
{
item.Visible = false;
item.SetCollisionLayerValue(1, false);
item.SetCollisionMaskValue(1, false);
// 移除父节点
item.GetParent()?.RemoveChild(item);
}
protected override bool CanDespawn(Bullet item)
{
return !item.IsActive && item.GetParent() != null;
}
}
// 使用示例
var bulletPool = new BulletPoolSystem();
// 从池中获取子弹
var bullet = bulletPool.Spawn("player");
AddChild(bullet);
// 回收子弹
bulletPool.Despawn(bullet);
```
### IPoolableNode
可池化节点接口。
```csharp
public interface IPoolableNode
{
void Reset();
void SetActive(bool active);
bool IsActive { get; }
}
```
#### 使用示例
```csharp
public partial class Bullet : Area2D, IPoolableNode
{
[Export] public float Speed { get; set; } = 500.0f;
[Export] public float Damage { get; set; } = 10.0f;
private bool _isActive;
public bool IsActive => _isActive;
public void Reset()
{
Position = Vector2.Zero;
Rotation = 0;
Velocity = Vector2.Zero;
_isActive = false;
}
public void SetActive(bool active)
{
_isActive = active;
Visible = active;
SetProcess(active);
}
public override void _Ready()
{
BodyEntered += OnBodyEntered;
}
private void OnBodyEntered(Node body)
{
if (body is Enemy enemy && _isActive)
{
enemy.TakeDamage(Damage);
// 子弹命中敌人,回收到池中
var bulletPool = GetNode<BulletPoolSystem>("/root/BulletPool");
bulletPool?.Despawn(this);
}
}
public override void _Process(double delta)
{
if (!_isActive) return;
Position += Transform.X * (float)(Speed * delta);
}
}
```
## 资源管理
### ResourceLoadUtility
资源加载工具类,简化和缓存 Godot 资源加载。
#### 构造函数
```csharp
public ResourceLoadUtility();
```
#### 方法
```csharp
public T LoadResource<T>(string path) where T : Resource;
public async Task<T> LoadResourceAsync<T>(string path) where T : Resource;
public void PreloadResource<T>(string path) where T : Resource;
public bool HasResource<T>(string path) where T : Resource;
```
#### 使用示例
```csharp
var resourceLoader = new ResourceLoadUtility();
// 同步加载资源
var playerTexture = resourceLoader.LoadResource<Texture2D>("res://textures/player.png");
var playerScene = resourceLoader.LoadResource<PackedScene>("res://scenes/Player.tscn");
// 异步加载资源
var musicStream = await resourceLoader.LoadResourceAsync<AudioStream>("res://audio/background.ogg");
// 预加载资源
resourceLoader.PreloadResource<Texture2D>("res://textures/enemy.png");
resourceLoader.PreloadResource<PackedScene>("res://scenes/enemy.tscn");
```
### AbstractResourceFactoryUtility
抽象资源工厂工具基类。
#### 抽象方法
```csharp
protected abstract void RegisterFactories();
protected abstract T CreateFactory<T>(string path, Dictionary<string, object> metadata = null) where T : class;
```
#### 使用示例
```csharp
public class GameResourceFactory : AbstractResourceFactoryUtility
{
protected override void RegisterFactories()
{
RegisterFactory<PlayerData>("res://data/players/{id}.json");
RegisterFactory<WeaponConfig>("res://data/weapons/{id}.json");
RegisterFactory<LevelConfig>("res://data/levels/{id}.json");
}
public PlayerData CreatePlayer(string playerId)
{
return CreateFactory<PlayerData>($"res://data/players/{playerId}.json");
}
public WeaponConfig CreateWeapon(string weaponId)
{
var metadata = new Dictionary<string, object>
{
["weaponId"] = weaponId,
["loadTime"] = DateTime.Now
};
return CreateFactory<WeaponConfig>($"res://data/weapons/{weaponId}.json", metadata);
}
}
```
## 日志系统
### GodotLogger
Godot 特定的日志实现。
#### 构造函数
```csharp
public GodotLogger(string categoryName);
public GodotLogger(string categoryName, LogLevel minLevel);
```
#### 方法
```csharp
public void Log<T>(LogLevel level, T message, params object[] args);
public void Debug<T>(T message, params object[] args);
public void Info<T>(T message, params object[] args);
public void Warning<T>(T message, params object[] args);
public void Error<T>(T message, params object[] args);
public void Error<T>(Exception exception, T message, params object[] args);
```
#### 使用示例
```csharp
// 创建日志器
var logger = new GodotLogger("GameController");
// 不同级别的日志
logger.Debug("Player position: {0}", player.Position);
logger.Info("Game started");
logger.Warning("Low health: {0}", player.Health);
logger.Error("Failed to load resource: {0}", resourcePath);
// 带异常的错误日志
logger.Error(exception, "An error occurred while processing player input");
```
### GodotLoggerFactory
Godot 日志工厂。
#### 方法
```csharp
public ILogger CreateLogger(string categoryName);
public ILogger CreateLogger(Type type);
```
#### 使用示例
```csharp
var factory = new GodotLoggerFactory();
// 创建日志器
var gameLogger = factory.CreateLogger("GameController");
var playerLogger = factory.CreateLogger(typeof(PlayerController));
// 在架构中使用
public class GameArchitecture : AbstractArchitecture
{
protected override void Init()
{
LoggerProperties = new LoggerProperties
{
LoggerFactoryProvider = new GodotLoggerFactoryProvider(),
MinLevel = LogLevel.Info
};
RegisterSystem(new GameController());
}
}
```
## 池化管理
### AbstractObjectPool<T>
通用对象池基类。
#### 构造函数
```csharp
public AbstractObjectPool(
Func<T> createFunc,
Action<T> actionOnGet = null,
Action<T> actionOnRelease = null,
bool collectionCheck = false
);
```
#### 方法
```csharp
public T Get();
public void Release(T item);
public void Clear();
public int CountInactive { get; }
public int CountAll { get; }
```
#### 使用示例
```csharp
// 创建对象池
var explosionPool = new AbstractObjectPool<ExplosionEffect>(
createFunc: () => new ExplosionEffect(),
actionOnGet: effect => effect.Reset(),
actionOnRelease: effect => Cleanup()
);
// 使用对象池
var effect = explosionPool.Get();
effect.Play(effect.Position);
// 回收对象
explosionPool.Release(effect);
```
---
## 音频系统
### AudioSystem
音频系统,管理音乐和音效播放。
#### 使用示例
```csharp
[ContextAware]
[Log]
public partial class AudioSystem : AbstractSystem
{
private AudioStreamPlayer _musicPlayer;
private readonly Dictionary<string, AudioStream> _soundCache = new();
protected override void OnInit()
{
InitializeAudioPlayers();
CacheSounds();
// 监听音频事件
this.RegisterEvent<PlaySoundEvent>(OnPlaySound);
this.RegisterEvent<PlayMusicEvent>(OnPlayMusic);
this.RegisterEvent<StopMusicEvent>(OnStopMusic);
this.RegisterEvent<SetVolumeEvent>(OnSetVolume);
}
private void InitializeAudioPlayers()
{
_musicPlayer = new AudioStreamPlayer();
AddChild(_musicPlayer);
// 配置音乐播放器
_musicPlayer.Bus = "Music";
}
private void CacheSounds()
{
var soundPaths = new[]
{
"res://audio/jump.wav",
"res://audio/attack.wav",
"res://audio/hurt.wav",
"res://audio/victory.wav"
};
foreach (var path in soundPaths)
{
var sound = GD.Load<AudioStream>(path);
var soundName = Path.GetFileNameWithoutExtension(path);
_soundCache[soundName] = sound;
}
}
private void OnPlaySound(PlaySoundEvent e)
{
if (_soundCache.TryGetValue(e.SoundName, out var sound))
{
PlaySound(sound);
}
else
{
Logger.Warning($"Sound not found: {e.SoundName}");
}
}
private void PlayMusic(PlayMusicEvent e)
{
var music = GD.Load<AudioStream>(e.MusicPath);
_musicPlayer.Stream = music;
_musicPlayer.Play();
Logger.Info($"Playing music: {e.MusicPath}");
}
private void OnStopMusic(StopMusicEvent e)
{
_musicPlayer.Stop();
Logger.Info("Music stopped");
}
private void OnSetVolume(SetVolumeEvent e)
{
AudioServer.SetBusVolume(e.BusName, e.Volume);
Logger.Info($"Set volume for bus {e.BusName}: {e.Volume}");
}
private void PlaySound(AudioStream sound)
{
var player = new AudioStreamPlayer();
player.Stream = sound;
player.Bus = "SFX";
player.Play();
// 自动清理播放器
this.CreateSignalBuilder(player.SignalName.Finished)
.WithFlags(ConnectFlags.OneShot)
.Connect(() => player.QueueFree())
.UnRegisterWhenNodeExitTree(this);
}
}
// 音频事件
public struct PlaySoundEvent { public string SoundName; }
public struct PlayMusicEvent { public string MusicPath; }
public struct StopMusicEvent { }
public struct SetVolumeEvent { public string BusName; public float Volume; }
```
---
**文档版本**: 1.0.0
**更新日期**: 2026-01-12

View File

@ -1,601 +0,0 @@
# GFramework.SourceGenerators API 参考
> GFramework.SourceGenerators 模块的完整 API 参考文档,包含所有源代码生成器的详细说明。
## 📋 目录
- [日志生成器](#日志生成器)
- [上下文感知生成器](#上下文感知生成器)
- [枚举扩展生成器](#枚举扩展生成器)
- [诊断系统](#诊断系统)
- [通用工具](#通用工具)
## 日志生成器
### [Log] 属性
为标记的类自动生成 ILogger 字段。
#### 构造函数参数
```csharp
[Log(
string fieldName = "Logger", // 生成的字段名
AccessModifier accessModifier = AccessModifier.Private, // 访问修饰符
bool isStatic = true, // 是否生成静态字段
string loggerName = null, // 自定义日志器名称
LogLevel minLevel = LogLevel.None, // 最小日志级别
bool includeLoggerInterface = false // 是否包含 ILogger 接口
bool enableConditionalCompilation = false // 是否启用条件编译
string loggerInterfaceName = "ILogger" // 日志接口名称
bool suppressAutoGeneratedAttribute = false // 是否抑制自动生成属性
string category = null // 日志类别
bool forceContextualLogging = false // 是否强制上下文日志
bool enableStructuredLogging = false // 是否启用结构化日志
string loggerFactoryName = null // 日志工厂名称
string logMessagePrefix = null // 日志消息前缀
bool enablePerformanceLogging = false // 是否启用性能日志
bool enableAsyncLogging = false // 是否启用异步日志
bool enableFluentLogging = false // 是否启用流畅日志
bool enableScopedLogging = false // 是否启用作用域日志
)]
```
#### 生成的代码示例
```csharp
// 默认配置生成的代码
public partial class MyClass
{
private static readonly ILogger Logger =
LoggerFactory.Create(builder => builder
.AddConsole()
.SetMinimumLevel(LogLevel.Information)
.CreateLogger<MyClass>());
}
// 自定义配置生成的代码
[Log(
fieldName = "CustomLogger",
accessModifier = AccessModifier.Public,
isStatic = false,
loggerName = "Custom.MyClass",
minLevel = LogLevel.Debug,
includeLoggerInterface = true
)]
public partial class CustomClass : ILogger
{
public ILogger CustomLogger { get; }
static CustomClass()
{
CustomLogger = LoggerFactory.Create(builder => builder
.AddConsole()
.SetMinimumLevel(LogLevel.Debug)
.CreateLogger<CustomClass>());
}
}
```
#### 支持的方法
生成的 Logger 支持以下方法:
```csharp
// 基础日志方法
Logger.LogDebug("Debug message");
Logger.LogInformation("Info message");
Logger.LogWarning("Warning message");
Logger.LogError("Error message");
Logger.LogCritical("Critical message");
// 带格式化的日志方法
Logger.LogInformation("Player {Name} has {Health} health", playerName, playerHealth);
// 异步日志方法
await Logger.LogInformationAsync("Async message");
// 结构化日志
Logger.LogInformation(new { PlayerName = "John", Health = 100 }, "Player {Name} has {Health} health");
```
## 上下文感知生成器
### [ContextAware] 属性
为标记的类自动实现 IContextAware 接口。
#### 生成的代码示例
```csharp
[ContextAware]
public partial class MyClass : IContextAware
{
private IContextAware.Context _context;
public IContextAware.Context Context => _context ??= new LazyContext(this);
public void SetContext(IContextAware.Context context)
{
_context = context;
}
public IContextAware.Context GetContext()
{
return _context;
}
}
// 使用延迟初始化
[ContextAware(useLazy = true)]
public partial class LazyContextClass : IContextAware
{
private Lazy<IContextAware.Context> _context;
public IContextAware.Context Context => _context.Value;
public void SetContext(IContextAware.Context context)
{
_context = new Lazy<IContextAware.Context>(() => context);
}
}
// 带上下文验证
[ContextAware(validateContext = true)]
public partial class ValidatedContextClass : IContextAware
{
private IContextAware.Context _context;
public IContextAware.Context Context =>
{
get => _context;
private set
{
_context = value;
if (_context?.IsInvalid == true)
{
throw new InvalidOperationException("Context is invalid");
}
}
}
}
```
#### 可用的方法
```csharp
// 获取模型
var playerModel = Context.GetModel<PlayerModel>();
var gameModel = Context.GetModel<GameModel>();
// 获取系统
var combatSystem = Context.GetSystem<CombatSystem>();
var audioSystem = Context.GetSystem<AudioSystem>();
// 获取工具
var storageUtility = Context.GetUtility<StorageUtility>();
var mathUtility = Context.GetUtility<MathUtility>();
// 发送事件
Context.SendEvent<PlayerDiedEvent>();
Context.SendEvent<DamageDealtEvent>(new DamageDealtEvent { Damage = 50 });
// 发送命令
Context.SendCommand(new AttackCommand());
var result = Context.SendCommand<AttackResult>(new AttackCommand());
// 发送查询
var canAttack = Context.SendQuery<CanAttackQuery>();
var playerData = Context.SendQuery<GetPlayerDataQuery>();
```
## 枚举扩展生成器
### [GenerateEnumExtensions] 属性
为枚举类型自动生成扩展方法。
#### 构造函数参数
```csharp
[GenerateEnumExtensions(
bool generateIsMethods = true, // 是否生成 IsX() 方法
bool generateHasMethod = true, // 是否生成 HasX() 方法
bool generateInMethod = true, // 是否生成 In(params T[]) 方法
bool generateTryParseMethod = false, // 是否生成 TryParse() 方法
string customPrefix = "Is", // 自定义方法名前缀
bool includeToString = false, // 是否生成 ToString 扩展
bool generateAllMethod = false, // 是否生成 All() 方法
bool generateCountMethod = false, // 是否生成 Count() 方法
bool generateDescriptionMethod = false, // 是否生成 Description() 方法
bool generateValuesMethod = false, // 是否生成 Values() 方法
string customNamespace = null, // 自定义命名空间
bool generateExtensionMethods = true, // 是否生成扩展方法
bool generateFlagMethods = true, // 是否为位标志枚举生成方法
bool generateValidationMethods = false, // 是否生成验证方法
bool generateUtilityMethods = false, // 是否生成工具方法
bool generateQueryableMethods = false, // 是否生成查询方法
string customMethodNameFormat = null, // 自定义方法名格式
bool generateDocumentation = false, // 是否生成文档注释
bool generateExamples = false, // 是否生成使用示例
)]
```
#### 普通枚举生成的代码示例
```csharp
[GenerateEnumExtensions]
public enum PlayerState
{
Idle,
Walking,
Running,
Jumping,
Attacking
}
// 生成的扩展方法
public static class PlayerStateExtensions
{
public static bool IsIdle(this PlayerState state) => state == PlayerState.Idle;
public static bool IsWalking(this PlayerState state) => state == PlayerState.Walking;
public static bool IsRunning(this PlayerState state) => state == PlayerState.Running;
public static bool IsJumping(this PlayerState state) => state == PlayerState.Jumping;
public static bool IsAttacking(this PlayerState state) => state == PlayerState.Attacking;
public static bool In(this PlayerState state, params PlayerState[] values)
{
return values.Contains(state);
}
}
```
#### 位标志枚举生成的代码示例
```csharp
[GenerateEnumExtensions]
[Flags]
public enum PlayerPermissions
{
None = 0,
CanMove = 1 << 0,
CanAttack = 1 << 1,
CanUseItems = 1 << 2,
CanChat = 1 << 3,
CanTrade = 1 << 4
}
// 生成的扩展方法
public static class PlayerPermissionsExtensions
{
public static bool HasCanMove(this PlayerPermissions permissions) => permissions.HasFlag(PlayerPermissions.CanMove);
public static bool HasCanAttack(this PlayerPermissions permissions) => permissions.HasFlag(PlayerPermissions.CanAttack);
public static bool HasCanUseItems(this PlayerPermissions permissions) => permissions.HasFlag(PlayerPermissions.CanUseItems);
public static bool HasAny(this PlayerPermissions permissions, params PlayerPermissions[] flags)
{
return flags.Any(flag => permissions.HasFlag(flag));
}
public static bool HasAll(this PlayerPermissions permissions, params PlayerPermissions[] flags)
{
return flags.All(flag => permissions.HasFlag(flag));
}
public static PlayerPermissions Add(this PlayerPermissions permissions, PlayerPermissions other)
{
return permissions | other;
}
public static PlayerPermissions Remove(this PlayerPermissions permissions, PlayerPermissions other)
{
return permissions & ~other;
}
public static PlayerPermissions Toggle(this PlayerPermissions permissions, PlayerPermissions flag)
{
return permissions ^ flag;
}
}
```
#### 高级功能示例
```csharp
[GenerateEnumExtensions(
customPrefix = "Is",
includeToString = true,
generateDescriptionMethod = true,
generateUtilityMethods = true
)]
public enum GameState
{
[Description("游戏菜单状态")]
Menu,
[Description("游戏进行中")]
Playing,
[Description("游戏暂停")]
Paused,
[Description("游戏结束")]
GameOver
}
// 生成的扩展方法包含更多功能
public static class GameStateExtensions
{
// IsX() 方法
public static bool IsMenu(this GameState state) => state == GameState.Menu;
public static bool IsPlaying(this GameState state) => state == GameState.Playing;
public static bool IsPaused(this GameState state) => state == GameState.Paused;
public static bool IsGameOver(this GameState state) => state == GameState.GameOver;
// ToString() 扩展
public static string ToDisplayString(this GameState state)
{
return state switch
{
GameState.Menu => "游戏菜单",
GameState.Playing => "游戏进行中",
GameState.Paused => "游戏暂停",
GameState.GameOver => "游戏结束"
};
}
// Description() 扩展
public static string GetDescription(this GameState state)
{
return typeof(GameState)
.GetMember(state.ToString())
?.GetCustomAttribute<DescriptionAttribute>()
?.Description ?? state.ToString();
}
// 工具方法
public static bool IsFinalState(this GameState state) => state == GameState.GameOver;
public static bool IsPlayingState(this GameState state) => state == GameState.Playing;
public static bool CanPause(this GameState state) => state == GameState.Playing;
// 验证方法
public static bool IsValidTransition(this GameState from, GameState to)
{
return (from, to) switch
{
(GameState.Menu, GameState.Playing) => true,
(GameState.Playing, GameState.Paused) => true,
(GameState.Paused, GameState.Playing) => true,
(GameState.Playing, GameState.GameOver) => true,
_ => false
};
}
}
```
## 诊断系统
### GF_Logging_001 - 日志字段名冲突
当使用 `[Log]` 属性时,如果已存在同名字段或属性,会触发此诊断。
#### 示例
```csharp
// 错误示例:字段名冲突
[Log(fieldName = "Logger")]
public partial class MyClass
{
private readonly ILogger Logger; // ❌ 冲突!
}
// 正确的解决方案
[Log(fieldName = "CustomLogger")]
public partial class MyClass
{
private readonly ILogger CustomLogger; // ✅ 使用不同的字段名
}
```
#### 诊断消息
```
error GF_Logging_001: Logger field name 'Logger' conflicts with existing field in type 'MyClass'
```
### GF_Rule_001 - 上下文感知接口冲突
当使用 `[ContextAware]` 属性时,如果类型已经实现了 IContextAware 接口,会触发此诊断。
#### 示例
```csharp
// 错误示例:接口冲突
[ContextAware]
public partial class MyClass : IContextAware // ❌ 冲突!
{
public IContextAware.Context Context { get; set; }
public void SetContext(IContextAware.Context context) { }
public IContextAware.Context GetContext() { return Context; }
}
// 正确的解决方案:移除手动实现
[ContextAware]
public partial class MyClass // ✅ 让生成器实现接口
{
// 移除手动实现的代码
}
```
#### 诊断消息
```
error GF_Rule_001: Type 'MyClass' already implements 'IContextAware' interface. Remove the [ContextAware] attribute or manual implementation.
```
## 通用工具
### TypeHelper
类型操作的工具类。
#### 主要方法
```csharp
public static class TypeHelper
{
// 类型检查
public static bool IsNullable(Type type);
public static bool IsGenericType(Type type);
public static bool IsValueType(Type type);
public static bool IsEnum(Type type);
// 泛型类型信息
public static Type GetGenericTypeDefinition(Type type);
public static Type[] GetGenericArguments(Type type);
public static bool ImplementsInterface(Type type, Type interfaceType);
// 属性信息
public static PropertyInfo[] GetProperties(Type type, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance);
public static PropertyInfo GetProperty(Type type, string name, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance);
public static bool HasProperty(Type type, string name);
// 方法信息
public static MethodInfo[] GetMethods(Type type, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance);
public static MethodInfo GetMethod(Type type, string name, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance);
public static bool HasMethod(Type type, string name);
// 构造函数信息
public static ConstructorInfo[] GetConstructors(Type type, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance);
public static ConstructorInfo GetConstructor(Type type, Type[] parameterTypes);
// 可实例化检查
public static bool HasParameterlessConstructor(Type type);
public static bool HasConstructor(Type type, params Type[] parameterTypes);
}
```
### SymbolHelper
符号操作的工具类。
#### 主要方法
```csharp
public static class SymbolHelper
{
// 获取符号信息
public static ITypeSymbol GetSymbolInfo(INamedTypeSymbol symbol, Compilation compilation);
public static IMethodSymbol GetMethodInfo(IMethodSymbol symbol);
public static IPropertySymbol GetPropertyInfo(IPropertySymbol symbol);
public static IEventSymbol GetEventInfo(IEventSymbol symbol);
// 符号比较
public static bool IsSameSymbol(ISymbol symbol1, ISymbol symbol2);
public static string GetFullyQualifiedName(ISymbol symbol);
public static string GetDocumentationCommentXml(ISymbol symbol);
// 符号查找
public static IEnumerable<ISymbol> GetMembers(INamedTypeSymbol symbol);
public static ISymbol GetMember(INamedTypeSymbol symbol, string name);
public static IEnumerable<AttributeData> GetAttributes(ISymbol symbol);
public static T GetAttribute<T>(ISymbol symbol);
public static bool HasAttribute<T>(ISymbol symbol);
}
```
### CompilationHelper
编译操作的工具类。
#### 主要方法
```csharp
public static class CompilationHelper
{
// 获取编译
public static Compilation GetCompilation(Compilation startingCompilation);
public static Compilation GetCompilation(SyntaxTree syntaxTree);
public static Compilation GetCompilation(IEnumerable<SyntaxTree> syntaxTrees);
// 获取语义模型
public static SemanticModel GetSemanticModel(Compilation compilation);
public static SemanticModel GetSemanticModel(SyntaxTree syntaxTree);
// 符号查找
public static INamedTypeSymbol GetDeclaredTypeSymbol(Compilation compilation, string name);
public static IMethodSymbol GetDeclaredMethodSymbol(Compilation compilation, string name);
public static IPropertySymbol GetDeclaredPropertySymbol(Compilation compilation, string name);
// 类型解析
public static INamedTypeSymbol ResolveType(Compilation compilation, string metadataName);
public static ITypeSymbol ResolveType(Compilation compilation, Type type);
public static IMethodSymbol ResolveMethod(Compilation compilation, string methodFullName, params ITypeSymbol[] parameterTypes);
// 编译检查
public static bool HasCompilationErrors(Compilation compilation);
public static IEnumerable<Diagnostic> GetCompilationDiagnostics(Compilation compilation);
public static string GetCompilationErrors(Compilation compilation);
}
```
---
## 配置示例
### 项目文件配置
```xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GeWuYou.GFramework.SourceGenerators" Version="1.0.0" />
<PackageReference Include="GeWuYou.GFramework.SourceGenerators.Attributes" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<Compile Remove="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
</ItemGroup>
</Project>
```
### 编辑器配置
```json
{
"sourceGenerators": {
"debug": true,
"logLevel": "Information",
"outputDirectory": "Generated",
"enableDocumentation": true,
"enablePerformanceLogging": false
},
"loggingGenerator": {
"defaultFieldName": "Logger",
"defaultAccessLevel": "Private",
"defaultStatic": true,
"defaultMinLevel": "None"
},
"contextAwareGenerator": {
"useLazyInit": false,
"validateContext": false
},
"enumExtensionsGenerator": {
"generateIsMethods": true,
"generateHasMethod": true,
"generateInMethod": true,
"customPrefix": "Is"
}
}
```
---
**文档版本**: 1.0.0
**更新日期**: 2026-01-12

View File

@ -284,23 +284,23 @@ public class PlayerController : IController
## 包说明
| 包名 | 职责 | 文档 |
|------------------|-----------------|------------------------------------|
| **architecture** | 架构核心,管理所有组件生命周期 | [查看](/core/architecture/README.md) |
| **constants** | 框架常量定义 | 本文档 |
| **model** | 数据模型层,存储状态 | [查看](/core/model/README.md) |
| **system** | 业务逻辑层,处理业务规则 | [查看](/core/system/README.md) |
| **controller** | 控制器层,连接视图和逻辑 | (在 Abstractions 中) |
| **utility** | 工具类层,提供无状态工具 | [查看](/core/utility/README.md) |
| **command** | 命令模式,封装写操作 | [查看](/core/command/README.md) |
| **query** | 查询模式,封装读操作 | [查看](/core/query/README.md) |
| **events** | 事件系统,组件间通信 | [查看](/core/events/README.md) |
| **property** | 可绑定属性,响应式编程 | [查看](/core/property/README.md) |
| **ioc** | IoC 容器,依赖注入 | [查看](/core/ioc/README.md) |
| **rule** | 规则接口,定义组件约束 | [查看](/core/rule/README.md) |
| **extensions** | 扩展方法,简化 API 调用 | [查看](/core/extensions/README.md) |
| **logging** | 日志系统,记录运行日志 | [查看](/core/logging/README.md) |
| **environment** | 环境接口,提供运行环境信息 | [查看](/core/environment/README.md) |
| 包名 | 职责 | 文档 |
|------------------|-----------------|----------------------|
| **architecture** | 架构核心,管理所有组件生命周期 | [查看](./architecture) |
| **constants** | 框架常量定义 | 本文档 |
| **model** | 数据模型层,存储状态 | [查看](./model) |
| **system** | 业务逻辑层,处理业务规则 | [查看](./system) |
| **controller** | 控制器层,连接视图和逻辑 | (在 Abstractions 中) |
| **utility** | 工具类层,提供无状态工具 | [查看](./utility) |
| **command** | 命令模式,封装写操作 | [查看](./command) |
| **query** | 查询模式,封装读操作 | [查看](./query) |
| **events** | 事件系统,组件间通信 | [查看](./events) |
| **property** | 可绑定属性,响应式编程 | [查看](./property) |
| **ioc** | IoC 容器,依赖注入 | [查看](./ioc) |
| **rule** | 规则接口,定义组件约束 | [查看](./rule) |
| **extensions** | 扩展方法,简化 API 调用 | [查看](./extensions) |
| **logging** | 日志系统,记录运行日志 | [查看](./logging) |
| **environment** | 环境接口,提供运行环境信息 | [查看](./environment) |
## 组件联动

View File

@ -0,0 +1,503 @@
# 场景管理
> GFramework.Game 模块提供的场景管理功能,实现游戏场景的加载、切换和状态管理
## 概述
GFramework.Game 提供了统一的场景管理系统,支持场景的异步加载、切换动画、状态保持等功能。通过场景管理,您可以优雅地处理游戏中的各种场景转换,如主菜单、游戏界面、设置菜单等。
## 核心特性
- **异步加载**:支持后台异步加载场景,避免卡顿
- **场景切换动画**:内置淡入淡出等切换效果
- **状态保持**:场景切换时保持必要的游戏状态
- **场景栈**:支持场景叠加(如弹出菜单)
- **资源管理**:自动管理场景资源的加载和卸载
## 基本用法
### 定义场景
```csharp
using GFramework.Game.scene;
public class GameScene : GameSceneBase
{
protected override void OnLoad()
{
// 场景加载时的初始化
}
protected override void OnUnload()
{
// 场景卸载时的清理
}
public override void OnEnter()
{
// 进入场景
}
public override void OnExit()
{
// 退出场景
}
}
```
### 场景管理器
```csharp
using GFramework.Game.scene;
[ContextAware]
public partial class SceneManager : Node
{
private ISceneManager _sceneManager;
public override void _Ready()
{
_sceneManager = Context.GetSystem<ISceneManager>();
// 初始化场景管理器
_sceneManager.Initialize();
}
public async Task SwitchToGameScene()
{
await _sceneManager.SwitchSceneAsync<GameScene>();
}
}
```
## 场景加载
### 同步加载
适用于小场景的快速切换:
```csharp
public void LoadMainMenu()
{
_sceneManager.SwitchScene<MainMenuScene>();
}
```
### 异步加载
大场景建议使用异步加载:
```csharp
public async Task LoadGameLevel(string levelName)
{
// 显示加载界面
loadingUI.Show();
try
{
// 异步加载场景
await _sceneManager.SwitchSceneAsync<GameLevelScene>(scene =>
{
// 可以在这里传递场景参数
var gameScene = scene as GameLevelScene;
gameScene.LevelName = levelName;
});
GD.Print("场景加载完成");
}
catch (Exception ex)
{
GD.PrintErr($"场景加载失败: {ex.Message}");
loadingUI.ShowError();
}
finally
{
loadingUI.Hide();
}
}
```
### 加载进度
监听加载进度:
```csharp
public async Task LoadSceneWithProgress<TScene>() where TScene : IScene
{
loadingUI.Show();
var progress = new Progress<float>(value =>
{
loadingUI.UpdateProgress(value * 100);
});
await _sceneManager.SwitchSceneAsync<TScene>(progress: progress);
loadingUI.Hide();
}
```
## 场景切换动画
### 内置切换效果
```csharp
public async Task SwitchWithFade()
{
// 使用淡入淡出效果
await _sceneManager.SwitchSceneAsync<GameScene>(
transition: new FadeTransition(
duration: 0.5f,
fadeColor: Colors.Black
)
);
}
public async Task SlideTransition()
{
// 使用滑动效果
await _sceneManager.SwitchSceneAsync<GameScene>(
transition: new SlideTransition(
direction: Vector2.Left,
duration: 0.3f
)
);
}
```
### 自定义切换动画
```csharp
public class CustomTransition : ISceneTransition
{
public float Duration { get; } = 1.0f;
public async Task PlayAsync(Node fromScene, Node toScene)
{
// 自定义动画逻辑
var tween = CreateTween();
// 旧场景缩小消失
tween.TweenProperty(fromScene, "scale", Vector2.Zero, Duration / 2)
.SetTrans(Tween.TransitionType.BackIn);
await ToSignal(tween, Tween.SignalName.Finished);
fromScene.Visible = false;
toScene.Visible = true;
toScene.Scale = Vector2.Zero;
// 新场景放大出现
tween = CreateTween();
tween.TweenProperty(toScene, "scale", Vector2.One, Duration / 2)
.SetTrans(Tween.TransitionType.BackOut);
await ToSignal(tween, Tween.SignalName.Finished);
}
}
```
## 场景栈
### 推送场景
将新场景推入栈中:
```csharp
public void PushPauseMenu()
{
_sceneManager.PushScene<PauseMenuScene>();
}
```
### 弹出场景
弹出栈顶场景:
```csharp
public void PopScene()
{
_sceneManager.PopScene();
}
```
### 示例:带返回的导航
```csharp
public async Task NavigateToSettings()
{
// 保存当前场景引用
var previousScene = _sceneManager.CurrentScene;
// 推入设置场景
await _sceneManager.PushSceneAsync<SettingsScene>();
// 设置场景有返回按钮
await _sceneManager.PushSceneAsync<ConfirmDialog>(
data: new ConfirmData
{
Message = "是否保存设置?",
OnConfirm = () => _sceneManager.PopScene(), // 不保存,直接返回
OnCancel = () =>
{
// 保存设置后返回
SaveSettings();
_sceneManager.PopScene();
}
}
);
}
```
## 场景状态管理
### 保存状态
```csharp
public class GameScene : GameSceneBase
{
private GameState _state;
protected override void OnLoad()
{
// 从存档加载状态
_state = LoadGameState();
}
protected override void OnUnload()
{
// 保存状态
SaveGameState(_state);
}
public override void OnExit()
{
// 清理工作
Cleanup();
}
}
```
### 跨场景数据传递
```csharp
// 传递数据到新场景
await _sceneManager.SwitchSceneAsync<GameScene>(data: new GameData
{
Level = 5,
Difficulty = Difficulty.Hard,
ContinueToken = saveToken
});
// 在目标场景中接收数据
public class GameScene : GameSceneBase
{
public override void OnEnter(object data)
{
var gameData = data as GameData;
InitializeLevel(gameData.Level, gameData.Difficulty);
}
}
```
## 预加载策略
### 预加载资源
```csharp
public void PreloadCommonResources()
{
_sceneManager.PreloadScene<MainMenuScene>();
_sceneManager.PreloadScene<GameLevelScene>(count: 3);
}
```
### 预加载配置
```csharp
var config = new ScenePreloadConfig
{
PreloadCount = 5,
Priority = ResourceLoader.CacheMode.Cache,
Timeout = 30.0f
};
_sceneManager.ConfigurePreload(config);
```
## 资源管理
### 自动卸载
```csharp
// 配置自动卸载策略
var unloadConfig = new SceneUnloadConfig
{
UnloadDelay = 30.0f, // 30秒后卸载
KeepReferences = true, // 保持引用
ForceUnloadOnMemoryPressure = true // 内存紧张时强制卸载
};
_sceneManager.ConfigureUnload(unloadConfig);
```
### 手动卸载
```csharp
// 卸载指定场景
_sceneManager.UnloadScene<MainMenuScene>();
// 卸载所有场景
_sceneManager.UnloadAllScenes();
```
## 最佳实践
### 1. 场景设计原则
```csharp
// 推荐:每个场景职责单一
public class MainMenuScene : GameSceneBase { /* 主菜单 */ }
public class SettingsScene : GameSceneBase { /* 设置菜单 */ }
public class GameHUDScene : GameSceneBase { /* 游戏HUD */ }
// 避免:场景职责过多
public class MegaScene : GameSceneBase
{
/* 包含菜单、设置、HUD、存档管理... 不要这样设计 */
}
```
### 2. 场景切换优化
```csharp
// 推荐:使用异步加载
public async Task LoadGame()
{
loadingUI.Show("正在加载游戏...");
await _sceneManager.SwitchSceneAsync<GameScene>();
}
// 避免:同步加载大场景
public void LoadGame()
{
// 这会导致游戏卡顿
_sceneManager.SwitchScene<GameScene>();
}
```
### 3. 内存管理
```csharp
public class GameScene : GameSceneBase
{
private Texture2D[] _largeTextures;
protected override void OnLoad()
{
// 加载资源
_largeTextures = LoadLargeTextures();
}
protected override void OnUnload()
{
// 及时释放大资源
foreach (var texture in _largeTextures)
{
texture.Dispose();
}
_largeTextures = null;
}
}
```
### 4. 错误处理
```csharp
public async Task SafeLoadScene<TScene>() where TScene : IScene
{
try
{
await _sceneManager.SwitchSceneAsync<TScene>();
}
catch (SceneNotFoundException)
{
Logger.Error($"场景 {typeof(TScene)} 未找到");
// 回退到默认场景
await _sceneManager.SwitchSceneAsync<FallbackScene>();
}
catch (ResourceLoadException ex)
{
Logger.Error($"资源加载失败: {ex.Message}");
await ShowRetryDialog();
}
}
```
## 与其他模块集成
### 与 Game 模块集成
```csharp
public class GameLevelScene : GameSceneBase
{
private GameManager _gameManager;
public override void OnEnter()
{
// 初始化游戏管理器
_gameManager = Context.GetSystem<GameManager>();
_gameManager.StartGame();
}
public override void OnExit()
{
_gameManager.EndGame();
}
}
```
### 与存档系统集成
```csharp
public class GameScene : GameSceneBase
{
private ISaveSystem _saveSystem;
protected override void OnLoad()
{
_saveSystem = Context.GetUtility<ISaveSystem>();
// 检查是否有自动存档
if (_saveSystem.HasAutoSave())
{
var dialog = Context.GetSystem<IDialogSystem>();
await dialog.ShowAsync("发现自动存档,是否继续?",
onConfirm: () => LoadAutoSave(),
onCancel: () => StartNewGame()
);
}
}
private void LoadAutoSave()
{
var saveData = _saveSystem.LoadAutoSave();
RestoreGameState(saveData);
}
public override void OnExit()
{
// 自动保存
_saveSystem.SaveAutoSave(CreateSaveData());
}
}
```
---
**相关文档**
- [Game 概述](./overview)
- [游戏设置](./setting)
- [存储系统](./storage)
- [存档系统](../game/storage)

View File

@ -348,7 +348,7 @@ public class PlayerManager
## 下一步学习
- [深入了解 Architecture 组件](/core/architecture/architecture)
- [掌握事件系统](/core/events/event-bus)
- [学习命令查询模式](/core/command-query/commands)
- [探索属性系统](/core/property/bindable-property)
- [深入了解 Architecture 组件](./core/architecture)
- [掌握事件系统](./core/events)
- [学习命令查询模式](./core/command)
- [探索属性系统](./core/property)

View File

@ -182,6 +182,6 @@ dotnet build
安装完成后,建议:
1. [快速开始](/getting-started/quick-start) - 构建第一个应用
2. [架构概览](/getting-started/architecture-overview) - 了解核心概念
3. [Core 模块文档](/core/overview) - 深入学习核心功能
1. [快速开始](./getting-started/quick-start) - 构建第一个应用
2. [架构概览](./getting-started/architecture-overview) - 了解核心概念
3. [Core 模块文档](./core) - 深入学习核心功能

View File

@ -321,7 +321,7 @@ Press any key to exit...
接下来您可以:
- [深入了解架构组件](/core/architecture/architecture)
- [学习事件系统](/core/events/event-bus)
- [探索 Godot 集成](/godot/overview)(如果您使用 Godot
- [查看完整教程](/tutorials/basic-tutorial)
- [深入了解架构组件](./core/architecture)
- [学习事件系统](./core/events)
- [探索 Godot 集成](./godot/overview)
- [查看完整教程](./tutorials/basic-tutorial)

View File

@ -0,0 +1,406 @@
# Godot 协程系统
> GFramework 在 Godot 引擎中的协程支持,实现异步操作的优雅管理
## 概述
GFramework.Godot 提供了与 Godot 引擎深度集成的协程系统,让异步编程变得简单直观。通过协程,您可以暂停执行、等待条件满足、或延迟执行操作,而不会阻塞主线程。
## 核心特性
- **无缝集成**:与 Godot 的 `_Process``_Ready` 等生命周期方法完美配合
- **类型安全**:强类型的协程返回结果处理
- **自动清理**:协程与节点生命周期自动绑定,避免内存泄漏
- **丰富的等待条件**:支持等待信号、时间延迟、帧结束等多种条件
## 基本用法
### 创建协程
使用 `StartCoroutine` 方法启动协程:
```csharp
using GFramework.Godot.coroutine;
[ContextAware]
public partial class MyNode : Node
{
public override void _Ready()
{
// 启动协程
this.StartCoroutine(DoSomethingAsync());
}
private System.Collections.IEnumerator DoSomethingAsync()
{
GD.Print("开始执行");
// 等待 2 秒
yield return new WaitForSeconds(2.0f);
GD.Print("2 秒后继续执行");
// 等待下一帧
yield return new WaitForEndOfFrame();
GD.Print("下一帧继续");
}
}
```
### 等待信号
协程可以等待 Godot 信号:
```csharp
private System.Collections.IEnumerator WaitForSignalExample()
{
GD.Print("等待按钮点击");
// 等待按钮被点击
var button = GetNode<Button>("Button");
yield return new WaitSignal(button, Button.SignalName.Pressed);
GD.Print("按钮被点击了!");
}
```
### 等待条件
等待自定义条件满足:
```csharp
private System.Collections.IEnumerator WaitUntilCondition()
{
GD.Print("等待生命值恢复");
// 等待生命值大于 50
var playerModel = Context.GetModel<PlayerModel>();
yield return new WaitUntil(() => playerModel.Health.Value > 50);
GD.Print("生命值已恢复!");
}
```
## 等待类型
### WaitForSeconds
等待指定时间(秒):
```csharp
private System.Collections.IEnumerator DelayExample()
{
GD.Print("开始倒计时");
yield return new WaitForSeconds(1.0f);
GD.Print("1 秒过去了");
yield return new WaitForSeconds(0.5f);
GD.Print("又过去了 0.5 秒");
}
```
### WaitForSecondsRealtime
等待实时时间(不受游戏暂停影响):
```csharp
private System.Collections.IEnumerator RealTimeDelay()
{
// 暂停游戏时也会继续计时
yield return new WaitForSecondsRealtime(5.0f);
GD.Print("5 秒真实时间已过");
}
```
### WaitForEndOfFrame
等待当前帧结束:
```csharp
private System.Collections.IEnumerator EndOfFrameExample()
{
// 修改数据
someData.Value = 100;
// 等待帧结束后再执行渲染相关操作
yield return new WaitForEndOfFrame();
// 现在可以安全地执行渲染操作
UpdateRendering();
}
```
### WaitUntil
等待条件满足:
```csharp
private System.Collections.IEnumerator WaitUntilExample()
{
var health = Context.GetModel<PlayerModel>().Health;
// 持续等待直到条件满足
yield return new WaitUntil(() => health.Value > 0);
GD.Print("玩家复活了!");
}
```
### WaitWhile
等待条件不再满足:
```csharp
private System.Collections.IEnumerator WaitWhileExample()
{
var gameState = Context.GetModel<GameModel>();
// 等待游戏不再暂停
yield return new WaitWhile(() => gameState.IsPaused.Value);
GD.Print("游戏继续");
}
```
## 进阶用法
### 组合等待
可以组合多种等待条件:
```csharp
private System.Collections.IEnumerator CombinedWait()
{
var health = Context.GetModel<PlayerModel>().Health;
var button = GetNode<Button>("Button");
// 等待生命值恢复或按钮点击(任一条件满足即可)
yield return new WaitAny(
new WaitUntil(() => health.Value > 50),
new WaitSignal(button, Button.SignalName.Pressed)
);
GD.Print("条件满足,继续执行");
}
```
### 超时处理
为等待添加超时:
```csharp
private System.Collections.IEnumerator WithTimeout()
{
var task = new WaitForSeconds(5.0f);
var timeout = new WaitForSeconds(5.0f);
// 等待任务完成,最多等 5 秒
bool completed = yield return new WaitRace(task, timeout);
if (completed)
{
GD.Print("任务完成");
}
else
{
GD.Print("任务超时");
}
}
```
### 协程取消
支持取消正在执行的协程:
```csharp
private CoroutineHandle _coroutine;
public override void _Ready()
{
_coroutine = this.StartCoroutine(LongRunningTask());
}
public void CancelTask()
{
_coroutine?.Cancel();
}
private System.Collections.IEnumerator LongRunningTask()
{
try
{
for (int i = 0; i < 100; i++)
{
GD.Print($"进度: {i}%");
yield return new WaitForSeconds(0.1f);
}
}
catch (CoroutineCancelledException)
{
GD.Print("协程被取消");
throw;
}
}
```
## 最佳实践
### 1. 自动生命周期管理
使用 `[ContextAware]` 特性确保协程在节点离开场景树时自动取消:
```csharp
[ContextAware]
public partial class MyController : Node
{
public override void _Ready()
{
// 当节点离开场景树时,协程会自动取消
this.StartCoroutine(AutoCleanupCoroutine());
}
}
```
### 2. 避免在协程中直接修改 UI
```csharp
// 不推荐:直接在协程中频繁更新 UI
private System.Collections.IEnumerator BadExample()
{
for (int i = 0; i < 100; i++)
{
label.Text = $"进度: {i}"; // 可能导致性能问题
yield return new WaitForEndOfFrame();
}
}
// 推荐:使用 BindableProperty 自动更新
private System.Collections.IEnumerator GoodExample()
{
var progress = new BindableProperty<int>(0);
// 使用 BindableProperty 注册 UI 更新
progress.Register(value => label.Text = $"进度: {value}")
.UnRegisterWhenNodeExitTree(this);
for (int i = 0; i < 100; i++)
{
progress.Value = i; // 自动更新 UI
yield return new WaitForEndOfFrame();
}
}
```
### 3. 使用协程进行资源加载
```csharp
private System.Collections.IEnumerator LoadResourcesAsync()
{
GD.Print("开始加载资源");
// 显示加载界面
loadingScreen.Visible = true;
// 异步加载资源
var textures = new List<Texture2D>();
foreach (var path in resourcePaths)
{
var texture = ResourceLoader.LoadThreadedGet<Texture2D>(path);
// 等待每张图片加载完成
yield return new WaitUntil(() => texture.GetLoadingStatus() == ResourceLoader.Loaded);
textures.Add(texture);
// 更新加载进度
UpdateProgress(textures.Count, resourcePaths.Length);
}
// 加载完成
loadingScreen.Visible = false;
OnResourcesLoaded(textures);
}
```
### 4. 场景切换处理
```csharp
private System.Collections.IEnumerator SceneTransitionAsync()
{
GD.Print("开始场景切换");
// 淡出当前场景
fadeAnimation.Play("FadeOut");
yield return new WaitSignal(fadeAnimation, AnimationPlayer.SignalName.AnimationFinished);
// 卸载当前场景
GetTree().CurrentScene.QueueFree();
// 加载新场景
var nextScene = ResourceLoader.Load<PackedScene>("res://scenes/NextScene.tscn");
var instance = nextScene.Instantiate();
GetTree().Root.AddChild(instance);
// 淡入新场景
fadeAnimation.Play("FadeIn");
yield return new WaitSignal(fadeAnimation, AnimationPlayer.SignalName.AnimationFinished);
GD.Print("场景切换完成");
}
```
## 与 Source Generators 集成
GFramework.SourceGenerators 可以自动为您的节点生成协程相关代码:
```csharp
[Log]
[ContextAware]
public partial class MyNode : Node
{
// Source Generator 会自动生成 Logger 字段
// 无需手动编写日志代码
public override void _Ready()
{
Logger.Info("节点已准备就绪");
this.StartCoroutine(ComplexAsyncOperation());
}
private System.Collections.IEnumerator ComplexAsyncOperation()
{
Logger.Debug("开始复杂异步操作");
yield return new WaitForSeconds(1.0f);
Logger.Debug("操作完成");
}
}
```
## 常见问题
### Q: 协程会在游戏暂停时继续执行吗?
A: 默认情况下,`WaitForSeconds` 会受到游戏暂停的影响。如果您需要在暂停时继续计时,请使用 `WaitForSecondsRealtime`
### Q: 如何调试协程?
A: 您可以在协程内部使用 `GD.Print()``Logger.Debug()` 来输出调试信息。VS Code 和 Rider 也支持在协程中设置断点。
### Q: 协程中出现异常会怎样?
A: 未捕获的异常会导致协程停止执行,并可能传播到调用方。建议使用 try-catch 包装可能抛出异常的代码。
---
**相关文档**
- [Godot 概述](./overview)
- [Node 扩展方法](./extensions)
- [信号系统](./signal)
- [事件系统](../core/events)

View File

@ -16,9 +16,6 @@ hero:
- theme: alt
text: 架构概览
link: /getting-started/architecture-overview
- theme: alt
text: API 参考
link: /api-reference/core-api
features:
- title: 🏗️ 清洁架构

View File

@ -0,0 +1,174 @@
# 枚举扩展生成器
> GFramework.SourceGenerators 自动生成枚举扩展方法
## 概述
枚举扩展生成器为枚举类型自动生成常用的扩展方法,如获取描述、转换为字符串、解析等。这大大简化了枚举的操作。
## 基本用法
### 标记枚举
```csharp
using GFramework.SourceGenerators.Attributes;
[EnumExtensions]
public enum PlayerState
{
Idle,
Running,
Jumping,
Attacking
}
```
### 生成的方法
上面的代码会被转换为:
```csharp
public static class PlayerStateExtensions
{
public static string GetDescription(this PlayerState value)
{
// 返回枚举的描述
}
public static bool HasFlag(this PlayerState value, PlayerState flag)
{
// 检查是否包含标志
}
public static PlayerState FromString(string value)
{
// 从字符串解析枚举
}
}
```
## 常用方法
### 获取描述
```csharp
[EnumExtensions]
public enum ItemQuality
{
[Description("普通")]
Common,
[Description("稀有")]
Rare,
[Description("史诗")]
Epic
}
public void PrintQuality(ItemQuality quality)
{
// 获取描述文本
Console.WriteLine(quality.GetDescription());
// 输出: "普通" / "稀有" / "史诗"
}
```
### 安全解析
```csharp
public void ParseState(string input)
{
// 安全地解析字符串为枚举
if (PlayerState.Running.TryParse(input, out var state))
{
Console.WriteLine($"状态: {state}");
}
}
```
### 获取所有值
```csharp
public void ListAllStates()
{
// 获取所有枚举值
foreach (var state in PlayerState.GetAllValues())
{
Console.WriteLine(state);
}
}
```
## 标志枚举
对于使用 `[Flags]` 特性的枚举:
```csharp
[EnumExtensions]
[Flags]
public enum PlayerPermissions
{
None = 0,
Read = 1,
Write = 2,
Execute = 4,
All = Read | Write | Execute
}
public void CheckPermissions()
{
var permissions = PlayerPermissions.Read | PlayerPermissions.Write;
// 检查是否包含特定权限
if (permissions.HasFlag(PlayerPermissions.Write))
{
Console.WriteLine("有写入权限");
}
// 获取所有设置的标志
foreach (var flag in permissions.GetFlags())
{
Console.WriteLine($"权限: {flag}");
}
}
```
## 自定义行为
### 忽略某些值
```csharp
[EnumExtensions(IgnoreValues = new[] { ItemQuality.Undefined })]
public enum ItemQuality
{
Undefined,
Common,
Rare,
Epic
}
// GetAllValues() 不会返回 Undefined
```
### 自定义转换
```csharp
[EnumExtensions(CaseSensitive = false)]
public enum Difficulty
{
Easy,
Medium,
Hard
}
// FromString("EASY") 也能正确解析
```
---
**相关文档**
- [Source Generators 概述](./overview)
- [日志生成器](./logging-generator)
- [规则生成器](./rule-generator)
- [API 参考](../api-reference/source-generators-api)

View File

@ -0,0 +1,161 @@
# 日志生成器
> GFramework.SourceGenerators 自动生成日志代码,减少样板代码
## 概述
日志生成器是一个 Source Generator它会自动为标记了 `[Log]` 特性的类生成 Logger 字段和日志方法调用。这消除了手动编写日志代码的需要,让开发者专注于业务逻辑。
## 基本用法
### 标记类
```csharp
using GFramework.SourceGenerators.Attributes;
[Log]
public partial class MyService
{
public void DoSomething()
{
// 自动生成 Logger 字段
// 自动生成日志调用
Logger.Info("执行操作");
}
}
```
### 生成代码
上面的代码会被编译时转换为:
```csharp
public partial class MyService
{
// 自动生成的字段
[CompilerGenerated]
private ILogger _logger;
// 自动生成的属性
[CompilerGenerated]
public ILogger Logger
{
get
{
if (_logger == null)
{
_logger = LoggerFactory.CreateLogger<MyService>();
}
return _logger;
}
}
}
```
## 日志级别
生成的日志方法支持多种级别:
```csharp
[Log]
public partial class MyClass
{
public void Example()
{
// 调试信息
Logger.Debug($"调试信息: {value}");
// 普通信息
Logger.Info("操作成功");
// 警告
Logger.Warning($"警告: {message}");
// 错误
Logger.Error($"错误: {ex.Message}");
// 严重错误
Logger.Critical("系统故障");
}
}
```
## 自定义日志类别
```csharp
[Log(LogCategory.Gameplay)]
public partial class GameplaySystem
{
// 日志会标记为 Gameplay 类别
public void Update()
{
Logger.Info("游戏逻辑更新");
}
}
```
## 与其他模块集成
### 与 Godot 集成
```csharp
[Log]
[ContextAware]
public partial class GodotController : Node
{
public override void _Ready()
{
Logger.Info("控制器已准备就绪");
}
}
```
### 与架构集成
```csharp
[Log]
public partial class MySystem : AbstractSystem
{
protected override void OnInit()
{
Logger.Info("系统初始化");
}
}
```
## 配置选项
### 禁用自动生成
```csharp
// 禁用自动日志调用生成
[Log(AutoLog = false)]
public partial class MyClass
{
// 仍会生成 Logger 字段,但不会自动生成日志调用
public void DoSomething()
{
// 需要手动调用 Logger
Logger.Info("手动日志");
}
}
```
### 自定义字段名称
```csharp
[Log(FieldName = "_customLogger")]
public partial class MyClass
{
// Logger 字段名称为 _customLogger
}
```
---
**相关文档**
- [Source Generators 概述](./overview)
- [枚举扩展生成器](./enum-generator)
- [规则生成器](./rule-generator)
- [API 参考](../api-reference/source-generators-api)

View File

@ -0,0 +1,164 @@
# 规则生成器
> GFramework.SourceGenerators 自动生成规则验证代码
## 概述
规则生成器为实现了规则接口的类型自动生成验证方法。这使得规则定义更加简洁,并确保规则的一致性。
## 基本用法
### 定义规则
```csharp
using GFramework.SourceGenerators.Attributes;
[RuleFor(typeof(Player))]
public class PlayerRule : IRule<Player>
{
public RuleResult Validate(Player player)
{
if (player.Health <= 0)
{
return RuleResult.Invalid("玩家生命值不能为零或负数");
}
if (string.IsNullOrEmpty(player.Name))
{
return RuleResult.Invalid("玩家名称不能为空");
}
return RuleResult.Valid();
}
}
```
### 使用生成的验证器
```csharp
public class PlayerValidator
{
// 自动生成 Validate 方法
public void ValidatePlayer(Player player)
{
var result = PlayerRuleValidator.Validate(player);
if (!result.IsValid)
{
Console.WriteLine($"验证失败: {result.ErrorMessage}");
}
}
}
```
## 组合规则
### 多规则组合
```csharp
[RuleFor(typeof(Player), RuleCombinationType.And)]
public class PlayerHealthRule : IRule<Player>
{
public RuleResult Validate(Player player)
{
if (player.Health <= 0)
return RuleResult.Invalid("生命值必须大于0");
return RuleResult.Valid();
}
}
[RuleFor(typeof(Player), RuleCombinationType.And)]
public class PlayerNameRule : IRule<Player>
{
public RuleResult Validate(Player player)
{
if (string.IsNullOrEmpty(player.Name))
return RuleResult.Invalid("名称不能为空");
return RuleResult.Valid();
}
}
```
### 验证所有规则
```csharp
public void ValidateAll(Player player)
{
var results = PlayerRuleValidator.ValidateAll(player);
foreach (var result in results)
{
if (!result.IsValid)
{
Console.WriteLine(result.ErrorMessage);
}
}
}
```
## 异步规则
```csharp
[RuleFor(typeof(Player), IsAsync = true)]
public class AsyncPlayerRule : IAsyncRule<Player>
{
public async Task<RuleResult> ValidateAsync(Player player)
{
// 异步验证,如检查服务器
var isBanned = await CheckBanStatus(player.Id);
if (isBanned)
{
return RuleResult.Invalid("玩家已被封禁");
}
return RuleResult.Valid();
}
}
```
## 最佳实践
### 1. 单一职责
```csharp
// 推荐:每个规则只验证一个方面
[RuleFor(typeof(Player))]
public class PlayerHealthRule : IRule<Player> { }
[RuleFor(typeof(Player))]
public class PlayerNameRule : IRule<Player> { }
// 避免:在一个规则中验证多个方面
[RuleFor(typeof(Player))]
public class PlayerMegaRule : IRule<Player>
{
public RuleResult Validate(Player player)
{
// 验证健康、名称、等级...
// 不要这样设计
}
}
```
### 2. 清晰的错误信息
```csharp
public RuleResult Validate(Player player)
{
// 推荐:具体的错误信息
return RuleResult.Invalid($"玩家 {player.Name} 的生命值 {player.Health} 不能小于 1");
// 避免:模糊的错误信息
return RuleResult.Invalid("无效的玩家");
}
```
---
**相关文档**
- [Source Generators 概述](./overview)
- [日志生成器](./logging-generator)
- [枚举扩展生成器](./enum-generator)
- [API 参考](../api-reference/source-generators-api)

View File

@ -437,9 +437,9 @@ dotnet test
### 学习资源
- [GFramework 主文档](/)
- [Core 模块文档](/core/overview)
- [Godot 集成文档](/godot/overview)
- [API 参考](/api-reference/core-api)
- [GFramework 主文档](../)
- [Core 模块文档](../core)
- [Godot 集成文档](../godot/overview)
- [API 参考](../api-reference/core-api)
享受游戏开发的乐趣吧!🎮