Skip to content

Instantly share code, notes, and snippets.

@bfollington
Last active August 30, 2023 14:21
Show Gist options
  • Save bfollington/39aa48eb09dc904c7636a6c676b98a1c to your computer and use it in GitHub Desktop.
Save bfollington/39aa48eb09dc904c7636a6c676b98a1c to your computer and use it in GitHub Desktop.
EventManager messaging layer designed for Unity
using System.ComponentModel.Design;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using System.Linq;
namespace Events
{
public class Disposer<T> : IDisposable
{
private EventManager _eventManager;
private Action<T> _listener;
public Disposer(EventManager em, Action<T> listener) {
_eventManager = em;
_listener = listener;
}
public void Dispose()
{
_eventManager.RemoveListener<T>(_listener);
}
}
public class EventManager
{
private ServiceContainer _serviceContainer;
private IList<Action> _pendingActions;
private int _isDispatching = 0;
public EventManager() {
_serviceContainer = new ServiceContainer();
_pendingActions = new List<Action>();
}
private IList<Action<T>> GetListenerList<T>() {
return _serviceContainer.GetService(typeof(IList<Action<T>>)) as IList<Action<T>>;
}
public Disposer<T> AddListener<T>(Action<T> action) {
var disposer = new Disposer<T>(this, action);
var listenerList = GetListenerList<T>();
if (listenerList == null) {
_serviceContainer.AddService(typeof(IList<Action<T>>), new List<Action<T>>());
listenerList = GetListenerList<T>();
}
if (_isDispatching > 0) {
_pendingActions.Add(() => listenerList.Add(action));
} else {
listenerList.Add(action);
}
return disposer;
}
public void RemoveListener<T>(Action<T> action) {
var listenerList = GetListenerList<T>();
if (listenerList != null) {
if (_isDispatching > 0) {
_pendingActions.Add(() => listenerList.Remove(action));
} else {
listenerList.Remove(action);
}
}
}
private void RunPendingActions() {
foreach (var action in _pendingActions) {
action.Invoke();
}
_pendingActions.Clear();
}
public bool Dispatch<T>() {
return Dispatch<T>(default(T));
}
public bool Dispatch<T>(T eventData) {
var listenerList = GetListenerList<T>();
if (eventData != null) {
Debug.Log($"{eventData.GetType().ToString()}: {eventData.ToString()}");
} else {
Debug.Log($"{typeof(T).Name}");
}
if (_isDispatching == 0) {
RunPendingActions();
}
if (listenerList != null && listenerList.Count > 0) {
_isDispatching++;
foreach (var listener in listenerList)
{
listener.Invoke(eventData);
}
_isDispatching--;
return true;
}
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment