コルーチンについての挙動についてまとめる。
目次
概要
ここでは、実際に遭遇した IEnumratorの使い方 や UnityのStartCorutine などの挙動について遭遇するたびにこれであっているんだっけ?と 不安に駆られるため、それらの 挙動だけ について記述したものです。 ここでは、どうしてそうなるかについては、他を当たってください。
※サンプルコードはBehaviorクラス内のものとする。
環境 Unity2018.4.9 VisualStudio2019 Community
実際の中身
IEnumrator を変数で保持し、MoveNextで実行した場合の挙動
この時のログの出力は以下の通り
まだ存在している
まだ存在している
まだ存在している
まだ存在している
存在していない この場合の挙動としては、MoveNext自体は5回実行可能で、5回目にbool nextの値がfalseで返却されます。
1回目:yield return 0; の所まで
2回目 : yiled return 1; の所まで
3回目:yield return 2; の所まで
4回目 : yiled return 3; の所まで
5回目:残りの部分までサンプルコード
private IEnumerator coltine;
void Start()
{
coltine = normalColutine();
}
void Update ()
{
if(null == coltine)
{
return;
}
bool next = coltine.MoveNext();
if(next)
{
Debug.Log("まだ存在している");
}
else
{
Debug.Log("存在していない");
coltine = null;
}
}
private IEnumerator normalColutine()
{
yield return 0;
yield return 1;
yield return 2;
yield return 3;
}
理解補足
MoveNext自体の挙動自体は、関数が終了したタイミングがMoveNext自体がfalseになるタイミングになる。
yield break;を使用した場合の挙動としては以下の通り
MoveNextの動かし方は先ほどの準拠
この場合のログの出力は以下の通り
まだ存在している
存在していない yield return の場合
private IEnumerator breakColutine()
{
yield return 0;
yield break;
}
yield break;が呼び出された時点で、MoveNextの返り値がfalseになる。
IEnumratorの中からStartCorutineを呼び出した挙動について
IEnumerator で 実装されているものからStartCorutine()を呼び出した際の挙動についてです。 パターンとして2パターン - IEnumrator をMoveNextで行った場合 - StartCoroutineで呼び出した場合
呼び出す IEnumratorの中身としては以下の通り
private IEnumerator callCorutine() { yield return 0; Debug.Log("call 1"); yield return StartCoroutine(normalColutine()); Debug.Log("call 2"); } private IEnumerator normalColutine() { Debug.Log("col1"); yield return 0; Debug.Log("col2"); yield return 0; Debug.Log("col3"); yield return 3; Debug.Log("col4"); yield return 5; }
callCorutineをMoveNextで呼び出した場合の出力 call1 cal1 call2 col2 col3 col4 となり、それぞれが別々に動き出すイメージです。
単純にこれは、MoveNextをUpdate側で呼び出している影響かなと思います。IEnumratorで呼び出した場合
call1 col1 col2 col3 col4 coll2 となり、StartCorutineで呼び出した先でさらに yield return StartCorutine で呼び出した場合は、そのコルーチンが終了してから、1つ目の処理の続きが実行されます。 ただ、yield return をつけない場合 call 1 col1 call2 col2 col3 col4 となります。 StartCorutineで呼び出した場合
コード全文
using System.Collections;
using UnityEngine;
public class CorutineSample : MonoBehaviour
{
private bool check = false;
private IEnumerator coltine;
// Use this for initialization
void Start ()
{
//coltine = normalColutine();
//coltine = breakColutine();
coltine = callCorutine();
//StartCoroutine(callCorutine());
}
// Update is called once per frame
void Update ()
{
if(null == coltine)
{
return;
}
bool next = coltine.MoveNext();
if(next)
{
Debug.Log("まだ存在している");
}
else
{
Debug.Log("存在していない");
coltine = null;
}
}
/// <summary>
/// Whileを使用したコルーチンです。
/// </summary>
/// <returns></returns>
private IEnumerator whileColutine()
{
int ban = 0;
while(false == check)
{
if(Input.GetKey(KeyCode.Space))
{
check = true;
}
///万が一の時用のセーフティ
if(ban >= 10)
{
check = true;
}
ban++;
Debug.LogFormat("whileColutine:{0}",ban);
}
IEnumerator col = normalColutine();
int val = 0;
while(val != 5)
{
col.MoveNext();
if(null != col.Current)
{
val = (int)col.Current;
}
Debug.Log("ここ通っているよ");
}
Debug.Log("while Corutine");
yield return null;
}
/// <summary>
/// 通常のコルーチンの処理
/// </summary>
/// <returns></returns>
private IEnumerator normalColutine()
{
Debug.Log("col1");
yield return 0;
Debug.Log("col2");
yield return 0;
Debug.Log("col3");
yield return 3;
Debug.Log("col4");
yield return 5;
}
/// <summary>
/// breakのコルーチン
/// </summary>
/// <returns></returns>
private IEnumerator breakColutine()
{
yield return 0;
yield break;
}
private IEnumerator ifColutine()
{
if(check)
{
Debug.Log("IfColutine check=True");
yield return 0;
}
else
{
Debug.Log("IfColutine Check = false");
yield break;
}
Debug.Log("IfColutine End");
yield break;
}
private IEnumerator breakColuine()
{
Debug.Log("breakColutine 1");
yield break;
//こっちは通らない
Debug.Log("breakColutine 2");
}
/// <summary>
/// IEnumeratorからStartCorutineが呼び出された場合のもの
/// </summary>
/// <returns></returns>
private IEnumerator callCorutine()
{
yield return 0;
Debug.Log("call 1");
yield return StartCoroutine(normalColutine());
Debug.Log("call 2");
}
}