Files
Workspace/Godot/README.md
T

202 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ShrinkSDK for Godot 4.7 C#
Godot 适配层使用共享 ShrinkSDK 运行时和 MSBuild/Cecil CodeGen。桌面基线为 Godot 4.7.2 Mono / .NET 8。Android 消费工程使用 .NET 9,并由工程提供对应平台的运行与导出验证;Web 和 iOS 不在本次支持范围。
## 直接运行 Workspace 示例
使用 Godot 4.7.2 Mono 打开:
```text
Godot/Samples/ShrinkSDK.Godot.Sample/project.godot
```
首次打开前可以先完成导入和编译:
```powershell
$godot = Join-Path $env:GODOT_HOME "godot_console.exe"
& $godot --headless --editor --path .\Godot\Samples\ShrinkSDK.Godot.Sample --quit
dotnet build .\Godot\Samples\ShrinkSDK.Godot.Sample\ShrinkSDK.Godot.Sample.csproj
& $godot --headless --path .\Godot\Samples\ShrinkSDK.Godot.Sample
```
`GODOT_HOME` 指向 Godot Mono 安装目录。成功运行时会输出 `SHRINK_GODOT_SMOKE_PASS`。
## 在现有 Godot C# 项目中安装
项目需要:
- Godot 4.7.2 Mono;
- .NET 8 SDK;
- `.csproj` 使用 `Godot.NET.Sdk/4.7.2`;
- 项目级 `NuGet.Config` 保留既有源并加入 ShrinkSDK feed。
`NuGet.Config` 的最小增量如下:
```xml
<configuration>
<packageSources>
<add key="ShrinkSDK" value="https://git.crash.work/api/packages/ShrinkSDK/nuget/index.json" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>
```
安装 Godot 宿主和所需模块:
```powershell
dotnet add package ShrinkSDK.Godot --version 0.2.1
dotnet add package ShrinkSDK.EntJoy.Godot --version 0.1.1
dotnet add package ShrinkSDK.EventBus --version 2.3.1
dotnet add package ShrinkSDK.Command --version 0.4.3
dotnet add package ShrinkSDK.Network --version 0.4.3
dotnet add package ShrinkSDK.DataSaver --version 2.5.0
dotnet restore
dotnet build
```
只有实际使用的模块需要安装。版本以 ShrinkSDK NuGet 源中的已发布版本为准,并保留命令中的固定版本号,不要改用浮动版本。
### EventBus 调试器(可选)
`ShrinkSDK.EventBus.Godot 0.1.1` 提供 Godot 编辑器中的事件订阅与分发调试窗口。安装 NuGet 包后,将包内 `contentFiles/any/any/addons/shrink_event_bus` 复制到项目的 `addons/shrink_event_bus`,再在 `Project > Project Settings > Plugins` 启用 **ShrinkEventBus**。它依赖公开的 `EventBus.ObserveDiagnostics`,订阅快照列出静态 `EventBus` 管理的 Bus,分发记录也可观察独立 Host;Release 构建不包含采集实现。
主线程 Bus 可以使用显式延后发布:
```csharp
var result = EventBus.PostDeferred(bus, new PlayerReadyEvent());
if (!result.Accepted)
GD.PushWarning($"deferred post rejected: {result.Failure}");
```
延后事件在下一次宿主主线程泵送时执行。`Inline`、`DedicatedThread`、`TaskPool` 或没有 `IShrinkDeferredMainThreadDispatcher` 的宿主会返回 `DeferredUnsupported`,不会静默改成同步分发。
### EntJoy ECS(可选)
`ShrinkSDK.EntJoy.Godot` 将 EntJoy 的 headless ECS/JobSystem 接入 Godot 节点生命周期。主场景根节点改为继承 `ShrinkEntJoyHost` 后,可从 `EntJoyWorld` 使用 `EntityManager`、`QueryBuilder` 和 EntJoy Job API;宿主会在 `_Ready` 初始化共享 JobSystem,在每帧 `_Process` 交换事件缓冲并提交待处理 Job,在 `_ExitTree` 释放 World。详见 [Godot/Packages/ShrinkSDK.EntJoy.Godot/README.md](Packages/ShrinkSDK.EntJoy.Godot/README.md)。
## Installer 插件
`ShrinkSDK.Godot.Installer` 的 nupkg 内包含完整的 `addons/shrinksdk`。取得 `0.2.0` 包后,将包内:
```text
contentFiles/any/any/addons/shrinksdk
```
复制到 Godot 项目的:
```text
addons/shrinksdk
```
然后在 Godot 中打开 `Project > Project Settings > Plugins`,启用 **ShrinkSDK Installer**。左侧 ShrinkSDK 面板可以:
- 查看项目直接安装的 ShrinkSDK NuGet 包及版本;
- 安装、升级或移除模块;
- 保留项目已有 NuGet 源和无关 `PackageReference`;
- 执行 `dotnet restore/build`;
- 查看 CodeGen 最后一次织入结果和生成的注册数量。
已安装版本高于面板目录版本时会显示 `Newer` 并禁用更新按钮,不会执行降级。
在 Workspace 中生成 Installer 包:
```powershell
dotnet build .\Assets\Modules\ShrinkInstaller\Godot~\ShrinkSDK.Godot.Installer.csproj -c Release
dotnet pack .\Assets\Modules\ShrinkInstaller\Godot~\ShrinkSDK.Godot.Installer.csproj -c Release --no-build -o .\Godot\Artifacts
```
## 宿主节点
主场景根节点继承 `ShrinkGodotHost`,并在 `_Ready` 中先调用 `base._Ready()`:
```csharp
using Cysharp.Threading.Tasks;
using ShrinkSDK.Godot;
public partial class GameRoot : ShrinkGodotHost
{
public override void _Ready()
{
base._Ready();
BootAsync().Forget();
}
private async UniTaskVoid BootAsync()
{
RequireWoven(GetType().Assembly);
await StartAppAsync();
}
}
```
宿主负责日志、主线程派发、时间、`user://` 持久化路径、截图、应用生命周期和网络 dispatch queue。`Runtime` 属性暴露可组合的 `ShrinkGodotRuntime`,供不直接继承宿主节点的入口复用。使用 `ShrinkNetworkService` 时,通过 `AddNetworkService(service)` 交给宿主逐帧泵送,释放前调用 `RemoveNetworkService(service)`。
`ShutdownAppAsync()` 只停止 App,保留运行时继续泵送派发和网络队列;`ShutdownAsync()` 会先停止 App,再关闭整个运行时。退出流程需要等待 App 的 inverse effect 完成时使用后者。
## 组合式宿主
Godot 4.7.2 项目优先让常驻入口继承 `Node`,持有一个 `ShrinkGodotRuntime`:在 `_Ready` 中 `Initialize(this)`,在 `_Process(delta)` 中 `Tick(delta)`,在 `_Notification(what)` 中 `Notify(what)`。入口设置 `ProcessMode = ProcessModeEnum.Always`,暂停时继续处理基础服务。
启动前必须初始化;退出时先保存业务状态并关闭服务组合,再等待 `ShutdownAsync()`,最后调用 `SceneTree.Quit()`。正常退出由项目显式协调,强制终止不保证清理。网络注册与逐帧驱动在所有者线程调用,后台任务可以使用 `TryPost` / `TryPostDeferred`。
受限沙箱中的设置存储可使用 `ShrinkGodotStorage.CreateRenameOnly(rootPath)`,通过 `ShrinkDataSaverAppModuleConfig.RuntimeConfig.Storage` 注入,并调用 `ShrinkBasicComposition.CreateEntries(services, network: null, dataSaver: config)`。轮转中断从备份恢复,孤立临时文件不会自动成为正式文件。
运行 `WorldDemo.tscn` 可验证两个实际世界节点的候选恢复、失败保留原世界、提交替换与订阅释放,以及暂停派发和正常退出。成功标记为 `SHRINK_GODOT_WORLD_PASS`。
## CodeGen 织入
EventBus、Command、Network 和 App 的特性注册由 `ShrinkSDK.CodeGen` 在构建时生成。项目正常引用这些模块后,`buildTransitive` 会默认设置:
```xml
<ShrinkCodeGenEnabled>true</ShrinkCodeGenEnabled>
```
执行:
```powershell
dotnet build
```
日志应出现类似:
```text
[ShrinkSDK.CodeGen] ... woven: instance=1, static=1, registry=2
```
运行时可以在启动阶段验证程序集:
```csharp
ShrinkGodotHost.RequireWoven(GetType().Assembly);
```
缺少织入时应修复 NuGet 引用或构建配置,不要增加运行时反射扫描兜底。只有明确采用手工注册的普通 .NET 宿主才设置 `<ShrinkCodeGenEnabled>false</ShrinkCodeGenEnabled>`。
## 特性声明示例
```csharp
using ShrinkCommand;
using ShrinkEventBus;
using ShrinkNetwork;
public readonly struct PlayerReadyEvent : IShrinkEvent { }
[ShrinkEventSubscriber]
public sealed class PlayerReadySubscriber
{
[ShrinkSubscribe]
private void OnPlayerReady(PlayerReadyEvent value) { }
}
[ShrinkCommandSubscriber]
public static class GameCommands
{
[ShrinkCommand("game/status")]
public static void Status() { }
}
[ShrinkNetworkMessage(41001, "game/player-ready")]
public sealed class PlayerReadyMessage : IShrinkNetworkMessage { }
```
实例订阅者使用 `EventBus.Attach(instance)` 绑定;静态订阅、Command、Network 和 App registry 由织入代码自动注册。