2026-03-28 15:10:54 +08:00
|
|
|
|
# Scripting
|
|
|
|
|
|
|
|
|
|
|
|
**命名空间**: `XCEngine::Scripting`
|
|
|
|
|
|
|
|
|
|
|
|
**类型**: `module`
|
|
|
|
|
|
|
2026-04-02 22:23:29 +08:00
|
|
|
|
**描述**: 提供脚本组件数据模型、字段覆盖存储、运行时调度器以及可替换的托管脚本后端抽象。
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
|
|
|
|
|
## 概览
|
|
|
|
|
|
|
2026-04-02 22:23:29 +08:00
|
|
|
|
当前脚本模块已经形成一条比较明确的“数据层 -> 调度层 -> 后端层”链路:
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
2026-04-02 22:23:29 +08:00
|
|
|
|
1. [ScriptComponent](ScriptComponent/ScriptComponent.md) 挂在 `GameObject` 上,保存程序集名、命名空间、类名、组件 UUID 和 [ScriptFieldStorage](ScriptFieldStorage/ScriptFieldStorage.md)。
|
|
|
|
|
|
2. [ScriptEngine](ScriptEngine/ScriptEngine.md) 在运行时收集场景内所有脚本组件,按 `(gameObjectUUID, scriptComponentUUID)` 跟踪实例状态,并统一驱动生命周期。
|
|
|
|
|
|
3. [IScriptRuntime](IScriptRuntime/IScriptRuntime.md) 定义“类发现、字段元数据、默认值读取、实例创建、生命周期调用、字段同步”的统一契约。
|
|
|
|
|
|
4. [NullScriptRuntime](NullScriptRuntime/NullScriptRuntime.md) 负责在没有真实托管后端时兜底,让脚本数据层和编辑流程仍然可工作。
|
|
|
|
|
|
5. [Mono](Mono/Mono.md) 子目录中的 [MonoScriptRuntime](Mono/MonoScriptRuntime/MonoScriptRuntime.md) 是当前唯一的真实托管后端,负责加载 `XCEngine.ScriptCore.dll` 与 `GameScripts.dll`、发现脚本类、创建托管实例并完成字段桥接。
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
2026-04-02 22:23:29 +08:00
|
|
|
|
如果从引擎分层角度理解:
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
2026-04-02 22:23:29 +08:00
|
|
|
|
- `ScriptComponent + ScriptFieldStorage` 是可序列化的数据层。
|
|
|
|
|
|
- `ScriptEngine` 是场景运行时的调度层。
|
|
|
|
|
|
- `IScriptRuntime`/`MonoScriptRuntime` 是托管执行后端。
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
|
|
|
|
|
## 设计要点
|
|
|
|
|
|
|
2026-04-02 22:23:29 +08:00
|
|
|
|
- 场景序列化只依赖 `ScriptComponent` 和 `ScriptFieldStorage`,不依赖 Mono 是否已经初始化。
|
|
|
|
|
|
- 字段模型分成“类声明默认值、存储覆盖值、活体托管值”三层,便于 Inspector 和调试工具说明字段来源。
|
|
|
|
|
|
- `ScriptEngine` 把生命周期顺序、运行中生成对象追踪、类切换重建都集中在一处。
|
|
|
|
|
|
- `IScriptRuntime` 让主流程只依赖契约,后续可以接别的托管后端,而不是把 Mono API 直接扩散到引擎各处。
|
|
|
|
|
|
|
|
|
|
|
|
## 当前运行链路
|
|
|
|
|
|
|
|
|
|
|
|
1. `SceneRuntime` 启动场景时调用 `ScriptEngine::OnRuntimeStart(scene)`。
|
|
|
|
|
|
2. `ScriptEngine` 先通知当前运行时启动,再递归收集场景里现有的 `ScriptComponent`,同时订阅 `Scene::OnGameObjectCreated()` 以追踪运行中创建的新对象。
|
|
|
|
|
|
3. 对满足运行条件的组件,运行时创建托管实例;`MonoScriptRuntime` 会先把 `ScriptFieldStorage` 中同名且类型匹配的字段写入实例。
|
|
|
|
|
|
4. `ScriptEngine` 统一按 `Awake -> OnEnable -> Start -> FixedUpdate/Update/LateUpdate` 驱动生命周期。
|
|
|
|
|
|
5. 每次生命周期调用后,运行时执行 `SyncManagedFieldsToStorage()`;当前 Mono 实现只会回写“本地已存在且类型仍匹配”的字段。
|
|
|
|
|
|
6. 编辑器或调试工具可通过 `ScriptEngine::TryGetScriptFieldModel()` / `TryGetScriptFieldSnapshots()` 看到字段默认值、覆盖值、活体值以及 `StoredOnly` / `TypeMismatch` 等诊断状态。
|
|
|
|
|
|
|
|
|
|
|
|
## 项目程序集来源
|
|
|
|
|
|
|
|
|
|
|
|
当 `XCENGINE_ENABLE_MONO_SCRIPTING` 打开时,`managed/CMakeLists.txt` 会构建两类程序集:
|
|
|
|
|
|
|
|
|
|
|
|
- 引擎脚本核心程序集:`XCEngine.ScriptCore.dll`
|
|
|
|
|
|
- 游戏脚本程序集:`GameScripts.dll`
|
|
|
|
|
|
|
|
|
|
|
|
除了测试用的 `build/managed` 输出,CMake 还会把项目 `project/Assets/**/*.cs` 编译到 `project/Library/ScriptAssemblies/GameScripts.dll`。`MonoScriptRuntime::Settings` 可以直接指向该目录,因此项目资产脚本和默认字段值已经进入当前文档的真实行为范围。
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
|
|
|
|
|
## 当前实现边界
|
|
|
|
|
|
|
|
|
|
|
|
- 当前公开支持的脚本字段类型是有限集合:标量、字符串、`Vector2/3/4` 和 `GameObject` 引用。
|
|
|
|
|
|
- 生命周期覆盖 `Awake / OnEnable / Start / FixedUpdate / Update / LateUpdate / OnDisable / OnDestroy`。
|
2026-04-02 22:23:29 +08:00
|
|
|
|
- `NullScriptRuntime` 只是桥接占位,不会真正执行脚本代码,也不会返回脚本类列表或字段默认值。
|
|
|
|
|
|
- `MonoScriptRuntime` 目前只发现应用程序集中的非抽象 `MonoBehaviour` 子类,不做热重载、域增量刷新或完整编辑器脚本生态。
|
|
|
|
|
|
- 字段同步目前不会自动把“运行中新增但本地没有声明”的字段持久化下来。
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
|
|
|
|
|
## 头文件
|
|
|
|
|
|
|
|
|
|
|
|
- [IScriptRuntime](IScriptRuntime/IScriptRuntime.md) - `IScriptRuntime.h`
|
|
|
|
|
|
- [NullScriptRuntime](NullScriptRuntime/NullScriptRuntime.md) - `NullScriptRuntime.h`
|
|
|
|
|
|
- [ScriptComponent](ScriptComponent/ScriptComponent.md) - `ScriptComponent.h`
|
|
|
|
|
|
- [ScriptEngine](ScriptEngine/ScriptEngine.md) - `ScriptEngine.h`
|
|
|
|
|
|
- [ScriptField](ScriptField/ScriptField.md) - `ScriptField.h`
|
|
|
|
|
|
- [ScriptFieldStorage](ScriptFieldStorage/ScriptFieldStorage.md) - `ScriptFieldStorage.h`
|
|
|
|
|
|
- [Mono](Mono/Mono.md) - `Mono/`
|
|
|
|
|
|
|
|
|
|
|
|
## 相关指南
|
|
|
|
|
|
|
|
|
|
|
|
- [Scripting Runtime And Field Model](../../_guides/Scripting/Scripting-Runtime-And-Field-Model.md) - 解释当前脚本系统如何把场景、脚本字段缓存和 Mono 运行时衔接起来,以及为什么这样设计。
|
2026-04-02 22:23:29 +08:00
|
|
|
|
- [Project Script Assembly And Field Sync](../../_guides/Scripting/Project-Script-Assembly-And-Field-Sync.md) - 解释 `project/Assets/**/*.cs` 如何进入 `GameScripts.dll`,以及默认值、存储覆盖和活体字段如何相互覆盖。
|
2026-03-28 15:10:54 +08:00
|
|
|
|
|
|
|
|
|
|
## 相关文档
|
|
|
|
|
|
|
|
|
|
|
|
- [SceneRuntime](../Scene/SceneRuntime/SceneRuntime.md)
|
|
|
|
|
|
- [Scene](../Scene/Scene.md)
|
|
|
|
|
|
- [上级目录](../XCEngine.md)
|
|
|
|
|
|
- [API 总索引](../../main.md)
|