feat(scripting): add runtime gameobject lifecycle api

This commit is contained in:
2026-03-27 16:30:16 +08:00
parent 26035e3940
commit a72f9f7f05
10 changed files with 395 additions and 0 deletions

View File

@@ -72,6 +72,7 @@ set(XCENGINE_SCRIPT_CORE_SOURCES
set(XCENGINE_GAME_SCRIPT_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/BuiltinComponentProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/AddComponentProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/RuntimeGameObjectProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/HierarchyProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/LifecycleProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/MeshComponentProbe.cs

View File

@@ -0,0 +1,98 @@
using XCEngine;
namespace Gameplay
{
public sealed class RuntimeGameObjectProbe : MonoBehaviour
{
public bool MissingBeforeCreate;
public bool CreatedRootSucceeded;
public bool CreatedChildSucceeded;
public bool FoundRootSucceeded;
public bool FoundChildSucceeded;
public string ObservedFoundRootName = string.Empty;
public string ObservedFoundChildParentName = string.Empty;
public int ObservedRootChildCountBeforeDestroy;
public bool CameraLookupSucceeded;
public bool MeshFilterLookupSucceeded;
public bool MeshRendererLookupSucceeded;
public float ObservedCameraFieldOfView;
public string ObservedMeshPath = string.Empty;
public int ObservedMaterialCount;
public string ObservedMaterial0Path = string.Empty;
public int ObservedRenderLayer;
public bool MissingChildAfterDestroy;
public bool FoundRootAfterDestroySucceeded;
public int ObservedRootChildCountAfterDestroy = -1;
public void Start()
{
MissingBeforeCreate = GameObject.Find("RuntimeCreatedRoot") == null;
GameObject root = GameObject.Create("RuntimeCreatedRoot");
GameObject child = GameObject.Create("RuntimeCreatedChild", root);
CreatedRootSucceeded = root != null;
CreatedChildSucceeded = child != null;
GameObject foundRoot = GameObject.Find("RuntimeCreatedRoot");
GameObject foundChild = GameObject.Find("RuntimeCreatedChild");
FoundRootSucceeded = foundRoot != null;
FoundChildSucceeded = foundChild != null;
if (foundRoot != null)
{
ObservedFoundRootName = foundRoot.name;
ObservedRootChildCountBeforeDestroy = foundRoot.transform.childCount;
Camera camera = foundRoot.AddComponent<Camera>();
MeshFilter meshFilter = foundRoot.AddComponent<MeshFilter>();
MeshRenderer meshRenderer = foundRoot.AddComponent<MeshRenderer>();
CameraLookupSucceeded = camera != null;
MeshFilterLookupSucceeded = meshFilter != null;
MeshRendererLookupSucceeded = meshRenderer != null;
if (camera != null)
{
camera.fieldOfView = 68.0f;
ObservedCameraFieldOfView = camera.fieldOfView;
}
if (meshFilter != null)
{
meshFilter.meshPath = "Meshes/runtime_created.mesh";
ObservedMeshPath = meshFilter.meshPath;
}
if (meshRenderer != null)
{
meshRenderer.SetMaterialPath(0, "Materials/runtime_created.mat");
meshRenderer.renderLayer = 4;
ObservedMaterialCount = meshRenderer.materialCount;
ObservedMaterial0Path = meshRenderer.GetMaterialPath(0);
ObservedRenderLayer = meshRenderer.renderLayer;
}
}
if (foundChild != null && foundChild.transform.parent != null)
{
ObservedFoundChildParentName = foundChild.transform.parent.gameObject.name;
}
if (child != null)
{
child.Destroy();
}
MissingChildAfterDestroy = GameObject.Find("RuntimeCreatedChild") == null;
GameObject foundRootAfterDestroy = GameObject.Find("RuntimeCreatedRoot");
FoundRootAfterDestroySucceeded = foundRootAfterDestroy != null;
if (foundRootAfterDestroy != null)
{
ObservedRootChildCountAfterDestroy = foundRootAfterDestroy.transform.childCount;
}
}
}
}

View File

@@ -11,6 +11,23 @@ namespace XCEngine
public ulong UUID => m_uuid;
public static GameObject Find(string name)
{
ulong uuid = InternalCalls.GameObject_Find(name ?? string.Empty);
return uuid != 0 ? new GameObject(uuid) : null;
}
public static GameObject Create(string name)
{
return Create(name, null);
}
public static GameObject Create(string name, GameObject parent)
{
ulong uuid = InternalCalls.GameObject_Create(name ?? string.Empty, parent?.UUID ?? 0);
return uuid != 0 ? new GameObject(uuid) : null;
}
public string Name
{
get => InternalCalls.GameObject_GetName(UUID) ?? string.Empty;
@@ -32,6 +49,11 @@ namespace XCEngine
InternalCalls.GameObject_SetActive(UUID, value);
}
public void Destroy()
{
InternalCalls.GameObject_Destroy(UUID);
}
public Transform Transform => GetComponent<Transform>();
public Transform transform => Transform;

View File

@@ -41,6 +41,15 @@ namespace XCEngine
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern ulong GameObject_AddComponent(ulong gameObjectUUID, Type componentType);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern ulong GameObject_Find(string name);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern ulong GameObject_Create(string name, ulong parentGameObjectUUID);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern void GameObject_Destroy(ulong gameObjectUUID);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool Behaviour_GetEnabled(ulong scriptComponentUUID);