Skip to content

Instantly share code, notes, and snippets.

@qwe321qwe321qwe321
Last active July 10, 2020 04:38
Show Gist options
  • Save qwe321qwe321qwe321/958c405524dbad0a12aa06589936d52e to your computer and use it in GitHub Desktop.
Save qwe321qwe321qwe321/958c405524dbad0a12aa06589936d52e to your computer and use it in GitHub Desktop.
BetterCoroutine is a wrapper of UnityEngine.Coroutine to make it safe and convenience. It provides a better approach to access and maintain the coroutine status and lifecycle.
/*
* BetterCoroutine is a wrapper of UnityEngine.Coroutine.
* It provides a better approach to access and maintain the coroutine status and lifecycle.
* Created by PeDev 2020 https://gist.github.com/qwe321qwe321qwe321/958c405524dbad0a12aa06589936d52e
*/
using System.Collections;
using UnityEngine;
namespace Pedev {
/// <summary>
/// The Coroutine wrapper provides a better approach to maintain the coroutine status and lifecycle.
/// </summary>
public class BetterCoroutine {
private Coroutine m_Coroutine;
private MonoBehaviour m_MonoProxy;
/// <summary>
/// Is the coroutine running?
/// </summary>
public bool IsRunning { get => m_Coroutine != null; }
/// <summary>
/// Create a new BetterCoroutine with the specific MonoBehaviour proxy and run the specific routine.
/// </summary>
/// <param name="monoProxy">The MonoBehaviour as a proxy for running coroutine.</param>
public static BetterCoroutine StartCoroutine(MonoBehaviour monoProxy, IEnumerator routine) {
BetterCoroutine coroutine = new BetterCoroutine(monoProxy);
coroutine.StartCoroutine(routine);
return coroutine;
}
/// <summary>
/// The Coroutine wrapper provides a better approach to maintain the coroutine status and lifecycle.
/// </summary>
/// <param name="monoProxy">The MonoBehaviour as a proxy for running coroutine.</param>
public BetterCoroutine(MonoBehaviour monoProxy) {
m_MonoProxy = monoProxy;
}
/// <summary>
/// Start a coroutine.
/// </summary>
/// <param name="routine"></param>
public void StartCoroutine(IEnumerator routine) {
if (!ValidateMono()) { return; }
StopCoroutine();
m_Coroutine = m_MonoProxy.StartCoroutine(RoutineWrapper(routine));
}
/// <summary>
/// Stop the running coroutine.
/// </summary>
public void StopCoroutine() {
if (!ValidateMono()) { return; }
if (m_Coroutine != null) {
m_MonoProxy.StopCoroutine(m_Coroutine);
m_Coroutine = null;
}
}
/// <summary>
/// Wrap the routine to set callbacks.
/// </summary>
/// <param name="routine"></param>
/// <returns></returns>
private IEnumerator RoutineWrapper(IEnumerator routine) {
yield return routine;
m_Coroutine = null;
}
/// <summary>
/// Validate the mono proxy is still alive.
/// </summary>
/// <returns></returns>
private bool ValidateMono() {
return m_MonoProxy != null;
}
}
}
using System.Collections;
using UnityEngine;
namespace Pedev {
/// <summary>
/// A simple example to moving this gameObject in the specific duration by BetterCoroutine.
/// </summary>
public class BetterCoroutineExample : MonoBehaviour {
public Vector3 movement = new Vector3(5f, 0, 0);
public float moveDuration = 3f;
private BetterCoroutine m_Coroutine;
// Initialize my components.
void Awake() {
m_Coroutine = new BetterCoroutine(this);
}
// Initialize my connections to others.
void OnGUI() {
if (GUI.Button(new Rect(10, 10, 300, 100), $"Move {movement} in {moveDuration} seconds")) {
// You can call it whenever you want. It will stop the first one immediately and restart it again.
// Therefore, you don't need to be worried about the coroutine safety.
m_Coroutine.StartCoroutine(Move(this.transform.position + movement, moveDuration));
}
// And you can check if the coroutine is running without declaring any variables.
GUI.Label(new Rect(10, 110, 300, 100), m_Coroutine.IsRunning ? "Coroutine is running." : "Coroutine stop.");
}
IEnumerator Move(Vector3 targetPosition, float duration) {
Vector3 src = transform.position;
float time = 0f;
while(time < duration) {
transform.position = Vector3.Lerp(src, targetPosition, time / duration);
time += Time.deltaTime;
yield return null;
}
transform.position = targetPosition;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment