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);
}
ご返信確認するのが遅くなってしまいましたが、ありがとうございます。