6

General
Working on a mod for a game using the Unity Engine.

The problem
I'm trying to attach to the activeSceneChanged event with this code:

SceneManager.activeSceneChanged += OnSceneChanged;

This results in the error:

CS0229 Ambiguity between 'SceneManager.activeSceneChanged' and 'SceneManager.activeSceneChanged'

After checking what's going on here, it seems that the activeSceneChanged member is both user generated and [CompilerGenerated]:

enter image description here

What I've tried myself
I honestly have no idea at all how I'd fix an issue like this. I've never encountered it before. Asked a few other devs I know, but they never seen it either. Decompiled the Unity DLL file with ILSpy, only to see that CompilerGenerated code isn't in there (kind of makes sense since it's generated by the compiler I assume).

I'd really like some help on how to approach this issue and solve it.

Edit
To help speed things up, here's a Github link to the mod: https://github.com/skarab42/ValheimTwitch

The error pops up at line 93 in Plugin.cs

Michael Liu
  • 52,147
  • 13
  • 117
  • 150
icecub
  • 8,615
  • 6
  • 41
  • 70
  • No idea what's going on, but neither of the highlighted lines show a _type_ (as you described it. The first line is a _field_, the second is an _event_. Since it's an event, then `UnityAction` must be a delegate type (because that's how you type events). That makes me curious what the first line signifies. Are you really sure that those are the only two places where `activeSceneChanged` occurs? – Flydog57 Apr 03 '23 at 20:33
  • @Flydog57 Sorry, I generalized "type" here to describe "something". My bad. Both are `delegate void UnityEngine.Events.UnityAction(T0 Arg0, T1 Arg1)` The arguments T0 and T1 are both Scene structs. I've used VStudio's search feature to see if `activeSceneChanged` could be located anywhere else in the file. It returned nothing. Just these 2 – icecub Apr 04 '23 at 18:04
  • 1
    What version of Unity are you using? There doesn't seem to be a problem with 2021.3.15f1, where as one might expect, the `activeSceneChanged` field is private instead of public. – Michael Liu Jul 03 '23 at 19:02
  • @MichaelLiu It's a mod for the game Valheim, so I have the stick the Unity version they use. Currently they're at `2020.03.45`. During mod development, all methods have been publicized (this is needed for modding the game). HarmonyLib is used to make sure it all works (which is just reflection). – icecub Jul 03 '23 at 19:12
  • @MichaelLiu You've put me on the right path though. I have absolutely no idea why (yet), but replacing the affected DLL (UnityEngine.CoreModule) with the original from Unity solves the issue. Funny thing is, the modified DLL works perfectly fine in any other project. Just not this one.. – icecub Jul 03 '23 at 19:45
  • `Decompiled the Unity DLL file` .. why? what for? If you make a mod for something you most probably only want to decompile the project specific code and not the entire engine base – derHugo Jul 04 '23 at 11:59
  • 1
    @derHugo Well obviously if a file is giving an error and I'm not sure what causes it, I attempt to figure it out any way I can. What else was I supposed to do? Just come to Stack Overflow for help without doing my best to figure it out myself first? – icecub Jul 04 '23 at 13:17

1 Answers1

2

Normally, when a class declares an event, the C# compiler emits a public event that is backed by a private field of the same name:

[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private static UnityAction<Scene, Scene> activeSceneChanged;

public static event UnityAction<Scene, Scene> activeSceneChanged
{
    add { ... }
    remove { ... }
}

But in this case, it seems like the Unity DLL has been modded, with the accessibility of the field changed from private to public. Hence the identifier SceneManager.activeSceneChanged is now ambiguous between the event and the field.

The ideal solution to this problem is to fix the tool that modded the Unity DLL. It shouldn't change the accessibility of a field when there's an event with the same name.

In the meantime, you can reference the unmodded Unity DLL, or you can use Reflection to add your event handler:

typeof(SceneManager).GetEvent("activeSceneChanged").GetAddMethod()
    .Invoke(null, new object[] { (UnityAction<Scene, Scene>)OnSceneChanged });
Michael Liu
  • 52,147
  • 13
  • 117
  • 150
  • That really makes a lot of sense! Thank you so much for explaining that. It really helps. I'll reward the bounty when that's available. – icecub Jul 04 '23 at 05:48