前提・実現したいこと
呼び出したコルーチンが終了したら、再びそのコルーチンが開始されるように無限ループさせるには、どのように実装すればよいでしょうか。
1つのコルーチンをコルーチン内で無限にループさせるのではなく、1つのコルーチンの処理を一連の処理として、
そのコルーチンの呼び出しを無限にループさせる方法(一連の処理を無限に繰り返す方法)について考えています。
また、可能であれば、試したことで試みているように、
ループし続ける(呼び出され続ける)コルーチンと、ループさせ続ける(呼び出しを実行し続ける)コルーチンを別に分け、
ループし続けるコルーチンのほうは、引数で汎用的にセットできるようにしたいと思っています。
さらに、コルーチンの一時停止や、コルーチンの終了方法や再開についても考えています。
ご教示お願いします
試したこと
・質問1。
C#
1 void Start (){ 2 StartCoroutine(LoopCoroutine(MyCoroutine(3f))); 3 } 4 5 IEnumerator LoopCoroutine(IEnumerator coroutine){ 6 while(true){ 7 yield return coroutine; 8 Debug.Log("while"); 9 } 10 } 11 12 IEnumerator MyCoroutine(float animationLength){ 13 14 Debug.Log("MyCoroutine:開始"); 15 for (float time = 0.0f; time < animationLength; time += Time.deltaTime) 16 { 17 yield return null; 18 } 19 Debug.Log("MyCoroutine:終了"); 20 }
上記のように実装してみたのですが、最初だけMyCoroutineが動いているような挙動を示し、
それ以降はMyCoroutineがスキップされてwhile文でループし続けるような挙動となりました。
以下のようなログとなりました。なぜ、MyCoroutineは1回だけしか動かないのでしょうか。
MyCoroutine:開始 MyCoroutine:終了 while while while while while while
・質問2。
コルーチンの停止と終了は、どちらもStopCoroutine()で合っていますか?
StopCoroutine()で停止したコルーチンは、破棄されるという認識で合っていますか?
StopCoroutine()で停止したコルーチンは破棄されるけど、StartCoroutineで再開すると、
停止した箇所から再開されるという認識で合っていますか?
リファレンスには、StopCoroutineに関する、停止・破棄・再開に関する説明は書かれていませんでした。
・質問3。
質問1がわからない状態ですが、コルーチンの無限呼び出しに開始・停止・終了処理の操作ができるようにしたいと
思い、以下の実装を考えてみました。
質問1では、無限に呼び出すコルーチンを汎用的に引数でセットしたいと考えていましたが、
コルーチンの多重起動防止のnullチェックを考えると、そのフラグをフィールドで持たせるしかなさそうなので、
汎用的に無限に呼び出すコルーチンをセットすることは不可能になりそうと考えました(仮に可能であれば教えていただきたいです)。
これより、目的を妥協し、特定のコルーチンの無限呼び出しの開始・停止・終了ができるように以下のように
組みました。ただ、ゲームを再生してみると、
①左クリックで「開始」のログが出ることを確認する。
②右クリックで、「終了」のログが出る前に停止する。
③再び、左クリックすると、「開始」のログが出力される。
という挙動になり、③が意図しない挙動となりました。
本来であれば、②で停止しているので、③では再開に該当し、「終了」のログが出るはずと予想していたのですが、
「開始」のログが出力されてしまいます。
質問2にも関連してきますが、こちらの記事の「コルーチンの一時停止」の説明ににもあるように、
StopCoroutineしたコルーチンを、StartCoroutineすると再開されると思っていたのですが、違うのでしょうか?
また、質問1が未解決の為、検証できてないのですが、
StopCoroutine(myLoopCoroutine)で、中で動かしているMyCoroutineの方も停止できていますか?
MyCoroutineの方までは停止できなかった場合、どのような実装で停止できますか?
C#
1 Coroutine myLoopCoroutine; 2 3 void Start (){ 4 5 } 6 7 void Update(){ 8 if (Input.GetMouseButton(0)){ 9 StartLoopCoroutine(2f); 10 } 11 if (Input.GetMouseButton(1)){ 12 StopLoopCoroutine(); 13 } 14 } 15 16 void StartLoopCoroutine(float second){ 17 if (myLoopCoroutine == null){ 18 myLoopCoroutine = StartCoroutine(LoopCoroutine(MyCoroutine(second))); 19 } 20 } 21 22 void StopLoopCoroutine(){ 23 if (myLoopCoroutine != null){ 24 StopCoroutine(myLoopCoroutine); 25 myLoopCoroutine = null; 26 } 27 } 28 29 30 IEnumerator LoopCoroutine(IEnumerator coroutine){ 31 while(true){ 32 yield return coroutine; 33 Debug.Log("while"); 34 } 35 } 36 37 IEnumerator MyCoroutine(float animationLength){ 38 39 Debug.Log("MyCoroutine:開始"); 40 for (float time = 0.0f; time < animationLength; time += Time.deltaTime) 41 { 42 yield return null; 43 } 44 Debug.Log("MyCoroutine:終了"); 45 }
・質問4。
コルーチンを動かしているスクリプトがアタッチしているゲームオブジェクトを破棄する、
もしくはそのスクリプトコンポーネントを破棄すれば、
そのスクリプト内のコルーチンは、質問1のような入れ子のコルーチンも含めて、全て破棄されるという認識で合っていますか?
こちらは、質問1のスクリプトにおいて、Update()に以下のようなスクリプトやゲームオブジェクトを破棄する処理を書いて試してみた所、
whileのログが停止することが確認できました。
ただ、質問1で入れ子のコルーチンが1回しか動かない状態であることや、ログの停止は確認できていても、
本当にそれでコルーチンを正しく破棄できているか?という疑問があり、念のため、質問させていただきました。
C#
1 void Update(){ 2 if (Input.GetMouseButton(0)){ 3 // Destroy(this); 4 Destroy(this.gameObject); 5 } 6 }
追記
・質問5で試みた実装。
C#
1 IEnumerator myLoopCoroutine; 2 3 bool loopCoroutineIsRunning = false; 4 5 void Start (){ 6 } 7 8 void Update(){ 9 if (Input.GetMouseButtonDown(0)){ 10 // コルーチンを動かす。起動もしくは再開。 11 StartLoopCoroutine(2f); 12 } 13 if (Input.GetMouseButtonDown(1)){ 14 // コルーチンの停止。 15 StopLoopCoroutine(); 16 } 17 } 18 19 void StartLoopCoroutine(float second){ 20 Debug.Log("Start coroutine"); 21 if (loopCoroutineIsRunning){ 22 Debug.LogError("Stop coroutine first!"); 23 return; 24 } 25 if (myLoopCoroutine == null){ 26 myLoopCoroutine = LoopCoroutine(); 27 StartCoroutine(myLoopCoroutine); 28 Debug.Log("New coroutine is started"); 29 } 30 if (myLoopCoroutine != null){ 31 StartCoroutine(myLoopCoroutine); 32 Debug.Log("Resume paused coroutine"); 33 } 34 loopCoroutineIsRunning = true; 35 } 36 37 void StopLoopCoroutine(){ 38 Debug.Log("Stop coroutine"); 39 if (myLoopCoroutine == null){ 40 Debug.LogError("Start coroutine first!"); 41 return; 42 } 43 if (loopCoroutineIsRunning){ 44 StopCoroutine(myLoopCoroutine); 45 } 46 loopCoroutineIsRunning = false; 47 Debug.Log("Coroutine is completely stopped"); 48 } 49 50 IEnumerator LoopCoroutine(){ 51 while(true){ 52 yield return MyCoroutine(3f); 53 } 54 } 55 56 IEnumerator MyCoroutine(float animationLength){ 57 Debug.Log("MyCoroutine:開始"); 58 for (float time = 0.0f; time < animationLength; time += Time.deltaTime){ 59 Debug.Log(time); 60 yield return null; 61 } 62 Debug.Log("MyCoroutine:終了"); 63 }
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2021/08/21 07:51 編集
2021/08/21 15:14
退会済みユーザー
2021/08/22 06:28