Created
January 24, 2014 20:48
-
-
Save Jerdak/8606110 to your computer and use it in GitHub Desktop.
Incomplete example of how to track Unity coroutines.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
/// <summary> | |
/// Coroutine tracker. | |
/// | |
/// Custom handler for coroutines that tracks when they start and stop... | |
/// Uses Singleton class from: http://wiki.unity3d.com/index.php/Singleton | |
/// </summary> | |
public class CoroutineTracker : Singleton<CoroutineTracker> { | |
Dictionary<string,int> CoroutineInstanceMap = new Dictionary<string, int>(); | |
/// <summary> | |
/// Hideous hack to wrap Monobehaviour.StartCoroutine | |
/// | |
/// Non-virtual methods cannot be overridden so use method-hiding | |
/// to allow the use of method name `StartCoroutine`. Know that | |
/// this is an awful hack that screws up polymorphism. | |
/// | |
/// Seriously, don't blame me when someone hates on you for | |
/// using method-hiding and a Singleton in the same class | |
/// | |
/// Ref: http://stackoverflow.com/questions/1853896/is-it-possible-to-override-a-non-virtual-method | |
/// </summary> | |
public new void StartCoroutine(IEnumerator routine){ | |
var key = routine.ToString (); | |
if (!CoroutineInstanceMap.ContainsKey (key)) { | |
CoroutineInstanceMap[key] = 0; | |
} | |
CoroutineInstanceMap [key] += 1; | |
// all routines must be wrapped in a decrementer that updates CoroutineInstanceMap | |
base.StartCoroutine (DecrementRoutine(routine)); | |
} | |
/// <summary> | |
/// Dump all instance counts to command line | |
/// </summary> | |
public void DumpRunningInstances(){ | |
foreach (var kvp in CoroutineInstanceMap) { | |
var key = kvp.Key; | |
Debug.Log (string.Format("{0} instances of {1} running", | |
CoroutineInstanceMap [key], | |
key)); | |
} | |
} | |
/// <summary> | |
/// Remove coroutine instance from map, clears key from the map if # instances are zero | |
/// </summary> | |
IEnumerator DecrementRoutine(IEnumerator routine){ | |
var key = routine.ToString (); | |
yield return base.StartCoroutine (routine); | |
CoroutineInstanceMap [key] -= 1; | |
Debug.Log (string.Format("Instance stopped, {0} instances of {1} running", | |
CoroutineInstanceMap [key], | |
key)); | |
if (CoroutineInstanceMap [key] == 0) { | |
Debug.Log (string.Format("No more instances of {0} running",key)); | |
CoroutineInstanceMap.Remove (key); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class ExampleCoroutines : MonoBehaviour { | |
// Use this for initialization | |
void Start () { | |
CoroutineTracker.Instance.StartCoroutine (WaitAndMove (2.0f)); | |
CoroutineTracker.Instance.StartCoroutine (WaitAndMove (3.0f)); | |
CoroutineTracker.Instance.StartCoroutine (WaitAndMove (4.0f)); | |
CoroutineTracker.Instance.StartCoroutine (WaitAndMove (5.0f)); | |
CoroutineTracker.Instance.StartCoroutine (WaitAndMove (6.0f)); | |
CoroutineTracker.Instance.DumpRunningInstances (); | |
} | |
IEnumerator WaitAndMove(float waitTime) { | |
yield return new WaitForSeconds(waitTime); | |
Vector3 position = transform.position; | |
position.y += 1; | |
transform.position = position; | |
print("WaitAndMove " + Time.time); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Original Source: http://wiki.unity3d.com/index.php/Singleton | |
/// License: Creative Commons | |
using UnityEngine; | |
/// <summary> | |
/// Be aware this will not prevent a non singleton constructor | |
/// such as `T myT = new T();` | |
/// To prevent that, add `protected T () {}` to your singleton class. | |
/// | |
/// As a note, this is made as MonoBehaviour because we need Coroutines. | |
/// </summary> | |
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour | |
{ | |
private static T _instance; | |
private static object _lock = new object(); | |
public static T Instance | |
{ | |
get | |
{ | |
if (applicationIsQuitting) { | |
Debug.LogWarning("[Singleton] Instance '"+ typeof(T) + | |
"' already destroyed on application quit." + | |
" Won't create again - returning null."); | |
return null; | |
} | |
lock(_lock) | |
{ | |
if (_instance == null) | |
{ | |
_instance = (T) FindObjectOfType(typeof(T)); | |
if ( FindObjectsOfType(typeof(T)).Length > 1 ) | |
{ | |
Debug.LogError("[Singleton] Something went really wrong " + | |
" - there should never be more than 1 singleton!" + | |
" Reopenning the scene might fix it."); | |
return _instance; | |
} | |
if (_instance == null) | |
{ | |
GameObject singleton = new GameObject(); | |
_instance = singleton.AddComponent<T>(); | |
singleton.name = "(singleton) "+ typeof(T).ToString(); | |
DontDestroyOnLoad(singleton); | |
Debug.Log("[Singleton] An instance of " + typeof(T) + | |
" is needed in the scene, so '" + singleton + | |
"' was created with DontDestroyOnLoad."); | |
} else { | |
Debug.Log("[Singleton] Using instance already created: " + | |
_instance.gameObject.name); | |
} | |
} | |
return _instance; | |
} | |
} | |
} | |
private static bool applicationIsQuitting = false; | |
/// <summary> | |
/// When Unity quits, it destroys objects in a random order. | |
/// In principle, a Singleton is only destroyed when application quits. | |
/// If any script calls Instance after it have been destroyed, | |
/// it will create a buggy ghost object that will stay on the Editor scene | |
/// even after stopping playing the Application. Really bad! | |
/// So, this was made to be sure we're not creating that buggy ghost object. | |
/// </summary> | |
public void OnDestroy () { | |
applicationIsQuitting = true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment