Unity EventManager 2.0
Меня спрашивали про простой менеджер событий Unity, как передавать разные параметры и количество, а то строки неудобно. В общем-то, это был пример, но если кому-то оказалось нужно — то вот немного улучшенная версия:
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using System;
public class EventManager : MonoBehaviour {
[Serializable]
public class GameEvent : UnityEvent<object[]> { };
private static EventManager _instance;
private Dictionary<string, GameEvent> _eventDictionary;
void Awake () {
if (_instance != null)
return;
_instance = GetComponent<EventManager> ();
if (_eventDictionary == null)
_eventDictionary = new Dictionary<string, GameEvent> ();
}
/// <summary>Добавляем "слушателя" для события</summary>
/// <param name="eventName">Название события</param>
/// <param name="listener">Метод-обработчик события</param>
public static void Subscribe (string eventName, UnityAction<object[]> listener) {
GameEvent thisEvent;
if (_instance._eventDictionary.TryGetValue (eventName, out thisEvent))
thisEvent.AddListener (listener);
else {
thisEvent = new GameEvent ();
thisEvent.AddListener (listener);
_instance._eventDictionary.Add (eventName, thisEvent);
}
}
/// <summary>Удаляем "слушателя" из списка</summary>
/// <param name="eventName">Название события</param>
/// <param name="listener">Метод-обработчик события</param>
public static void Unsubscribe (string eventName, UnityAction<object[]> listener) {
if (_instance == null)
return;
GameEvent thisEvent;
if (_instance._eventDictionary.TryGetValue (eventName, out thisEvent))
thisEvent.RemoveListener (listener);
}
/// <summary>Отправить событие</summary>
/// <param name="eventName">Название события</param>
/// <param name="parameters">Параметр массив</param>
public static void SendEvent (string eventName, params object[] parameters) {
GameEvent thisEvent;
if (_instance._eventDictionary.TryGetValue (eventName, out thisEvent)) {
thisEvent.Invoke (parameters);
}
}
}
Теперь количество параметров динамическое и любого типа. Для простого взаимодействия, вполне работоспособно. Пример использования:
void OnEnable () {
EventManager.Subscribe ("event_name", MyFunction);
}
void OnDisable () {
EventManager.Unsubscribe ("event_name", MyFunction);
}
void MyFunction (object[] parameters) {
Debug.Log (parameters.Length); // количество параметров -> 3 в примере
Debug.Log (parameters[1]); // выведет -> 1
}
...
EventManager.SendEvent ("event_name", "param_string", 1, 2); // вызов события
Этот способ записи, к сожалению, вызывает гарантированный memory allocation для заворачивания параметров в массив + боксинг / анбоксинг для marshal-by-value типов. Самое правильное — создавать struct-типы с нужными полями и кидать их, ну или class-ы, но тогда думать о пулинге. Ну и пример реализации (называется eventbus) — знаешь где найти ;)
Да, я знаю, и про eventbus тоже :_)
Это же пример из обучалки Unity, просто немного модернизированный. Как и написал, «для простого взаимодействия» вполне пойдет.