Add logging and cleaning up leaked scene objects after play mode in Editor
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
#include "Engine/Engine/CommandLine.h"
|
#include "Engine/Engine/CommandLine.h"
|
||||||
#include "Engine/Renderer/ProbesRenderer.h"
|
#include "Engine/Renderer/ProbesRenderer.h"
|
||||||
#include "Engine/Animations/Graph/AnimGraph.h"
|
#include "Engine/Animations/Graph/AnimGraph.h"
|
||||||
|
#include "Engine/Core/ObjectsRemovalService.h"
|
||||||
|
|
||||||
ManagedEditor::InternalOptions ManagedEditor::ManagedEditorOptions;
|
ManagedEditor::InternalOptions ManagedEditor::ManagedEditorOptions;
|
||||||
|
|
||||||
@@ -572,6 +573,29 @@ bool ManagedEditor::EvaluateVisualScriptLocal(VisualScript* script, VisualScript
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ManagedEditor::WipeOutLeftoverSceneObjects()
|
||||||
|
{
|
||||||
|
Array<ScriptingObject*> objects = Scripting::GetObjects();
|
||||||
|
bool removedAny = false;
|
||||||
|
for (ScriptingObject* object : objects)
|
||||||
|
{
|
||||||
|
if (EnumHasAllFlags(object->Flags, ObjectFlags::IsDuringPlay) && EnumHasNoneFlags(object->Flags, ObjectFlags::WasMarkedToDelete))
|
||||||
|
{
|
||||||
|
if (auto* sceneObject = Cast<SceneObject>(object))
|
||||||
|
{
|
||||||
|
if (sceneObject->HasParent())
|
||||||
|
continue; // Skip sub-objects
|
||||||
|
|
||||||
|
LOG(Error, "Object '{}' (ID={}, Type={}) is still in memory after play end but should be destroyed (memory leak).", sceneObject->GetNamePath(), sceneObject->GetID(), sceneObject->GetType().ToString());
|
||||||
|
sceneObject->DeleteObject();
|
||||||
|
removedAny = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removedAny)
|
||||||
|
ObjectsRemovalService::Flush();
|
||||||
|
}
|
||||||
|
|
||||||
void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly)
|
void ManagedEditor::OnEditorAssemblyLoaded(MAssembly* assembly)
|
||||||
{
|
{
|
||||||
ASSERT(!HasManagedInstance());
|
ASSERT(!HasManagedInstance());
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ public:
|
|||||||
API_FUNCTION(Internal) static VisualScriptStackFrame GetVisualScriptPreviousScopeFrame();
|
API_FUNCTION(Internal) static VisualScriptStackFrame GetVisualScriptPreviousScopeFrame();
|
||||||
API_FUNCTION(Internal) static Array<VisualScriptLocal> GetVisualScriptLocals();
|
API_FUNCTION(Internal) static Array<VisualScriptLocal> GetVisualScriptLocals();
|
||||||
API_FUNCTION(Internal) static bool EvaluateVisualScriptLocal(VisualScript* script, API_PARAM(Ref) VisualScriptLocal& local);
|
API_FUNCTION(Internal) static bool EvaluateVisualScriptLocal(VisualScript* script, API_PARAM(Ref) VisualScriptLocal& local);
|
||||||
|
API_FUNCTION(Internal) static void WipeOutLeftoverSceneObjects();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnEditorAssemblyLoaded(MAssembly* assembly);
|
void OnEditorAssemblyLoaded(MAssembly* assembly);
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ namespace FlaxEditor.States
|
|||||||
|
|
||||||
// Restore editor scene
|
// Restore editor scene
|
||||||
SceneRestoring?.Invoke();
|
SceneRestoring?.Invoke();
|
||||||
_duplicateScenes.DeletedScenes();
|
_duplicateScenes.UnloadScenes();
|
||||||
PluginManager.Internal_DeinitializeGamePlugins();
|
PluginManager.Internal_DeinitializeGamePlugins();
|
||||||
Editor.Internal_SetPlayMode(false);
|
Editor.Internal_SetPlayMode(false);
|
||||||
_duplicateScenes.RestoreSceneData();
|
_duplicateScenes.RestoreSceneData();
|
||||||
|
|||||||
@@ -120,9 +120,9 @@ namespace FlaxEditor.Utilities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the creates scenes for the simulation.
|
/// Deletes the creates scenes for the simulation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void DeletedScenes()
|
public void UnloadScenes()
|
||||||
{
|
{
|
||||||
Profiler.BeginEvent("DuplicateScenes.DeletedScenes");
|
Profiler.BeginEvent("DuplicateScenes.UnloadScenes");
|
||||||
Editor.Log("Restoring scene data");
|
Editor.Log("Restoring scene data");
|
||||||
|
|
||||||
// TODO: here we can keep changes for actors marked to keep their state after simulation
|
// TODO: here we can keep changes for actors marked to keep their state after simulation
|
||||||
@@ -134,6 +134,8 @@ namespace FlaxEditor.Utilities
|
|||||||
throw new Exception("Failed to unload scenes.");
|
throw new Exception("Failed to unload scenes.");
|
||||||
}
|
}
|
||||||
FlaxEngine.Scripting.FlushRemovedObjects();
|
FlaxEngine.Scripting.FlushRemovedObjects();
|
||||||
|
Editor.WipeOutLeftoverSceneObjects();
|
||||||
|
|
||||||
Profiler.EndEvent();
|
Profiler.EndEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -721,6 +721,15 @@ void Scripting::Reload(bool canTriggerSceneReload)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Array<ScriptingObject*, HeapAllocation> Scripting::GetObjects()
|
||||||
|
{
|
||||||
|
Array<ScriptingObject*> objects;
|
||||||
|
_objectsLocker.Lock();
|
||||||
|
_objectsDictionary.GetValues(objects);
|
||||||
|
_objectsLocker.Unlock();
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
MClass* Scripting::FindClass(const StringAnsiView& fullname)
|
MClass* Scripting::FindClass(const StringAnsiView& fullname)
|
||||||
{
|
{
|
||||||
if (fullname.IsEmpty())
|
if (fullname.IsEmpty())
|
||||||
|
|||||||
@@ -79,6 +79,13 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all registered scripting objects.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Use with caution due to potentially large memory allocation.</remarks>
|
||||||
|
/// <returns>The collection of the objects.</returns>
|
||||||
|
static Array<ScriptingObject*, HeapAllocation> GetObjects();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the class with given fully qualified name within whole assembly.
|
/// Finds the class with given fully qualified name within whole assembly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user