Fix calling script OnDestroy when removing actors or scripts from the scene

This commit is contained in:
Wojtek Figat
2023-12-18 21:43:13 +01:00
parent 72f45afa45
commit bc2e130281
3 changed files with 41 additions and 12 deletions

View File

@@ -206,10 +206,18 @@ void Actor::OnDeleteObject()
#endif #endif
for (int32 i = 0; i < Scripts.Count(); i++) for (int32 i = 0; i < Scripts.Count(); i++)
{ {
auto e = Scripts[i]; auto script = Scripts[i];
ASSERT(e->_parent == this); ASSERT(script->_parent == this);
e->_parent = nullptr; if (script->_wasAwakeCalled)
e->DeleteObject(); {
script->_wasAwakeCalled = false;
CHECK_EXECUTE_IN_EDITOR
{
script->OnDestroy();
}
}
script->_parent = nullptr;
script->DeleteObject();
} }
#if BUILD_DEBUG #if BUILD_DEBUG
ASSERT(callsCheck == Scripts.Count()); ASSERT(callsCheck == Scripts.Count());
@@ -889,9 +897,13 @@ void Actor::EndPlay()
for (auto* script : Scripts) for (auto* script : Scripts)
{ {
CHECK_EXECUTE_IN_EDITOR if (script->_wasAwakeCalled)
{ {
script->OnDestroy(); script->_wasAwakeCalled = false;
CHECK_EXECUTE_IN_EDITOR
{
script->OnDestroy();
}
} }
} }

View File

@@ -27,6 +27,7 @@ Script::Script(const SpawnParams& params)
, _tickUpdate(false) , _tickUpdate(false)
, _tickLateUpdate(false) , _tickLateUpdate(false)
, _tickLateFixedUpdate(false) , _tickLateFixedUpdate(false)
, _wasAwakeCalled(false)
, _wasStartCalled(false) , _wasStartCalled(false)
, _wasEnableCalled(false) , _wasEnableCalled(false)
{ {
@@ -86,7 +87,7 @@ void Script::SetParent(Actor* value, bool canBreakPrefabLink)
// Unlink from the old one // Unlink from the old one
if (_parent) if (_parent)
{ {
if (!value && _parent->IsDuringPlay() && _parent->IsActiveInHierarchy() && GetEnabled()) if (!value && _parent->IsDuringPlay() && _parent->IsActiveInHierarchy() && GetEnabled() && _wasEnableCalled)
{ {
// Call disable when script is removed from actor (new actor is null) // Call disable when script is removed from actor (new actor is null)
Disable(); Disable();
@@ -241,19 +242,31 @@ String Script::ToString() const
void Script::OnDeleteObject() void Script::OnDeleteObject()
{ {
// Ensure to unlink from the parent (it will call Disable event if required) // Call OnDisable
SetParent(nullptr); if (_wasEnableCalled)
// Check if remove object from game
if (IsDuringPlay())
{ {
Disable();
}
// Call OnDestroy
if (_wasAwakeCalled)
{
_wasAwakeCalled = false;
CHECK_EXECUTE_IN_EDITOR CHECK_EXECUTE_IN_EDITOR
{ {
OnDestroy(); OnDestroy();
} }
}
// End play
if (IsDuringPlay())
{
EndPlay(); EndPlay();
} }
// Unlink from parent
SetParent(nullptr);
// Base // Base
SceneObject::OnDeleteObject(); SceneObject::OnDeleteObject();
} }
@@ -274,6 +287,9 @@ void Script::Initialize()
if (!IsRegistered()) if (!IsRegistered())
RegisterObject(); RegisterObject();
// Call OnAwake
ASSERT(!_wasAwakeCalled);
_wasAwakeCalled = true;
CHECK_EXECUTE_IN_EDITOR CHECK_EXECUTE_IN_EDITOR
{ {
OnAwake(); OnAwake();

View File

@@ -20,6 +20,7 @@ protected:
uint16 _tickUpdate : 1; uint16 _tickUpdate : 1;
uint16 _tickLateUpdate : 1; uint16 _tickLateUpdate : 1;
uint16 _tickLateFixedUpdate : 1; uint16 _tickLateFixedUpdate : 1;
uint16 _wasAwakeCalled : 1;
uint16 _wasStartCalled : 1; uint16 _wasStartCalled : 1;
uint16 _wasEnableCalled : 1; uint16 _wasEnableCalled : 1;
#if USE_EDITOR #if USE_EDITOR