Optimize Actor::DestroyChildren

This commit is contained in:
Wojtek Figat
2025-06-20 09:05:25 +02:00
parent 2e10d776e9
commit d3a50cdacb
6 changed files with 124 additions and 4 deletions

View File

@@ -466,12 +466,71 @@ Array<Actor*> Actor::GetChildren(const MClass* type) const
void Actor::DestroyChildren(float timeLeft)
{
if (Children.IsEmpty())
return;
PROFILE_CPU();
// Actors system doesn't support editing scene hierarchy from multiple threads
if (!IsInMainThread() && IsDuringPlay())
{
LOG(Error, "Editing scene hierarchy is only allowed on a main thread.");
return;
}
// Get all actors
Array<Actor*> children = Children;
// Inform Editor beforehand
Level::callActorEvent(Level::ActorEventType::OnActorDestroyChildren, this, nullptr);
if (_scene && IsActiveInHierarchy())
{
// Disable children
for (Actor* child : children)
{
if (child->IsActiveInHierarchy())
{
child->OnDisableInHierarchy();
}
}
}
Level::ScenesLock.Lock();
// Remove children all at once
Children.Clear();
_isHierarchyDirty = true;
// Unlink children from scene hierarchy
for (Actor* child : children)
{
child->_parent = nullptr;
if (!_isActiveInHierarchy)
child->_isActive = false; // Force keep children deactivated to reduce overhead during destruction
if (_scene)
child->SetSceneInHierarchy(nullptr);
}
Level::ScenesLock.Unlock();
// Inform actors about this
for (Actor* child : children)
{
child->OnParentChanged();
}
// Unlink children for hierarchy
for (Actor* child : children)
{
//child->EndPlay();
//child->SetParent(nullptr, false, false);
}
// Delete objects
const bool useGameTime = timeLeft > ZeroTolerance;
for (Actor* child : children)
{
child->SetParent(nullptr, false, false);
child->DeleteObject(timeLeft, useGameTime);
}
}
@@ -1280,7 +1339,6 @@ void Actor::OnActiveChanged()
if (wasActiveInTree != IsActiveInHierarchy())
OnActiveInTreeChanged();
//if (GetScene())
Level::callActorEvent(Level::ActorEventType::OnActorActiveChanged, this, nullptr);
}
@@ -1311,7 +1369,6 @@ void Actor::OnActiveInTreeChanged()
void Actor::OnOrderInParentChanged()
{
//if (GetScene())
Level::callActorEvent(Level::ActorEventType::OnActorOrderInParentChanged, this, nullptr);
}

View File

@@ -263,6 +263,9 @@ Delegate<Actor*, Actor*> Level::ActorParentChanged;
Delegate<Actor*> Level::ActorOrderInParentChanged;
Delegate<Actor*> Level::ActorNameChanged;
Delegate<Actor*> Level::ActorActiveChanged;
#if USE_EDITOR
Delegate<Actor*> Level::ActorDestroyChildren;
#endif
Delegate<Scene*, const Guid&> Level::SceneSaving;
Delegate<Scene*, const Guid&> Level::SceneSaved;
Delegate<Scene*, const Guid&> Level::SceneSaveError;
@@ -851,6 +854,11 @@ void Level::callActorEvent(ActorEventType eventType, Actor* a, Actor* b)
case ActorEventType::OnActorActiveChanged:
ActorActiveChanged(a);
break;
#if USE_EDITOR
case ActorEventType::OnActorDestroyChildren:
ActorDestroyChildren(a);
break;
#endif
}
}

View File

@@ -549,7 +549,13 @@ private:
OnActorOrderInParentChanged = 3,
OnActorNameChanged = 4,
OnActorActiveChanged = 5,
#if USE_EDITOR
OnActorDestroyChildren = 6,
#endif
};
static void callActorEvent(ActorEventType eventType, Actor* a, Actor* b);
#if USE_EDITOR
API_EVENT(Internal) static Delegate<Actor*> ActorDestroyChildren;
#endif
};