Coroutineの挙動が不信だったので調べてみたのでメモ。
当初の状況
あれ?yield return www;してるからwwwインスタンスがデータ取得してからでないと次進まないはず
にも関わらずwww.textよめねーぞって怒られる。なんでだ…?
Reset()もできずハマる。
今回の問題点と目的
- coroutineはStopCortoutineした後に同じメソッドをStartCoroutineするとStopしたところから再開するんじゃ?疑惑の解消
- Start/Stopの動きを先ず確認
- 進む原因は?
ダメなソース
using UnityEngine; using System.Collections; public class coroutine : MonoBehaviour { // Use this for initialization IEnumerator Start () { StartCoroutine(Test()); Debug.Log("StartCoroutine 1"); yield return new WaitForSeconds(2f); StopCoroutine("Test"); Debug.Log("StopCoroutine"); yield return new WaitForSeconds(2f); StartCoroutine(Test()); Debug.Log("StartCoroutine 2"); } IEnumerator Test() { Debug.Log("Test Start"); yield return new WaitForSeconds(1f); Debug.Log("1 second"); yield return new WaitForSeconds(1f); Debug.Log("2 second"); yield return new WaitForSeconds(1f); Debug.Log("3 second"); yield return new WaitForSeconds(1f); Debug.Log("4 second"); yield return new WaitForSeconds(1f); Debug.Log("5 second"); Debug.Log("Test End"); } // Update is called once per frame void Update () { } }
結果
コンソールにはこんな表示が。
StopCoroutine()した後も元気に走り続けるTest()の姿が!
原因は、文字列ではなくハンドラを直接StartCoroutine()に渡していた事。
StopCoroutine()は文字列で受取った指定のCoroutineしか参照できず、あたかも処理を完遂したかの様にエラーも出さなきゃ警告も出ない。
修正
using UnityEngine; using System.Collections; using System.Collections.Generic; public class coroutine : MonoBehaviour { // Use this for initialization IEnumerator Start () { StartCoroutine("Test"); Debug.Log("StartCoroutine 1"); yield return new WaitForSeconds(2f); StopCoroutine("Test"); Debug.Log("StopCoroutine"); yield return new WaitForSeconds(2f); StartCoroutine("Test"); Debug.Log("StartCoroutine 2"); } IEnumerator Test() { Debug.Log("Test Start"); yield return new WaitForSeconds(1f); Debug.Log("1 second"); yield return new WaitForSeconds(1f); Debug.Log("2 second"); yield return new WaitForSeconds(1f); Debug.Log("3 second"); yield return new WaitForSeconds(1f); Debug.Log("4 second"); yield return new WaitForSeconds(1f); Debug.Log("5 second"); Debug.Log("Test End"); } // Update is called once per frame void Update () { } }
これだと以下のように動く。
ちゃんとStopCoroutineで止まってくれた。
そして疑惑だった途中再開もされていない。文字列で指定すればStopCoroutine()もちゃんと機能するということも分かった。
おまけ
- Startが今回のサンプルの様にIEnumeratorを返すタイプなのにStopAllCoroutines()をするとStartまで止めてしまうので注意。
- Resetは必要無い。
- IEnumeratorにparameterを渡す場合は第二引数に入れて上げれば機能する。
参考にしました
StartCoroutineを文字列でやらないとStopCoroutineが効かないのですね?
では、StartCoroutineに引数付きのを実行したときはうつすべがないのでしょうか。
shinriyo さん
こんにちは。コメント有難うございます。
引数付きで文字列指定のハンドラStartCoroutineに渡すには、第二引数以降のパラメータとして実行することで可能です。
IEnumerator Start(){
StartCoroutine(“Test”,1);
yield return new WaitForSeconds(1f);
StopCoroutine(“Test”);
}
IEnumerator Test(int i){
Debug.Log(“TestStartWith:”+i);
yield return new WaitForSeconds(2f);
Debug.Log(“TestEndWith:”+i);
}
ご返信確認するのが遅くなってしまいましたが、ありがとうございます。