godotengine / godotengine/godot

[MRP] Possible fix/workaround for .NET: Failed to unload assemblies when using generic AND non-generic classes with same class name

Open
#110,784 1 comment 3 reactions 0 assignees View on GitHub
bug needs testing topic:dotnet
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

Reproducible v4.5.stable.mono.official [876b29033]

### System information

Windows 11 - Godot v4.5.stable.mono.official [876b29033] - RTX 4080 Super

### Issue description

Describing the issue [.NET: Failed to unload assemblies. Please check for more information.](https://github.com/godotengine/godot/issues/78513#top)

when building the assemblies from c# with two identical class names one of them being generic and the other non-generic -> `SomeClass` & `SomeClass`

### Minimal reproduction project (MRP)

# Download Link for MRP
[Typed Class Issue MRP.zip](https://github.com/user-attachments/files/22472026/Typed.Class.Issue.MRP.zip)

This MRP has been requested by [Delsin-Yu](https://github.com/Delsin-Yu) -> https://github.com/godotengine/godot/issues/78513#issuecomment-3319661064

# Explanation about this MRP

This is a rip off from an Action System where the ActionCollection.tscn holds all SceneObjects that inherit from either the SomeBase or SomeBase classes. These are being loaded at the beginning in the _Ready hook.

For this MRP I added 4 Actions as listed in the `EBaseAction` Enum.
These can be found in the actions folder located under `res://actions/`

1. `EBaseAction.SyncActionWithoutParam` <- Executes a synchronous method without a param

2. `EBaseAction.SyncActionWithParam` <- Executes a synchronous method with an integer as the param

3. `EBaseAction.AsyncActionWithoutParam` <- Executes an aynchronous method without a param

4. `EBaseAction.AsyncActionWithParam` <- Executes an asynchronous method with an integer as the param

Both base classes take the ISomeBase interface in to account and are abstract because they hold an abstract enum to which is mandatory to override.
Further are virtual methods to override to be able to override synchronous or asynchronous methods that can be loaded with params or optionally without params.

All these Actions are called from the `Main.cs` _Ready hook.

### Steps to reproduce

# Instructions to reproduce error (Solution for this MRP is at the bottom):

1. Initially open `Main.cs`

2. Rename
`[Export] string something;`
to
`[Export] string somethingggg;`

3. In Visual Studio code `Ctrl+Shift+B` -> `dotnet: build`

4. Let the assemblies build.

5. Focus to Godot Editor (click somewhere in the godot editor)

6. Get the errors in the console:

ERROR: /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/ExceptionUtils.cs:113 - System.ArgumentException: An item with the same key has already been added. Key: SomeBase`1[System.Int32]
ERROR: at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
ERROR: at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
ERROR: at Godot.Bridge.ScriptManagerBridge.ScriptTypeBiMap.Add(IntPtr scriptPtr, Type scriptType) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs:line 30
ERROR: at Godot.Bridge.ScriptManagerBridge.TryReloadRegisteredScriptWithClass(IntPtr scriptPtr) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:line 691

7. Rename
`[Export] string somethingggg;`
to
`[Export] string something;`

8. In Visual Studio code `Ctrl+Shift+B` -> `dotnet: build`

9. Let the assemblies build.

10. Focus to Godot Editor (click somewhere in the godot editor)

11. You should see the unloading assemblies error at the bottom of the godot editor:

# Solution to fix this issue:

1. Open `SomeTypedBase.cs` (found at `res://base/SomeTypedBase.cs`)

2. Rename (F2) the class name from `SomeBase` something else like `SomeTypedBase`

3. If needed restart the editor because of the failed assembly still hanging.

4. Open Godot Editor

5. Open Visual Studio

6. Again in Visual Studio code `Ctrl+Shift+B` -> `dotnet: build`

6. Unloading Assembly Errors should be gone

Contributor guide

Open the contributing guide

Research direction

Start with the MRP steps using Main.cs and res://base/SomeTypedBase.cs, then inspect the reported paths modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs and ScriptManagerBridge.cs. Reproduce the rename-and-build cycle with SomeBase and SomeBase, and trace the reported duplicate-key and assembly-unload errors. Done means the assemblies reload without these errors while both class forms remain usable.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
developer-experience, game-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.