Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectDisposedException on many internal nodes after reloading a scene #71032

Open
lorenzo-arena opened this issue Jan 7, 2023 · 5 comments
Open

Comments

@lorenzo-arena
Copy link

Godot version

4.0-beta10.mono

System information

Windows 11, Ryzen 3700U Vega 10 iGPU

Issue description

After reloading a scene, a lot of errors come up when trying to interact with internal nodes of a scene. This happens also if:

  • scene A loads scene B
  • scene B loads scene A
  • scene A loads scene B another time

Steps to reproduce

The provided project has a scene with a timer; that scene is istantiated as a node inside another scene (Game.tscn). When Game.tscn gets reloaded if the internal scene tries to access the timer node the exception comes out.

Minimal reproduction project

To reproduce the issue:

  • load the project
  • start the game
  • click on the "Start Game" button
  • don't jump, so that the game over title appears
  • select "Back to Menu"
  • select "Start Game" again

flappy-bird.zip

@lorenzo-arena
Copy link
Author

By looking at the Godot output I also have the following errors:

Cannot open file '/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs'.
  Failed to read file: '/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs'.
  Cannot load C# script file '/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs'.
  Failed loading resource: /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs. Make sure resources have been imported by opening the project in the editor at least once.
  Cannot open file 'C:/Users/arena/Projects/20-games-challenge/flappy-bird/Godot.SourceGenerators/Godot.SourceGenerators.ScriptSignalsGenerator/GameEvents_ScriptSignals.generated.cs'.
  Failed to read file: 'C:/Users/arena/Projects/20-games-challenge/flappy-bird/Godot.SourceGenerators/Godot.SourceGenerators.ScriptSignalsGenerator/GameEvents_ScriptSignals.generated.cs'.
  Cannot load C# script file 'C:/Users/arena/Projects/20-games-challenge/flappy-bird/Godot.SourceGenerators/Godot.SourceGenerators.ScriptSignalsGenerator/GameEvents_ScriptSignals.generated.cs'.
  Failed loading resource: C:/Users/arena/Projects/20-games-challenge/flappy-bird/Godot.SourceGenerators/Godot.SourceGenerators.ScriptSignalsGenerator/GameEvents_ScriptSignals.generated.cs. Make sure resources have been imported by opening the project in the editor at least once.

@raulsntos
Copy link
Member

This is the error that I get after starting the game and losing a second time:

E 0:00:06:0572   void Godot.Bridge.ScriptManagerBridge.RaiseEventSignal(IntPtr , Godot.NativeInterop.godot_string_name* , Godot.NativeInterop.godot_variant** , Int32 , Godot.NativeInterop.godot_bool* ): System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'Godot.Timer'.
  <C++ Error>    Exception
  <C++ Source>   /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs:73 @ IntPtr Godot.Object.GetPtr(Godot.Object )()
  <Stack Trace>  Object.base.cs:73 @ IntPtr Godot.Object.GetPtr(Godot.Object )()
                 Object.base.cs:137 @ System.String Godot.Object.ToString()()
                 GD.cs:70 @ System.String Godot.GD+<>c.<GetPrintParams>b__3_0(System.Object )()
                 :0 @ TOutput[] System.Array.ConvertAll<TInput , TOutput >(TInput[] , System.Converter`2[TInput,TOutput] )()
                 GD.cs:70 @ System.String[] Godot.GD.GetPrintParams(System.Object[] )()
                 GD.cs:236 @ void Godot.GD.Print(System.Object[] )()
                 TubesGenerator.cs:35 @ void TubesGenerator.onPlayerDied()()
                 GameEvents_ScriptSignals.generated.cs:42 @ void GameEvents.RaiseGodotClassSignalCallbacks(Godot.NativeInterop.godot_string_name& , Godot.NativeInterop.NativeVariantPtrArgs )()
                 ScriptManagerBridge.cs:341 @ void Godot.Bridge.ScriptManagerBridge.RaiseEventSignal(IntPtr , Godot.NativeInterop.godot_string_name* , Godot.NativeInterop.godot_variant** , Int32 , Godot.NativeInterop.godot_bool* )()

Here's what I think is happening:

  • The TubesGenerator._Ready() method is invoked when the node is added to the Scene Tree.
  • On the _Ready() method, you subscribe to the GameEvents.PlayerDied event using the TubesGenerator.onPlayerDied method.
  • When moving to a different scene, the TubesGenerator instance is disposed, but the event is not unsubscribed.
  • When the player dies a second time and emits the PlayerDied event, the onPlayerDied method is invoked on the disposed TubesGenerator instance.

In this case, this would be a duplicate of this issue:

As a workaround you can try connecting to signals with the Connect method:

gameEvents.Connect(GameEvents.SignalName.PlayerDied, Callable.From(onPlayerDied));
// or
gameEvents.Connect(GameEvents.SignalName.PlayerDied, new Callable(this, MethodName.onPlayerDied));

The errors about reading the C# script files look similar to what I'm getting:

ERROR: Cannot open file '/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs'.
   at: read_all_file_utf8 (modules/mono/utils/string_utils.cpp:152)
ERROR: Failed to read file: '/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs'.
   at: load_source_code (modules/mono/csharp_script.cpp:2644)
ERROR: Cannot load C# script file '/root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs'.
   at: load (modules/mono/csharp_script.cpp:2714)
ERROR: Failed loading resource: /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Object.base.cs. Make sure resources have been imported by opening the project in the editor at least once.
   at: _load (core/io/resource_loader.cpp:214)

It looks like it may be this issue:

But it's weird because it's complaining about C# files that are engine code, not the game code.

Your errors also seem to be complaining about generated code, I didn't get those and as far as I know we are generating code using UTF-8 encoding. You may find it helpful to enable keeping generated files to look into them and see if you find anything weird:

<PropertyGroup>
    <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>

@lorenzo-arena
Copy link
Author

For the first part, I think this is definitely the same issue which was reported in #70414

I tried converting the calls using Connect but I didn't manage to get it working; I always receive errors like

ERROR: In Object of type 'Button': Attempt to connect nonexistent signal 'Pressed' to callable 'Delegate::Invoke'.
   at: (core/object/object.cpp:1256)

I tried adding the property but where should the files be generated?

@raulsntos
Copy link
Member

I tried converting the calls using Connect but I didn't manage to get it working

The error complains about the signal Pressed not existing in Button, that's true because the signal you're trying to connect to is pressed. Signals in native Godot classes use the snake_case naming convention.

It sounds like you may be using string literals for the signal name, I'd recommend using the exposed SignalName static class that is generated on every Godot type (e.g.: Button.SignalName.Pressed). This way you don't have to worry about naming conventions and also avoid allocating extra StringNames.

I tried adding the property but where should the files be generated?

Oh yeah, I should've mentioned, sorry about that. They are generated to .godot/mono/temp/obj/Debug/generated.

@lorenzo-arena
Copy link
Author

I slightly changed the architecture of the project so that references to disposed object are not called anymore and the issue is gone. I still have to try to convert the provided project to using Connect, so I will report here when I'm able to try it.

As for the generated files issue, after fixing the one of the disposed object it doesn't seems to happen anymore; I gave a look to the generated files and they doesn't seem to present any strange character.

aaronmsimon added a commit to aaronmsimon/godot-heartbeast-galaxy-defiance that referenced this issue Mar 31, 2024
Video 13 in series https://www.youtube.com/playlist?list=PL9FzW-m48fn09w6j8NowI_pSBVcsb3V78

Was getting errors after restarting after death and couldn't figure it out.  I realized thanks to this post:
godotengine/godot#71032
that I was not removing the event!  Removed it at the scene unloading and it worked!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants