Fix crash when unloading scene during tick of that scene

This commit is contained in:
Wojtek Figat
2026-03-12 13:39:01 +01:00
parent 5c51652e16
commit 8318a9c1d0
4 changed files with 31 additions and 23 deletions

View File

@@ -958,9 +958,6 @@ bool LevelImpl::unloadScene(Scene* scene)
// Simple enqueue scene root object to be deleted
scene->DeleteObject();
// Force flush deleted objects so we actually delete unloaded scene objects (prevent from reloading their managed objects, etc.)
ObjectsRemovalService::Flush();
return false;
}

View File

@@ -389,11 +389,14 @@ void Scene::BeginPlay(SceneBeginData* data)
if (model == nullptr)
CreateCsgModel();
}
Ticking.SetTicking(true);
}
void Scene::EndPlay()
{
// Improve scene cleanup performance by removing all data from scene rendering and ticking containers
Ticking.SetTicking(false);
Ticking.Clear();
Rendering.Clear();
Navigation.Clear();

View File

@@ -44,7 +44,7 @@ void SceneTicking::TickData::Tick()
{
TickScripts(Scripts);
for (int32 i = 0; i < Ticks.Count(); i++)
for (int32 i = 0; i < Ticks.Count() && _canTick; i++)
Ticks.Get()[i].Call();
}
@@ -66,7 +66,7 @@ void SceneTicking::TickData::TickExecuteInEditor()
{
TickScripts(ScriptsExecuteInEditor);
for (int32 i = 0; i < TicksExecuteInEditor.Count(); i++)
for (int32 i = 0; i < TicksExecuteInEditor.Count() && _canTick; i++)
TicksExecuteInEditor.Get()[i].Call();
}
@@ -89,10 +89,8 @@ SceneTicking::FixedUpdateTickData::FixedUpdateTickData()
void SceneTicking::FixedUpdateTickData::TickScripts(const Array<Script*>& scripts)
{
for (auto* script : scripts)
{
script->OnFixedUpdate();
}
for (int32 i = 0; i < scripts.Count() && _canTick; i++)
scripts.Get()[i]->OnFixedUpdate();
}
SceneTicking::UpdateTickData::UpdateTickData()
@@ -102,36 +100,30 @@ SceneTicking::UpdateTickData::UpdateTickData()
void SceneTicking::UpdateTickData::TickScripts(const Array<Script*>& scripts)
{
for (auto* script : scripts)
{
script->OnUpdate();
}
for (int32 i = 0; i < scripts.Count() && _canTick; i++)
scripts.Get()[i]->OnUpdate();
}
SceneTicking::LateUpdateTickData::LateUpdateTickData()
: TickData(64)
: TickData(0)
{
}
void SceneTicking::LateUpdateTickData::TickScripts(const Array<Script*>& scripts)
{
for (auto* script : scripts)
{
script->OnLateUpdate();
}
for (int32 i = 0; i < scripts.Count() && _canTick; i++)
scripts.Get()[i]->OnLateUpdate();
}
SceneTicking::LateFixedUpdateTickData::LateFixedUpdateTickData()
: TickData(64)
: TickData(0)
{
}
void SceneTicking::LateFixedUpdateTickData::TickScripts(const Array<Script*>& scripts)
{
for (auto* script : scripts)
{
script->OnLateFixedUpdate();
}
for (int32 i = 0; i < scripts.Count() && _canTick; i++)
scripts.Get()[i]->OnLateFixedUpdate();
}
void SceneTicking::AddScript(Script* obj)
@@ -167,3 +159,11 @@ void SceneTicking::Clear()
LateUpdate.Clear();
LateFixedUpdate.Clear();
}
void SceneTicking::SetTicking(bool enable)
{
FixedUpdate._canTick = enable;
Update._canTick = enable;
LateUpdate._canTick = enable;
LateFixedUpdate._canTick = enable;
}

View File

@@ -46,6 +46,9 @@ public:
/// </summary>
class FLAXENGINE_API TickData
{
protected:
friend SceneTicking;
bool _canTick = true;
public:
Array<Script*> Scripts;
Array<Tick> Ticks;
@@ -134,6 +137,11 @@ public:
/// </summary>
void Clear();
/// <summary>
/// Changes the ability to tick. When disabled, the ticking functions won't be called. Can be called during ticking (eg. when scene is unloaded) to stp performing any more ticks.
/// </summary>
void SetTicking(bool enable);
public:
/// <summary>
/// The fixed update tick function.