# Mono **命名空间**: `XCEngine::Scripting` **类型**: `submodule` **描述**: 收纳基于 Mono 的托管脚本运行时实现,以及当前脚本字段发现、默认值读取与运行时桥接的 Mono 后端文档。 ## 概览 `docs/api/XCEngine/Scripting/Mono` 对应 `engine/include/XCEngine/Scripting/Mono`。它不是独立命名空间,而是脚本系统按运行时后端拆出的子目录。 当前这里的核心公开类型是 [MonoScriptRuntime](MonoScriptRuntime/MonoScriptRuntime.md)。它负责: - 初始化 Mono root domain / app domain - 加载 `XCEngine.ScriptCore.dll` 与 `GameScripts.dll` - 发现应用程序集中的非抽象 `MonoBehaviour` 子类 - 构建字段元数据与字段默认值查询能力 - 创建脚本实例、注入上下文并调用生命周期 - 通过 internal call 把 `Debug`、`Time`、`Input`、`GameObject`、`Transform` 等托管 API 接回原生实现 ## 字段发现模型 这一轮最重要的语义更新,是当前 Mono 后端已经不再等同于“只发现 public 实例字段”。 当前真实规则是: - 先排除: - `static` - `const / literal` - `readonly / init-only` - 然后接受: - `public` 实例字段 - 或者标了 `[SerializeField]` 的 `private` 实例字段 - 最后再按当前支持的字段类型过滤 这意味着: - `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 后端。 - 字段发现只扫描应用程序集里的非抽象 `MonoBehaviour` 子类。 - `[SerializeField] private` 已支持,但“未标注 private”“`readonly`”“不支持类型”仍然不会进入字段模型。 - 项目脚本能否被发现,取决于它是否成功进入 `GameScripts.dll`,而不是取决于源文件是否存在于目录里。 ## 头文件 - [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) ## 相关文档 - [Scripting](../Scripting.md) - [IScriptRuntime](../IScriptRuntime/IScriptRuntime.md)