How to find the UI button gameObject calling specific function with onClick

Hi there,

I am working on a project that is fairly large, and coming in new to it, and its using the new Unity UI system. So I am trying to figure out the games logic and flow, and I come across functions in the code base that are called from UI buttons onClick event. Thing is I want to find which button is calling it, to fully understand the project I am working on, and there my issue comes up.

I have lots of buttons, and there is no way to search in the editor for that function name (ie myFunction() ) that I can see. It seems I have to click each button in the project (pain as there are lots of them), and inspect each one till I find the right button with the function specified in the onclick paramters in the inspector. This is a pain for this larger project.

So, am I missing something? Is there a way to quickly find the button via a search, that is calling my function? I know some said in IRC that maybe I could write an editor script to do this, but frankly thats also a PITA. Would be nice if this search capability was built into the editor.

Thanks,
Blake

1 Like

I don’t think there’s an easy way of doing this, but perhaps in your case even a simple list representation would help untangle the logic a bit? If so, maybe you could just make a quick MonoBehavior and print out the results, like so:

//AllOnClicks.cs
Button[] buttons = (Button[])FindObjectsOfType<Button>();
foreach(Button btn in buttons){
    int ec = btn.onClick.GetPersistentEventCount();
    Debug.LogWarning("Button " + btn + " (" + ec + " onClick delegates): ");
    for(int i=0; i<ec; i++){
        Debug.Log("onClick " + i + ": " + btn.onClick.GetPersistentTarget(i) + "." + btn.onClick.GetPersistentMethodName(i) + "()");
    }
}

Sadly I didn’t find a way to print out the inspector-assigned variables this way though.

Blake, I want to know this too - and a number of people have asked the question

Can you use reflection ?

so basically

using System.Diagnostics;
StackTrace st = new StackTrace();
Console.WriteLine(st.GetFrame(1).GetMethod().Name);

I’m back from holidays…

Blake, did you still need help with this?

It’s a little primitive, but you can search the name of the method in your scene.unity file.
For each match, search the parent GameObject → m_Name.

For example, in the following code, the GoToMenu method is bind on a button called GoBack.

2 Likes

If you know the name of the GameObject calling your method, you can just use GameObject.Find(“NameOfGameObject”), but this may not work if you have many GameObjects throughout many scenes with different names calling the same method which (would be odd indeed) in that case, you can try to pass an integer into the method that the button calls and then use a switch statement to capture the button.

If there is a way to find which GameObject called a method programmatically, I have not found that method. I’m sure finding proper docs with proper explanations would help with that but these Unity docs seem incomplete compared to other doc files I’ve sifted through (Like React docs are usually nice with examples of best practices).

1 Like
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;

public class ButtonMethodFinder : EditorWindow
{
    private string methodName = "";
    private Vector2 scrollPos;

    [MenuItem("Window/Button Method Finder")]
    public static void ShowWindow()
    {
        GetWindow<ButtonMethodFinder>("Button Method Finder");
    }

    private void OnGUI()
    {
        GUILayout.Label("Find Buttons by Method Name", EditorStyles.boldLabel);
        methodName = EditorGUILayout.TextField("Method Name", methodName);

        if (GUILayout.Button("Find Buttons"))
        {
            FindButtons();
        }

        if (buttonList != null)
        {
            scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
            foreach (var button in buttonList)
            {
                if (GUILayout.Button(button.name))
                {
                    Selection.activeGameObject = button.gameObject;
                }
            }
            EditorGUILayout.EndScrollView();
        }
    }

    private List<Button> buttonList;

    private void FindButtons()
    {
        buttonList = new List<Button>();

        foreach (var button in FindObjectsOfType<Button>())
        {
            var persistentEventCount = button.onClick.GetPersistentEventCount();
            for (int i = 0; i < persistentEventCount; i++)
            {
                var targetMethod = button.onClick.GetPersistentMethodName(i);
                if (targetMethod == methodName)
                {
                    buttonList.Add(button);
                    break;
                }
            }
        }

        if (buttonList.Count == 0)
        {
            Debug.LogWarning("No buttons found with the method name: " + methodName);
        } else
        {
            Debug.Log("Found " + buttonList.Count + " buttons with the method name: " + methodName);
        }
    }
}