using System; using System.Collections; using UnityEngine; using UnityEngine.Events; namespace Shared.ScriptableVariables { // Component to tie GameEvents to Unity's event system public class GameEventListener : MonoBehaviour { [Tooltip("The game event to listen to")] public GameEvent eventToListenTo; [Tooltip("The UnityEvent to raise in response to the game event being raised")] public UnityEvent response; [Tooltip("The delay to have before firing the Unity Events")] public float delay = 0.0f; //--------------------------------------------------------------------------- void OnEnable() { eventToListenTo.OnRaised += OnEventRaised; } //--------------------------------------------------------------------------- void OnDisable() { eventToListenTo.OnRaised -= OnEventRaised; } //--------------------------------------------------------------------------- public virtual void OnEventRaised() { // If there isn't a delay (or it's set wrong), just fire the Unity Event right away if (delay <= 0.0f) { InvokeUnityEvent(); } // Otherwise, wait for the delay and THEN fire the Unity Event else { StartCoroutine(DelayInvokeUnityEvent()); } } //--------------------------------------------------------------------------- private IEnumerator DelayInvokeUnityEvent() { yield return new WaitForSeconds(delay); InvokeUnityEvent(); } //--------------------------------------------------------------------------- private void InvokeUnityEvent() { if (response != null) { try { response.Invoke(); } catch (Exception exception) { Debug.LogError($"{gameObject.name} is throwing the following exception:"); Debug.LogException(exception); } } } } //--------------------------------------------------------------------------- public abstract class GameEventListener<T> : MonoBehaviour { [Tooltip("The delay to have before firing the Unity Events")] public float delay = 0.0f; //--------------------------------------------------------------------------- protected abstract GameEvent<T> GetGameEvent(); //--------------------------------------------------------------------------- protected abstract UnityEvent<T> GetUnityEvent(); //--------------------------------------------------------------------------- void OnEnable() { GetGameEvent().OnRaised += OnEventRaised; } //--------------------------------------------------------------------------- void OnDisable() { GetGameEvent().OnRaised -= OnEventRaised; } //--------------------------------------------------------------------------- public virtual void OnEventRaised(T value) { // If there isn't a delay (or it's set wrong), just fire the Unity Event right away if (delay <= 0.0f) { InvokeUnityEvent(value); } // Otherwise, wait for the delay and THEN fire the Unity Event else { StartCoroutine(DelayInvokeUnityEvent(value)); } } //--------------------------------------------------------------------------- private IEnumerator DelayInvokeUnityEvent(T value) { yield return new WaitForSeconds(delay); InvokeUnityEvent(value); } //--------------------------------------------------------------------------- private void InvokeUnityEvent(T value) { var unityEvent = GetUnityEvent(); if (unityEvent != null) { try { unityEvent.Invoke(value); } catch (Exception exception) { Debug.LogError($"{gameObject.name} is throwing the following exception:"); Debug.LogException(exception); } } } } }