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

@@ -28,6 +28,10 @@ void ScriptEngine::OnRuntimeStart(Components::Scene* scene) {
m_runtimeScene = scene;
m_runtimeRunning = true;
m_runtime->OnRuntimeStart(scene);
m_runtimeSceneCreatedSubscription = scene->OnGameObjectCreated().Subscribe(
[this](Components::GameObject* gameObject) {
HandleGameObjectCreated(gameObject);
});
for (Components::GameObject* root : scene->GetRootGameObjects()) {
CollectScriptComponents(root);
@@ -49,6 +53,12 @@ void ScriptEngine::OnRuntimeStart(Components::Scene* scene) {
}
void ScriptEngine::OnRuntimeStop() {
if (m_runtimeScene && m_runtimeSceneCreatedSubscription != 0) {
m_runtimeScene->OnGameObjectCreated().Unsubscribe(m_runtimeSceneCreatedSubscription);
m_runtimeScene->OnGameObjectCreated().ProcessUnsubscribes();
m_runtimeSceneCreatedSubscription = 0;
}
if (!m_runtimeRunning) {
m_runtimeScene = nullptr;
m_scriptStates.clear();
@@ -209,6 +219,34 @@ void ScriptEngine::CollectScriptComponents(Components::GameObject* gameObject) {
}
}
void ScriptEngine::EnsureTrackedScriptsReady(Components::GameObject* gameObject) {
if (!gameObject) {
return;
}
for (ScriptComponent* component : gameObject->GetComponents<ScriptComponent>()) {
ScriptInstanceState* state = FindState(component);
if (!state || !ShouldScriptRun(*state)) {
continue;
}
EnsureScriptReady(*state, true);
}
for (Components::GameObject* child : gameObject->GetChildren()) {
EnsureTrackedScriptsReady(child);
}
}
void ScriptEngine::HandleGameObjectCreated(Components::GameObject* gameObject) {
if (!m_runtimeRunning || !gameObject || gameObject->GetScene() != m_runtimeScene) {
return;
}
CollectScriptComponents(gameObject);
EnsureTrackedScriptsReady(gameObject);
}
ScriptEngine::ScriptInstanceState* ScriptEngine::TrackScriptComponent(ScriptComponent* component) {
if (!component || !component->GetGameObject()) {
return nullptr;