LogicalError / realtime-CSG-for-unity

Realtime-CSG, CSG level editor for Unity
https://realtimecsg.com
MIT License
761 stars 80 forks source link

Exiting play mode with brush selected causes MissingReferenceException with destroyed CSGBrush #255

Closed hunterhunted closed 5 years ago

hunterhunted commented 6 years ago

I often edit brushes then play to check how they seem ingame, but was getting spammed with errors upon stopping and entering edit mode again if a brush was still selected at the time.

Error received: "MissingReferenceException: The object of type 'CSGBrush' has been destroyed but you are still trying to access it. Your script should either check if it is null or you should not destroy the object." in OnInspectorGUI of EditModeSelection.GUI.cs at line: var gameObject = targetNodes[0].gameObject;

The 3D selection box etc is also no longer visible. These (and further errors if in a tool edit mode such as Mesh) happen until the selection is changed manually.

There might be a better way, but I've done this as a workaround in the meantime (to version 1.529): In OnInspectorGUI of EditModeSelection.GUI.cs: Replaced if (targetNodes.Length > 0 ) with if (targetNodes.Length > 0 && targetNodes[0] != null) to avoid initial errors.

In SetTargets of EditMode.Object.cs: Replaced if (!ArrayUtility.Contains(brushes, newBrushes[i])) with if (brushes[i] == null || !ArrayUtility.Contains(brushes, newBrushes[i])) To ensure refresh if brushes destroyed in object mode.

In Select of BrushSelection.cs: Replaced if (foundBrushes.Contains(Brushes[i])) with if (Brushes[i] != null && foundBrushes.Contains(Brushes[i])) To allow null brushes to be removed from the lists for mesh edit.

In SetTargets of EditMode.Surface.cs: Replaced if (foundBrushes.Contains(brushTargets[i])) with if (brushTargets[i] != null && foundBrushes.Contains(brushTargets[i])) To remove null brushes from surface targets.

In RunOnce of UpdateLoop.cs: Added if (EditModeManager.FilteredSelection.NodeTargets.Length > 0 && EditModeManager.FilteredSelection.NodeTargets[0] == null) { EditModeManager.UpdateSelection(); } To force a selection update on exiting play mode.

With these edits, there are no errors and the scene shows most tools correctly (though default sub-part selection similar to recompiling) when exiting play mode (Not used clip mode much, didn't notice any difference with similar null check for backupData[i].brush or not.)

LogicalError commented 6 years ago

Thanks for letting me know about this & thanks for the fix :)

hunterhunted commented 6 years ago

Also discovered OnApplicationQuit in CSGSceneManagerInstance sets InternalCSGModelManager.IsQuitting = true; when exiting play mode, which stops component unregistration/dynamic updates when deleting brushes etc.

To repro, play/stop then delete brushes: this will not update the rendered model automatically until recompiling scripts. One-time update forcable by calling ForceRebuild or exiting play mode again but EnsureBuildFinished does not detect the removed brush.

I've worked around for now by putting InternalCSGModelManager.IsQuitting = false; inside the OnCreated function for CSGModel in InternalCSGModelManager.Registration.cs but I don't know if this will cause other problems or not.

LogicalError commented 6 years ago

thanks, I'll see if I can fix this soon

LogicalError commented 5 years ago

This seems to have already been fixed at some point? Let me know if you still run into this