コルーチンとは
- 非同期処理できる。
- 関数を任意のタイミングで中断・再開できる機能。
- 複数の処理を疑似並列できる。(完全な並列ではない)
- Unity のメインスレッドで処理する。
- 結果は返せない。
- GameObject と処理が紐づく。
- IEnumerator 型を戻り値とした関数を定義する。
- コルーチンを実行したいときは
StartCoroutine(string コルーチン名)
またはStartCoroutine(IEnumerator型の変数)
- コルーチンを停止(中断)したいときは
StopCoroutine(string コルーチン名)
またはStopCoroutine(IEnumerator型の変数)
コルーチンの主要な機能一覧
機能 | 詳細 |
---|---|
yield return null | 1フレーム分処理を中断、次のフレームで続きの行を処理 |
yield break | コルーチンを途中で終了、再開はできない |
yield return new WaitForSeconds(float seconds) | 指定した seconds 秒、コルーチンを中断する |
yield return new WaitUntil(Func predicate) | predicate の関数の返り値が true になったら処理を再開する |
yield return new WaitWhile(Func predicate) | predicate の関数の返り値が false になったら処理を再開する |
yield return StartCoroutine() | 指定したコルーチンを実行、完了するまで後続処理は行わない |
StopAllCoroutines() | コルーチンを全て止める |
yield return null
yield return null
は、1フレーム分処理を中断して、次のフレームで続きの行を処理します。
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
IEnumerator sample1 = Sample1();
IEnumerator sample2 = Sample2();
StartCoroutine(sample1);
StartCoroutine(sample2);
}
IEnumerator Sample1()
{
Debug.Log("Sample1 Start.");
yield return null; // Sample1()の処理は1フレーム待機
Debug.Log("Sample1 End.");
}
IEnumerator Sample2()
{
Debug.Log("Sample2 Start.");
yield return null; // Sample2()の処理は1フレーム待機
Debug.Log("Sample2 End.");
}
}
だから、結果は下の通りで、
yield break
yield break
は、コルーチンを途中で終了します。
再開はできないです。
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
IEnumerator sample1 = Sample1();
IEnumerator sample2 = Sample2();
StartCoroutine(sample1);
StartCoroutine(sample2);
}
IEnumerator Sample1()
{
Debug.Log("Sample1 Start.");
yield break; // Sample1() の処理はここで止める
Debug.Log("Sample1 End.");
}
IEnumerator Sample2()
{
Debug.Log("Sample2 Start.");
yield break; // Sample2() の処理をここで止める
Debug.Log("Sample2 End.");
}
}
コルーチンを途中で終了したので、Sample1 End.
と Sample2 End.
は出力されません。
yield return new WaitForSeconds(float seconds)
yield return new WaitForSeconds(seconds)
は、指定した秒数の間、コルーチンの実行を待ちます。
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
IEnumerator sample1 = Sample1();
IEnumerator sample2 = Sample2();
StartCoroutine(sample1);
StartCoroutine(sample2);
}
IEnumerator Sample1()
{
Debug.Log("Sample1 Start.");
yield return null; // Sample1()の処理は1フレーム待機
Debug.Log("Sample1 End.");
}
IEnumerator Sample2()
{
Debug.Log("Sample2 Start.");
yield return new WaitForSeconds (1.0f); // Sample2()の処理は1秒待機
Debug.Log("Sample2 End.");
}
}
Sample2 End.
が、他より1秒経過してから出力されるようになります。
yield return new WaitUntil(Func predicate)
yield return new WaitUntil(Func<bool> predicate)
は、predicate で指定した関数が true を返したときに再開します。
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
bool flg = false;
void Start()
{
IEnumerator sample1 = Sample1();
IEnumerator sample2 = Sample2();
StartCoroutine(sample1);
StartCoroutine(sample2);
}
IEnumerator Sample1()
{
Debug.Log("Sample1 Start.");
yield return new WaitUntil(() => flg == true); // flg が true になるまで処理が止まる
Debug.Log("Sample1 End.");
}
IEnumerator Sample2()
{
Debug.Log("Sample2 Start.");
yield return null;
Debug.Log("Sample2 End.");
flg = true; // Sample2()の最後に flg を true にする
}
}
flg が true になるまで、 Sample1 End. が出力されないため、下記のような結果になります。
yield return new WaitWhile(Func predicate)
yield return new WaitWhile(Func<bool> predicate)
は、predicate で指定した関数が false を返したときに再開します。
WaitUntil(Func<bool> predicate)
の逆バージョン。
使い方は上と一緒なので省略。
yield return StartCoroutine()
yield return StartCoroutine()
は、指定したコルーチンを実行し、完了するまで処理を中断します。
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
bool flg = false;
void Start()
{
IEnumerator sample1 = Sample1();
StartCoroutine(sample1);
}
IEnumerator Sample1()
{
Debug.Log("Sample1 Start.");
IEnumerator sample2 = Sample2();
yield return StartCoroutine(sample2); // Sample2() を実行が終わるまで待機
Debug.Log("Sample1 End.");
}
IEnumerator Sample2()
{
Debug.Log("Sample2 Start.");
yield return null; // Sample2()の処理は1秒待機
Debug.Log("Sample2 End.");
}
}
StopAllCoroutines()
名前の通り、コルーチンの全てを止めます。
Behavior 上で実行されている全てを止めます。
using System.Collections;
using UnityEngine;
public class Test : MonoBehaviour
{
void Start()
{
IEnumerator sample1 = Sample1();
IEnumerator sample2 = Sample2();
StartCoroutine(sample1);
StartCoroutine(sample2);
StopAllCoroutines(); // 全てのコルーチンを止める
}
IEnumerator Sample1()
{
Debug.Log("Sample1 Start.");
yield return null;
Debug.Log("Sample1 End.");
}
IEnumerator Sample2()
{
Debug.Log("Sample2 Start.");
yield return null;
Debug.Log("Sample2 End.");
}
}
コルーチンを途中で終了したので、Sample1 End.
と Sample2 End.
は出力されません。
終わりに
Unity 初心者なので、間違いがあったら教えてくれるとありがたいです。
今まで雰囲気で非同期処理を書いていたので、しっかり勉強するために記事を書くことにしました。
いまのところ、async/await編、UniRx編を書く予定です。
挫折したらごめんなさい。
参考文献
コルーチン - Unity マニュアル
【C#/Unity】コルーチン(Coroutine)とは何なのか
Unityのコルーチン機能を使う