Skip to content

Instantly share code, notes, and snippets.

@jackbrookes
Last active January 22, 2023 10:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jackbrookes/3efb9b2cb489f701376cbbdcf09d0713 to your computer and use it in GitHub Desktop.
Save jackbrookes/3efb9b2cb489f701376cbbdcf09d0713 to your computer and use it in GitHub Desktop.
Simple extended Unity3D Coroutine interface. Allows checking if coroutine has finished, and a method to end the Coroutine early.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// Used to test the ExtendedCoroutine interface.
public class CoroutineTest : MonoBehaviour
{
// Start is called before the first frame update
IEnumerator Start()
{
ExtendedCoroutine myRoutine = new ExtendedCoroutine(this, MoveUpOneUnit);
myRoutine.Start();
yield return new WaitUntil(() => myRoutine.completed || Input.GetKeyDown(KeyCode.Escape));
Destroy(gameObject);
}
IEnumerator MoveUpOneUnit()
{
float startTime = Time.time;
Vector3 startPos = transform.position;
Vector3 endPos = transform.position + Vector3.up;
float t;
while ((t = (Time.time - startTime) / 5f) < 1)
{
transform.position = Vector3.Lerp(startPos, endPos, t);
yield return null;
}
transform.position = endPos;
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// An extended interface to Unity's coroutines, allowing easier termination and checking the status of the coroutine.
///
/// Example usage inside a MonoBehaviour:
///
/// public IEnumerator Start()
/// {
/// ExtendedCoroutine example = new ExtendedCoroutine(this, MySequence);
///
/// // we must manually start the coroutine running
/// example.Start();
///
/// // completed status
/// Debug.Log(example.completed);
///
/// // terminate early
/// example.Stop();
///
/// // we can start it again from the beginning
/// example.Start();
///
/// // checking for completion can be used for more complex coroutine behaviour
/// yield return new WaitUntil(() => example.completed || Input.GetKeyDown(KeyCode.Escape));
/// }
///
///
/// IEnumerator MySequence()
/// {
/// // do something
/// yield return new WaitForSeconds(1f);
/// }
///
/// </summary>
public class ExtendedCoroutine
{
public bool completed { get; private set; }
public MonoBehaviour source { get; private set; }
public Func<IEnumerator> routineFunction { get; private set; }
public Coroutine runningRoutine { get; private set; }
public ExtendedCoroutine(MonoBehaviour source, Func<IEnumerator> routineFunction)
{
this.completed = false;
this.source = source;
this.routineFunction = routineFunction;
}
/// <summary>
/// Start a new coroutine
/// </summary>
public void Start()
{
if (runningRoutine != null) source.StopCoroutine(runningRoutine);
runningRoutine = source.StartCoroutine(RunSequence());
}
public void Stop()
{
if (runningRoutine != null) source.StopCoroutine(runningRoutine);
runningRoutine = null;
completed = false;
}
IEnumerator RunSequence()
{
yield return routineFunction.Invoke();
completed = true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment