Skip to content

Instantly share code, notes, and snippets.

@FlaShG
Last active August 17, 2023 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FlaShG/c7bd1a76dd46e2085f51afb8735afdad to your computer and use it in GitHub Desktop.
Save FlaShG/c7bd1a76dd46e2085f51afb8735afdad to your computer and use it in GitHub Desktop.
An event class for Unity that can run coroutines.
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// An event that can run coroutines.
/// Invoking it returns an IEnumerator that can be waited for in another coroutine.
/// The Invocation waits until all registered coroutines are finished.
/// </summary>
public class CoroutineEvent
{
private readonly List<Action> directResponses = new List<Action>();
private readonly List<Func<IEnumerator>> coroutines = new List<Func<IEnumerator>>();
private readonly List<Coroutine> runningCoroutines = new List<Coroutine>();
public void AddResponse(Action response)
{
directResponses.Add(response);
}
public void AddResponse(Func<IEnumerator> coroutine)
{
coroutines.Add(coroutine);
}
public void RemoveResponse(Action response)
{
directResponses.Remove(response);
}
public void RemoveResponse(Func<IEnumerator> coroutine)
{
coroutines.Remove(coroutine);
}
public IEnumerator Invoke()
{
foreach (var response in directResponses)
{
try
{
response.Invoke();
}
catch (Exception exception)
{
Debug.LogException(exception);
}
}
foreach (var coroutine in coroutines)
{
try
{
runningCoroutines.Add(GlobalCoroutineService.StartCoroutine(coroutine()));
}
catch (Exception exception)
{
Debug.LogException(exception);
}
}
try
{
foreach (var coroutine in runningCoroutines)
{
yield return coroutine;
}
}
finally
{
runningCoroutines.Clear();
}
}
}
public readonly CoroutineEvent onStart = new CoroutineEvent();
private void Start()
{
// It's of course way more interesting to allow other components to add their events here
onStart.AddResponse(DoStuff);
onStart.AddResponse(DoMoreStuff);
StartCoroutine(RunStart());
}
private IEnumerator RunStart()
{
yield return onStart.Invoke();
Debug.Log("OnStart is finished, I can do other things now");
}
private IEnumerator DoStuff()
{
// ...
}
private IEnumerator DoMoreStuff()
{
// ...
}
using UnityEngine;
using System.Collections;
/// <summary>
/// A simple global service for running coroutines.
/// </summary>
public static class GlobalCoroutineService
{
private class Worker : MonoBehaviour
{
}
private static Worker worker;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Initialize()
{
var gameObject = new GameObject("Global Coroutine Worker");
worker = gameObject.AddComponent<Worker>();
Object.DontDestroyOnLoad(gameObject);
gameObject.HideFlags = HideFlags.HideAndDontSave;
}
public static Coroutine StartCoroutine(IEnumerator coroutine)
{
return worker.StartCoroutine(coroutine);
}
public static void StopCoroutine(Coroutine coroutine)
{
worker.StopCoroutine(coroutine);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment