godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.55k stars 21.26k forks source link

"Cannot access a disposed object" when using an exported node and scene inheritance #99152

Open AdamLearns opened 2 weeks ago

AdamLearns commented 2 weeks ago

Tested versions

System information

M2 macOS - Sonoma 14.6.1

Issue description

In the attached project, try running Derived.tscn. It will output this:

E 0:00:00:0674   GodotObject.base.cs:78 @ nint Godot.GodotObject.GetPtr(Godot.GodotObject): System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'foo.Base'.
  <C# Error>     System.ObjectDisposedException
  <C# Source>    /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs:78 @ nint Godot.GodotObject.GetPtr(Godot.GodotObject)
  <Stack Trace>  GodotObject.base.cs:78 @ nint Godot.GodotObject.GetPtr(Godot.GodotObject)
                 Node.cs:752 @ Godot.StringName Godot.Node.GetName()
                 Node.cs:374 @ Godot.StringName Godot.Node.get_Name()
                 NodeReferencer.cs:13 @ void foo.NodeReferencer._Ready()
                 Node.cs:2401 @ bool Godot.Node.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name&, Godot.NativeInterop.NativeVariantPtrArgs, Godot.NativeInterop.godot_variant&)
                 foo.NodeReferencer_ScriptMethods.generated.cs:40 @ bool foo.NodeReferencer.InvokeGodotClassMethod(Godot.NativeInterop.godot_string_name&, Godot.NativeInterop.NativeVariantPtrArgs, Godot.NativeInterop.godot_variant&)
                 CSharpInstanceBridge.cs:24 @ Godot.NativeInterop.godot_bool Godot.Bridge.CSharpInstanceBridge.Call(nint, Godot.NativeInterop.godot_string_name*, Godot.NativeInterop.godot_variant**, int, Godot.NativeInterop.godot_variant_call_error*, Godot.NativeInterop.godot_variant*)

For whatever reason, Base.Dispose is indeed called. I don't know why that's happening, but as a result, NodeReferencer is unable to access the now-disposed node being referenced.

Steps to reproduce

It seems that you have to do this:

This does not seem to reproduce when using GDScript, only C#. In GDScript, I don't see NOTIFICATION_PREDELETE being sent.

Minimal reproduction project (MRP)

DisposedObjectRepro.zip

AdamLearns commented 2 weeks ago

Note to anyone experiencing this: you can work around this by setting NodeWithReference through code instead of through the editor. This isn't ideal as it means that you can't just start using the nodes from _Ready(), but at least it's a somewhat minimal change as opposed to redoing your entire scene inheritance hierarchy.