feat(scripting): support managed script component api

This commit is contained in:
2026-03-28 00:43:13 +08:00
parent 6bde199393
commit e522bad582
8 changed files with 349 additions and 37 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/ScriptComponentApiProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/RuntimeGameObjectProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/HierarchyProbe.cs
${CMAKE_CURRENT_SOURCE_DIR}/GameScripts/LifecycleProbe.cs

View File

@@ -0,0 +1,74 @@
using System;
using XCEngine;
namespace Gameplay
{
public sealed class ScriptComponentTargetProbe : MonoBehaviour
{
public int AwakeCount;
public int StartCount;
public int HostCallCount;
public string HostName = string.Empty;
public void Awake()
{
AwakeCount++;
HostName = gameObject.Name;
}
public void Start()
{
StartCount++;
}
public void IncrementFromHost()
{
HostCallCount++;
}
}
public sealed class ScriptComponentApiProbe : MonoBehaviour
{
public bool InitialHasTarget;
public bool InitialLookupReturnedNull;
public bool AddedTarget;
public bool HasTargetAfterAdd;
public bool LookupSucceededAfterAdd;
public bool TryGetSucceededAfterAdd;
public bool ReturnedSameInstance;
public bool TargetEnabledAfterAdd;
public int ObservedTargetAwakeCount;
public int ObservedTargetStartCount;
public int ObservedTargetHostCallCount;
public string ObservedTargetHostName = string.Empty;
public void Start()
{
InitialHasTarget = HasComponent<ScriptComponentTargetProbe>();
InitialLookupReturnedNull = GetComponent<ScriptComponentTargetProbe>() == null;
ScriptComponentTargetProbe added = AddComponent<ScriptComponentTargetProbe>();
AddedTarget = added != null;
HasTargetAfterAdd = HasComponent<ScriptComponentTargetProbe>();
ScriptComponentTargetProbe resolved = GetComponent<ScriptComponentTargetProbe>();
TryGetSucceededAfterAdd = TryGetComponent(out ScriptComponentTargetProbe tried);
LookupSucceededAfterAdd = resolved != null;
ReturnedSameInstance = added != null
&& ReferenceEquals(added, resolved)
&& ReferenceEquals(added, tried);
if (added == null)
{
return;
}
added.IncrementFromHost();
TargetEnabledAfterAdd = added.enabled;
ObservedTargetAwakeCount = added.AwakeCount;
ObservedTargetStartCount = added.StartCount;
ObservedTargetHostCallCount = added.HostCallCount;
ObservedTargetHostName = added.HostName ?? string.Empty;
}
}
}

View File

@@ -64,14 +64,12 @@ namespace XCEngine
public T GetComponent<T>() where T : Component
{
ulong componentOwnerUUID = InternalCalls.GameObject_GetComponent(UUID, typeof(T));
return Component.Create<T>(componentOwnerUUID);
return InternalCalls.GameObject_GetComponent(UUID, typeof(T)) as T;
}
public T AddComponent<T>() where T : Component
{
ulong componentOwnerUUID = InternalCalls.GameObject_AddComponent(UUID, typeof(T));
return Component.Create<T>(componentOwnerUUID);
return InternalCalls.GameObject_AddComponent(UUID, typeof(T)) as T;
}
public bool TryGetComponent<T>(out T component) where T : Component

View File

@@ -36,10 +36,10 @@ namespace XCEngine
internal static extern bool GameObject_HasComponent(ulong gameObjectUUID, Type componentType);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern ulong GameObject_GetComponent(ulong gameObjectUUID, Type componentType);
internal static extern Component GameObject_GetComponent(ulong gameObjectUUID, Type componentType);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern ulong GameObject_AddComponent(ulong gameObjectUUID, Type componentType);
internal static extern Component GameObject_AddComponent(ulong gameObjectUUID, Type componentType);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern ulong GameObject_Find(string name);