docs: sync api and planning docs
This commit is contained in:
@@ -4,51 +4,102 @@
|
||||
|
||||
**类型**: `submodule`
|
||||
|
||||
**描述**: 收纳基于 Mono 的托管脚本运行时实现。
|
||||
**描述**: 收纳基于 Mono 的托管脚本运行时实现,以及当前脚本字段发现、默认值读取与运行时桥接的 Mono 后端文档。
|
||||
|
||||
## 概览
|
||||
|
||||
`docs/api/XCEngine/Scripting/Mono` 对应 `engine/include/XCEngine/Scripting/Mono` 子目录。它不是独立命名空间,而是脚本模块按后端实现拆出来的子目录。
|
||||
`docs/api/XCEngine/Scripting/Mono` 对应 `engine/include/XCEngine/Scripting/Mono`。它不是独立命名空间,而是脚本系统按运行时后端拆出的子目录。
|
||||
|
||||
当前这里唯一的公开类型是 [MonoScriptRuntime](MonoScriptRuntime/MonoScriptRuntime.md)。它负责:
|
||||
当前这里的核心公开类型是 [MonoScriptRuntime](MonoScriptRuntime/MonoScriptRuntime.md)。它负责:
|
||||
|
||||
- 初始化 Mono root domain 和 app domain。
|
||||
- 解析 `MonoScriptRuntime::Settings`,推导程序集目录、脚本核心程序集和游戏程序集路径。
|
||||
- 加载 `XCEngine.ScriptCore.dll` 与 `GameScripts.dll`。
|
||||
- 发现应用程序集中的非抽象 `MonoBehaviour` 子类,并缓存支持的公共实例字段与生命周期方法。
|
||||
- 为 `ScriptComponent` 创建托管实例,注入 `GameObject`/`ScriptComponent` 上下文,并在生命周期后同步字段。
|
||||
- 初始化 Mono root domain / app domain
|
||||
- 加载 `XCEngine.ScriptCore.dll` 与 `GameScripts.dll`
|
||||
- 发现应用程序集中的非抽象 `MonoBehaviour` 子类
|
||||
- 构建字段元数据与字段默认值查询能力
|
||||
- 创建脚本实例、注入上下文并调用生命周期
|
||||
- 通过 internal call 把 `Debug`、`Time`、`Input`、`GameObject`、`Transform` 等托管 API 接回原生实现
|
||||
|
||||
## 为什么单独分目录
|
||||
## 字段发现模型
|
||||
|
||||
把 Mono 运行时放进独立子目录,而不是直接塞进 `Scripting` 根目录,有两个直接好处:
|
||||
这一轮最重要的语义更新,是当前 Mono 后端已经不再等同于“只发现 public 实例字段”。
|
||||
|
||||
- 可以清楚区分“脚本系统公共契约”和“具体后端实现”。
|
||||
- 以后如果接入别的脚本后端,这里天然就是平行扩展点。
|
||||
当前真实规则是:
|
||||
|
||||
## 程序集来源
|
||||
- 先排除:
|
||||
- `static`
|
||||
- `const / literal`
|
||||
- `readonly / init-only`
|
||||
- 然后接受:
|
||||
- `public` 实例字段
|
||||
- 或者标了 `[SerializeField]` 的 `private` 实例字段
|
||||
- 最后再按当前支持的字段类型过滤
|
||||
|
||||
当前 Mono 后端既支持测试程序集目录,也支持项目资产脚本程序集目录:
|
||||
这意味着:
|
||||
|
||||
- `managed/CMakeLists.txt` 会构建基础 `XCEngine.ScriptCore.dll` 与 `GameScripts.dll`。
|
||||
- 同一份 CMake 还会把 `project/Assets/**/*.cs` 编译到 `project/Library/ScriptAssemblies/GameScripts.dll`。
|
||||
- `tests/scripting/test_project_script_assembly.cpp` 已验证运行时能从项目程序集目录发现 `ProjectScripts.ProjectScriptProbe` 及其默认字段值。
|
||||
- `FieldMetadataProbe.Health` / `Speed` / `Label` 这类 `public` 字段会被发现
|
||||
- `FieldMetadataProbe.HiddenFlag` 这种 `[SerializeField] private` 字段也会被发现
|
||||
- `IgnoredPrivateCounter` 这类未标注的 `private` 字段仍然会被忽略
|
||||
- `SharedCounter` 这类 `static` 字段会被忽略
|
||||
- `UnsupportedRotation` 这类当前不支持的类型也会被忽略
|
||||
|
||||
## 为什么要支持 `[SerializeField] private`
|
||||
|
||||
这是一个很典型的 Unity 风格设计,但它的价值不只是“和 Unity 看齐”。更重要的是它解决了工程里的两个真实矛盾:
|
||||
|
||||
- 你希望字段能被序列化、能被 Inspector 或场景存储驱动
|
||||
- 但你又不希望把这个字段暴露成脚本类的公开 API
|
||||
|
||||
支持 `[SerializeField] private` 的好处包括:
|
||||
|
||||
- 保留封装边界,不必为了可持久化而把内部状态全部改成 `public`
|
||||
- 更适合后续重构,减少脚本 API 面被外部任意依赖
|
||||
- 和商业引擎用户的认知模型一致,降低脚本作者迁移成本
|
||||
|
||||
而继续忽略“未标注的 private 字段”,则能防止把纯运行时内部状态意外持久化。
|
||||
|
||||
## 为什么要排除 `readonly`
|
||||
|
||||
当前字段同步模型要求:
|
||||
|
||||
- 运行前可以把 `ScriptFieldStorage` 里的覆盖值写回托管实例
|
||||
- 运行后可以把托管实例里的值同步回本地存储
|
||||
|
||||
`readonly` 字段不适合承担这类双向同步职责,因此当前实现把 `init-only` 直接排除。这是一个偏工程安全的取舍。
|
||||
|
||||
## 程序集事实来源
|
||||
|
||||
当前 Mono 后端的类发现和字段发现,依赖的是“编译后的程序集事实”,而不是直接扫描 `.cs` 源文件目录:
|
||||
|
||||
- `XCEngine.ScriptCore.dll` 提供托管基类和属性
|
||||
- `GameScripts.dll` 提供应用层脚本类
|
||||
|
||||
这和商业引擎常见的做法一致:Inspector 列表、字段元数据、默认值读取和真正实例化,都应该基于同一份已编译产物。
|
||||
|
||||
## 测试锚点
|
||||
|
||||
当前行为直接受到以下测试约束:
|
||||
|
||||
- `ClassFieldMetadataListsSupportedPublicInstanceFields`
|
||||
- `ClassFieldDefaultValueQueryReturnsSerializeFieldPrivateInitializers`
|
||||
- `SerializeFieldPrivateFieldsApplyStoredValuesAndPersistAcrossSceneRoundTrip`
|
||||
- `test_project_script_assembly.cpp` 里的项目程序集发现与默认值读取用例
|
||||
|
||||
## 当前实现边界
|
||||
|
||||
- 当前只实现了 Mono 后端,没有并列的 IL2CPP、Lua 或自研 VM 后端。
|
||||
- 目录里只有一个 public header,说明当前重点仍然是把一条 Mono 托管链路跑通。
|
||||
- 类发现只扫描当前应用程序集里的非抽象 `MonoBehaviour` 子类,不会把工具类或抽象基类暴露给脚本绑定 UI。
|
||||
- 字段发现只接受受支持类型的 `public` 非 `static` 实例字段。
|
||||
- internal call 目前已覆盖 `GameObject`、`Transform`、`Camera`、`Light`、`MeshFilter`、`MeshRenderer`、日志和时间桥接,但远不是完整编辑器级脚本 API 面。
|
||||
- 当前只有 Mono 后端,没有并列的 IL2CPP / Lua / 自研 VM 后端。
|
||||
- 字段发现只扫描应用程序集里的非抽象 `MonoBehaviour` 子类。
|
||||
- `[SerializeField] private` 已支持,但“未标注 private”“`readonly`”“不支持类型”仍然不会进入字段模型。
|
||||
- 项目脚本能否被发现,取决于它是否成功进入 `GameScripts.dll`,而不是取决于源文件是否存在于目录里。
|
||||
|
||||
## 头文件
|
||||
|
||||
- [MonoScriptRuntime](MonoScriptRuntime/MonoScriptRuntime.md) - `MonoScriptRuntime.h`
|
||||
- [MonoScriptRuntime](MonoScriptRuntime/MonoScriptRuntime.md)
|
||||
|
||||
## 相关指南
|
||||
|
||||
- [Scripting Runtime And Field Model](../../../_guides/Scripting/Scripting-Runtime-And-Field-Model.md)
|
||||
- [Project Script Assembly And Field Sync](../../../_guides/Scripting/Project-Script-Assembly-And-Field-Sync.md)
|
||||
- [Game View Runtime Input Bridge](../../../_guides/Editor/Game-View-Runtime-Input-Bridge.md)
|
||||
|
||||
## 相关文档
|
||||
|
||||
|
||||
Reference in New Issue
Block a user