Cysharp / R3

The new future of dotnet/reactive and UniRx.
MIT License
2.25k stars 98 forks source link

Godot Error for reload editor #125

Closed tkzcxl closed 3 weeks ago

tkzcxl commented 8 months ago

After installing and setting up the plugin, create a C# script and attach it to the scene, then run the game. Close the game, modify the script, rebuild/run the game, and the following error occurs

modules/mono/mono_gd/gd_mono.cpp:528 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User) modules/mono/mono_gd/gd_mono.cpp:512 - .NET: Giving up on assembly reloading. Please restart the editor if unloading was failing. (User)

platform : windows Godot version : 4.2.1/4.1/4.3dev3

tkzcxl commented 8 months ago

The script does not need to contain anything, just needs public override void _Ready() { GD.Print("Hello"); } It can then be triggered by modifying the print after the game has run once

neuecc commented 8 months ago

If it's a Godot issue, I can't touch it. https://github.com/godotengine/godot/issues/78513 I will keep a close watch on this.

Delsin-Yu commented 8 months ago

78513 is a mega issue that describes various issues that eventually lead to AssemblyUnloadingFailure, I would like to know which of these issues R3 has triggered, or if we have just discovered a new one.

  1. Capturing a variable in a Callable prevents assembly unloading
  2. C# Script Registration that uses Generics can error out in the ScriptManagerBridge
  3. C# Initialize an Exported GodotObject prevents assembly unloading

Really miss the day when AppDomain existed and we didn't need to care about these references' chaos.

tkzcxl commented 8 months ago

If it's a Godot issue, I can't touch it. godotengine/godot#78513 I will keep a close watch on this.

After investigation, it appears to be an issue with Godot's plugin system, which is caused by the AddAutoloadSingleton method. I've found a workaround to make R3 work with Godot 4.x. The solution involves copying the _ExitTree code from GodotR3Plugin and placing it at the top of _EnterTree. This should circumvent the problem. Code

public override void _EnterTree()
    {
        // Remove before adding to avoid problems
        if (observableTrackerDebugger != null)
        {
            RemoveDebuggerPlugin(observableTrackerDebugger);
            observableTrackerDebugger = null;
        }
        RemoveAutoloadSingleton(nameof(FrameProviderDispatcher));
        RemoveAutoloadSingleton(nameof(ObservableTrackerRuntimeHook));

        observableTrackerDebugger ??= new ObservableTrackerDebuggerPlugin();
        AddDebuggerPlugin(observableTrackerDebugger);
        // Automatically install autoloads here for ease of use.
        AddAutoloadSingleton(nameof(FrameProviderDispatcher), "res://addons/R3.Godot/FrameProviderDispatcher.cs");
        AddAutoloadSingleton(nameof(ObservableTrackerRuntimeHook), "res://addons/R3.Godot/ObservableTrackerRuntimeHook.cs");
    }
tkzcxl commented 8 months ago

Oh, no, that might still have a chance of causing the issue. The method I've found that seems to work without problems is to add these two autoloaded singletons and then comment out the part where you add the autoloaded singletons. Perhaps there's a better way to do this?

lfod1997 commented 6 months ago

Can confirm this issue. The workaround proposed by @tkzcxl , which is informative, does not help much, in my case.

dotMemory mem dump shows that a LoaderAllocator is implicitly created when a local variable tab, allocated in ObservableTrackerDebuggerPlugin.cs:54, gets captured by callables in local scope (which is a known pitfall), breaking unloadability.

So

78513 is a mega issue that describes various issues that eventually lead to AssemblyUnloadingFailure, I would like to know which of these issues R3 has triggered, or if we have just discovered a new one.

  1. Capturing a variable in a Callable prevents assembly unloading

Seems we are hitting category 1.

Tried introducing named methods to avoid capturing; did not solve the problem either.

Delsin-Yu commented 6 months ago

Can confirm this issue. The workaround proposed by @tkzcxl , which is informative, does not help much, in my case.

dotMemory mem dump shows that a LoaderAllocator is implicitly created when a local variable tab, allocated in ObservableTrackerDebuggerPlugin.cs:54, gets captured by callables in local scope (which is a known pitfall), breaking unloadability.

So

78513 is a mega issue that describes various issues that eventually lead to AssemblyUnloadingFailure, I would like to know which of these issues R3 has triggered, or if we have just discovered a new one.

  1. Capturing a variable in a Callable prevents assembly unloading

Seems we are hitting category 1.

Tried introducing named methods to avoid capturing; did not solve the problem either.

This issue should be fixed by now, which will be included in the upcoming 4.3 dev6, sadly this fix cannot be back ported to older Godot versions.

github-actions[bot] commented 4 weeks ago

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 30 days.

Delsin-Yu commented 4 weeks ago

@tkzcxl If possible, can you try this on the 4.3 stable?

tkzcxl commented 3 weeks ago

@tkzcxl如果可能的话,您可以在 4.3 稳定版上尝试一下吗?

4.3 is ok