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:
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:
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);
}
}