-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial Connecting Reconstructed Logic to UnityEvents
One of the biggest surprises when working with IL2CPP decompilations is that 100% of serialized event data survives.
When a designer sets up a button click or an interaction trigger in the Unity Inspector using UnityEvent, Unity saves the target object, method name, and arguments into the scene or prefab YAML file. Even though the C# code behind those methods was stripped during IL2CPP compilation, the YAML files still remember every call chain.
This guide explains how to read serialized UnityEvent graphs, inspect target calls, and make sure your reconstructed C# components plug into existing scene wiring.
Open any decompiled .unity scene file or .prefab file in a text editor and search for m_PersistentCalls. You will see blocks that look like this:
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 11500000, guid: a1b2c3d4e5f67890a1b2c3d4e5f67890, type: 3}
m_TargetAssemblyTypeName: Menu, Assembly-CSharp
m_MethodName: OpenPanel
m_Mode: 5
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument: Panel_Settings
m_BoolArgument: 0
m_CallState: 2Here is what each field means:
-
m_TargetAssemblyTypeName: The class holding the method (e.g.Menu). -
m_MethodName: The exact method name invoked when the event fires (e.g.OpenPanel). -
m_Mode: Parameter mode (0= Void/No args,1= Int,2= Float,3= String,4= Object,5= EventDefined). -
m_StringArgument: The string parameter passed to the method (e.g."Panel_Settings").
In the MiSide port, the main menu carried 108 ButtonMouseClick components, 84 of which had wired event handlers and 20 with scene-loading calls.
Because the scene YAML file retains all 84 event chains intact, you do not have to rewrite the actions that happen when buttons are clicked. You only need to write the minimal wrapper that receives UI clicks and calls eventClick.Invoke().
Once eventClick.Invoke() runs, Unity's built-in event engine executes the entire original event chain—triggering scene loads, opening panels, changing settings, and toggling GameObjects.
When you rebuild a component that uses UnityEvent, your replacement C# class must match three things so Unity can deserialize it correctly:
-
Same Class Name: Must match the original script name (e.g.
ButtonMouseClick). -
Same Field Names: The
UnityEventfields must match the original variable names in C# (e.g.public UnityEvent eventClick;). -
Same Method Signatures: Any target method called by an event in YAML (e.g.
public void OpenPanel(string panelName)) must exist with the exact same name and parameter type.
Suppose a door object in Scene 2 - InGame has a 23-call UnityEvent chain attached to an ObjectInteractive script.
Looking at the scene YAML, we see the interaction event calls:
Animator.SetTrigger("OpenDoor")AudioSource.Play()ObjectAnimationPlayer.AnimationPlay()
To get this whole chain working, your replacement ObjectInteractive script only needs to fire its onClick event when the player looks at the object and presses the interaction key:
using UnityEngine;
using UnityEngine.Events;
public class ObjectInteractive : MonoBehaviour
{
public UnityEvent onClick;
// Called by PlayerMove raycast when player presses Use key
public void Click()
{
if (onClick != null)
{
onClick.Invoke(); // Fires the original 23-call chain from the scene YAML
}
}
}You didn't have to code the door opening, animation triggering, or audio playback. As long as Click() calls onClick.Invoke(), Unity handles the rest.
- Search scene/prefab YAML for
m_PersistentCallsto see what methods the scene expects to call. - Ensure your reconstructed C# script defines public
UnityEventfields with matching names. - Ensure methods called by events (like
OpenPanel(string)) have matching public signatures. - Run
tools/remap-ugui.pyto fix synthetic script GUIDs so uGUI components link to Unity's native package scripts instead of missing script placeholders.