Adding multiple methods to OnClick event

I am trying to call multiple methods from a single button OnClick event based on a list of actions I am looping through, and I’m not sure exactly how to handle it. I’ve tried this method, but it is adding 3 listeners which all call the last method that I loop over:

string method, arguments;
Button btn = dialogButton.GetComponent<Button>();

foreach(DialogAction dialogAction in option.actions){
	method = dialogAction.method;
	arguments = dialogAction.arguments;
	btn.onClick.AddListener(() => { ExposeMethod(method,arguments); });
}

Very sorry if this is a duplicate issue, I couldn’t find anything quite like this.

You are facing a problem called “Closure”. It’s quite annoying, and I know the feel when you absolutely don’t understand when it happens. Here is some litterature :

Personally I like to decentralize the events so parameters and multiple events can be passed. A custom static event handling class lets you add and remove your own handlers and broadcast when they should be called with a fixed number of generic parameters. This is the way you might use it in your code:

btn.onClick.AddListener(() => { EventManager.Broadcast<string, string>( EVNT.Button1, method, arguments); });

The implementation for this involves a static class that essentially just executes a single delegate based on the event enum. This is the class used (although you can definitely find other examples of messenger classes online):

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public enum EVNT { MyEvent1, MyEvent2, MyEvent3, Button1 };
public static class EventManager {

    private static Dictionary<EVNT, Delegate> eventTable = new Dictionary<EVNT, Delegate>();


    public static void AddHandler(EVNT evnt, Action action)
    {
        if (!eventTable.ContainsKey(evnt)) eventTable[evnt] = action;
        else eventTable[evnt] = (Action)eventTable[evnt] + action;
    }

	public static void AddHandler<T>(EVNT evnt, Action<T> action)
    {
        if (!eventTable.ContainsKey(evnt)) eventTable[evnt] = action;
        else eventTable[evnt] = (Action<T>)eventTable[evnt] + action;
    }

    public static void AddHandler<T, U>(EVNT evnt, Action<T, U> action)
    {
        if (!eventTable.ContainsKey(evnt)) eventTable[evnt] = action;
        else eventTable[evnt] = (Action<T, U>)eventTable[evnt] + action;
    }

    public static void Broadcast(EVNT evnt)
    {
        Delegate d;
        if (eventTable.TryGetValue(evnt, out d))
        {
            Action action = d as Action;
            if (action != null) action();
        }
    }

    public static void Broadcast<T>(EVNT evnt, T param)
    {
        Delegate d;
        if (eventTable.TryGetValue(evnt, out d))
        {
            Action<T> action = d as Action<T>;
            if (action != null) action(param);
        }
    }

    public static void Broadcast<T, U>(EVNT evnt, T param, U param2)
    {
        Delegate d;
        if (eventTable.TryGetValue(evnt, out d))
        {
            Action<T, U> action = d as Action<T, U>;
            if (action != null) action(param, param2);
        }
    }

    public static void RemoveHandler(EVNT evnt, Action action)
    {
        if(eventTable[evnt] != null)
            eventTable[evnt] = (Action)eventTable[evnt] - action;
        if (eventTable[evnt] == null)
            eventTable.Remove(evnt);
    }

    public static void RemoveHandler<T>(EVNT evnt, Action<T> action)
    {
        if (eventTable[evnt] != null)
            eventTable[evnt] = (Action<T>)eventTable[evnt] - action;
        if (eventTable[evnt] == null)
            eventTable.Remove(evnt);
    }

    public static void RemoveHandler<T, U>(EVNT evnt, Action<T, U> action)
    {
        if (eventTable[evnt] != null)
            eventTable[evnt] = (Action<T, U>)eventTable[evnt] - action;
        if (eventTable[evnt] == null)
            eventTable.Remove(evnt);
    }
}

Button butYes = GameObject.Find(“ButtonYes”).GetComponent();

butYes.onClick.AddListener(() => Method1());
butYes.onClick.AddListener(() => Method2("Variable1"));