Scriptable Object EventSystem

// ScriptableObject Event System // Each ScriptableObject acts as an event stream // Provides a button when inspecting the SO to "raise" the event // The SO can be placed in UnityEvent callbacks to easily "raise" them by calling the "raise" function // Also included is a EventListening component for applying event responses // if not plugging into an external system //////////////// // Interfaces.cs using System; using System.Collections.Generic; public interface IEventListener { void OnEventRaised(T payload); } public interface IEvent { List> EventListeners { get; } void Raise(T payload); } ///////////////// // StringEvent.cs using System; using UnityEngine; using Sirenix.OdinInspector; [CreateAssetMenu(menuName = "Events/GameEvent")] public class StringEvent   : GenericEvent { [DisableInEditorMode] public string payload; [Button, DisableInEditorMode] public void Raise {         Raise(payload); }  }   //////////////////   // GenericEvent.cs   using System; using System.Collections.Generic; using UnityEngine; using Sirenix.OdinInspector; public abstract class GenericEvent  : ScriptableObject, IEvent {   [SerializeField] List> _eventListeners = new List>; [ShowInInspector] public List> EventListeners {         get { return _eventListeners; } }     public bool DebugLog = false; public void Raise(T payload) {         if (DebugLog) {             Debug.LogFormat("Begin Event Raise for {0}", this); }         for (int i = EventListeners.Count - 1; i >= 0; i--) {             if (DebugLog) {                 Debug.LogFormat("\tCalling {0}", EventListeners[i]); }             EventListeners[i].OnEventRaised(payload); }      }      public override string ToString {         return string.Format("Event_{0}<{1}>", name, typeof(T)); }  }   //////////////////////////   // GenericEventListener.cs   using System; using UnityEngine; using Sirenix.OdinInspector; public abstract class GenericEventListener  : MonoBehaviour, IEventListener  where T : IEvent {     [ShowInInspector] public T Event; private void OnEnable {         if (!Event.EventListeners.Contains(this)) Event.EventListeners.Add(this); }     private void OnDisable {         if (Event.EventListeners.Contains(this)) Event.EventListeners.Remove(this); }     public virtual void OnEventRaised(U payload) {} public override String ToString {         return String.Format("Listener_{0}<{1}>", gameObject.name, typeof(T)); }  }   ///////////////////////   // EchoEventListener.cs   using System; using UnityEngine; public class EchoEventListener  : GenericEventListener {   public override void OnEventRaised(string payload) {         Debug.Log(payload); }  }