Files
XCEngine/docs/api/XCEngine/Scripting/Mono/MonoScriptRuntime/DestroyManagedObject.md

95 lines
2.6 KiB
Markdown
Raw Normal View History

2026-04-03 15:48:09 +08:00
# MonoScriptRuntime::DestroyManagedObject
**命名空间**: `XCEngine::Scripting`
**类型**: `method`
**头文件**: `XCEngine/Scripting/Mono/MonoScriptRuntime.h`
## 签名
```cpp
bool DestroyManagedObject(MonoObject* managedObject);
```
## 作用
根据传入的托管包装对象,销毁它在原生运行时中对应的 `GameObject` 或组件。
## 当前实现行为
- 只有在运行时已初始化,且 `managedObject` 非空时才会继续。
- 函数会先切回当前 Mono app domain再读取对象的实际 `MonoClass`
### 当对象是 `GameObject` 包装对象时
- 读取 `managedGameObjectUUID`
- 必须能在当前 internal-call 活动场景里找到对应 `GameObject`
- 且该对象确实属于当前活动场景
- 满足条件后调用 `scene->DestroyGameObject(gameObject)`
### 当对象是组件包装对象时
- 必须是 `Component` 本体或其子类
- 先读取 `gameObjectUUID`
- 若它是脚本行为包装对象,还会继续读取 `scriptComponentUUID`
- 能精确定位到原生脚本组件时,会调用内部 `DestroyNativeComponentInstance(...)`
对于内建原生组件包装对象,当前支持:
- `Camera`
- `Light`
- `MeshFilter`
- `MeshRenderer`
以下类型当前不会被销毁:
- `Transform`
- 无法识别的组件类型
- 无法定位到有效原生对象的包装对象
## 组件销毁语义
当前底层 `DestroyNativeComponentInstance(...)` 会:
1. 拒绝销毁空组件和 `Transform`
2. 若组件当前启用,且宿主对象在层级中处于激活状态,则先调用 `OnDisable()`
3. 调用 `OnDestroy()`
4. 最后执行 `gameObject->RemoveComponent(component)`
这说明当前实现不是简单地把组件从数组里抹掉,而是尽量保持接近引擎生命周期语义的销毁顺序。
## 与托管侧 API 的关系
当前 `Object.Destroy(...)` 的 internal call 最终会走到这个方法:
```text
InternalCall_Object_Destroy
-> MonoScriptRuntime::DestroyManagedObject
```
因此它是托管脚本“请求销毁原生对象”的核心落点之一。
## 测试锚点
`tests/scripting/test_mono_script_runtime.cpp` 中的
- `UnityObjectApiSupportsHierarchyLookupAndDestroy`
直接覆盖了当前层级查询与销毁语义,包括:
- 子对象与父对象查询
- 组件查询
- 销毁后对象与组件是否真的从场景中消失
## 返回值
- 成功定位并销毁原生对象或组件时返回 `true`
- 其余情况返回 `false`
## 相关文档
- [MonoScriptRuntime](MonoScriptRuntime.md)
- [CreateManagedComponentWrapper](CreateManagedComponentWrapper.md)
- [DestroyScriptInstance](DestroyScriptInstance.md)