Giovarco
Giovarco

Reputation: 63

Unity EventManager that also supports coroutine

I'm looking for a C# EventManager like this one that supports coroutine execution. In other words, I would like to be able to do something like:

EventManager.StartListening("AString", ACoroutine);

I know I could wrap my coroutine in a function and use the current version of the code, but it would be better if the code itself supported this to avoid dirty code.

Upvotes: 0

Views: 544

Answers (1)

Everts
Everts

Reputation: 10701

You can wrap your coroutine in a normal method so you can use the existing code:

private IEnumerator coroutine = null;
void AMethod()
{
     if(this.coroutine != null){ return; } // Already running
     this.coroutine = ACoroutine();
     StartCoroutine(this.coroutine);
}

private IEnumerator ACoroutine()
{
      yield return null;
      this.coroutine = null;
}

void Start()
{
     EventManager.StartListening("AString", AMethod);
}

EDIT: Here is the system supporting coroutine. It has to adopt a slight different process(or at least I did not dig into it) so instead of calling an event of the type, you create a list of the type. This is because your StartCoroutine cannot call multiple delegates and requires iterations.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EventManager : MonoBehaviour
{
    private Dictionary<string, List<Func<IEnumerator>>> eventDictionary;

    private static EventManager eventManager;

    public static EventManager instance
    {
        get
        {
            if (!eventManager)
            {
                eventManager = FindObjectOfType(typeof(EventManager)) as EventManager;

                if (!eventManager)
                {
                    Debug.LogError("There needs to be one active EventManger script on a GameObject in your scene.");
                }
                else
                {
                    eventManager.Init();
                }
            }
            return eventManager;
        }
    }
    void Init()
    {
        if (eventDictionary == null)
        {
            eventDictionary = new Dictionary<string, List<Func<IEnumerator>>>();
        }
    }
    public void StartListening(string eventName, Func<IEnumerator> listener)
    {
        List<Func<IEnumerator>> thisEvent;
        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.Add(listener);
        }
        else
        {
            instance.eventDictionary.Add(eventName, new List<Func<IEnumerator>>() { listener });
        }
    }

    public void StopListening(string eventName, Func<IEnumerator> listener)
    {
        if (eventManager == null) return;
        List<Func<IEnumerator>> thisEvent;
        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            thisEvent.Remove(listener);
        }
    }

    public void TriggerEvent(string eventName)
    {

        List<Func<IEnumerator>> thisEvent = null;
        if (instance.eventDictionary.TryGetValue(eventName, out thisEvent))
        {
            for (int i = thisEvent.Count -1 ; i >= 0; i--)
            {
                if(thisEvent[i] == null)
                { 
                     thisEvent.RemoveAt(i);
                     continue; 
                }
                StartCoroutine(thisEvent[i]());
            }
        }
    }
}

Upvotes: 1

Related Questions