i-school - コルーチンを変数に代入して実行する

コルーチンを変数に代入して実行する(未)


 書式は主に2種類あります。どちらでも問題なく変数内にコルーチンのメソッドが代入されます。

1.IEnumrator型
2.Coroutine型

 IEnumrator型は、IEnumratorインターフェイスを使用しているものです。
 Coroutine型は、MonoBehavior.Coroutineクラスのインスタンスの参照をオーバーロードして使用しているものです。

1.IEnumeratorを使用する場合


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CoroutineTest : MonoBehaviour
{
    // IEnumerator型の宣言。外部のクラスから呼びたい場合にはPublic修飾子をつける
    private IEnumerator actionCoroutine = null;

    IEnumerator Start()
    {
        // 変数にコルーチンメソッドを代入
        actionCoroutine = ActionFire();

        // 代入されていコルーチンメソッドを実行
        yield return StartCoroutine(actionCoroutine);        
    }

    public void Slash() {
        // 変数に値(メソッド)がないか確認
        if (actionCoroutine != null) {
            // メソッドがある場合にはコルーチン処理が動いているので停止させる
            StopCoroutine(actionCoroutine);
            // 代入されている値をnullにする(メソッドを抜く)
            actionCoroutine = null;
        }

        // 変数にコルーチンメソッドを代入
        actionCoroutine = ActionSlash();
        // 代入されていコルーチンメソッドを実行
        StartCoroutine(ActionSlash());
    }

    IEnumerator ActionFire() {
        Debug.Log("Action");
        yield return new WaitForSeconds(1.0f);

        // 処理が終了したので、代入されている値をnullにする(メソッドを抜く)
        if (actionCoroutine != null) {
            actionCoroutine = null;
        }
    }

    IEnumerator ActionSlash() {
        Debug.Log("Slash");
        yield return new WaitForSeconds(1.0f);

        // 処理が終了したので、代入されている値をnullにする(メソッドを抜く)
        if (actionCoroutine != null) {
            actionCoroutine = null;
        }
    }
}

2.Coroutineを使用する場合


 コルーチンの代入書式と実行書式がIEnumerator型とは異なります。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CoroutineTest : MonoBehaviour
{
    // Coroutine型の宣言。外部のクラスから呼びたい場合にはPublic修飾子をつける
    private Coroutine actionCoroutine = null;

    void Start()
    {
        // 変数にコルーチンメソッドを代入して実行
        actionCoroutine = StartCoroutine(ActionFire());        
    }

    public void Slash() {
        // 変数に値(メソッド)がないか確認
        if (actionCoroutine != null) {
            // メソッドがある場合にはコルーチン処理が動いているので停止させる
            StopCoroutine(actionCoroutine);
            // 代入されている値をnullにする(メソッドを抜く)
            actionCoroutine = null;
        }

        // 変数にコルーチンメソッドを代入して実行
        actionCoroutine = StartCoroutine(ActionSlash());
    }

    IEnumerator ActionFire() {
        Debug.Log("Action");
        yield return new WaitForSeconds(1.0f);

        // 処理が終了したので、代入されている値をnullにする(メソッドを抜く)
        if (actionCoroutine != null) {
            actionCoroutine = null;
        }
    }

    IEnumerator ActionSlash() {
        Debug.Log("Slash");
        yield return new WaitForSeconds(1.0f);

        // 処理が終了したので、代入されている値をnullにする(メソッドを抜く)
        if (actionCoroutine != null) {
            actionCoroutine = null;
        }
    }
}

3.変数を利用することでStopCoroutineで実行中のコルーチンを停止する


 コルーチンを実行するにあたり、特定の処理が行われた場合には、そのコルーチン処理を停止したいという状況があるとします。
そういった場合、事前に変数を用意しておいて、その変数内にコルーチンメソッドを代入し、実行をさせておくことで
StopCoroutine処理により、動いているコルーチン処理を終了させることが出来ます。

 そのまま再度StartCoroutineをすれば、コルーチン停止前の状態から再開されます。
もしもそのコルーチン処理を途中ではなく、最初から処理を実行したいのであれば、
再度、メソッドを代入し直してから実行することでメソッドの最初の処理から実行されます。

 また、yield return StartCoroutine(コルーチン用の変数)で命令しているStartCoroutineも、StopCoroutineで停止できます。

4.変数を利用することで、特定の種類の処理を、常に1つの処理に制御して実行する


 変数を使ってコルーチンを実行しているため、常にその変数を使用してコルーチンを実行することにより、意図していない並列処理が動くことを防ぐことも出来ます。

 例えば、ある1つのステートの実行のみを期待されているような処理が複数のコルーチンによって行われるような場合、
コルーチン用に作った変数を常に1つだけ使ってコルーチンを実行していくことで、2つ以上のステートが実行されることを排除できます。
 
つまり

 ・攻撃アクション
 ・防御アクション
 ・探索アクション
 ・スキルアクション
 
といったような、アクション系の処理がすべてコルーチンにて実装されている場合は、すべてが並列処理できる状態になっています。
当然ながら、あるアクション中に予期しない他のアクションが差し込まれてしまうこともあり得ます。

 このような処理については、これらのアクション系の処理は常に1つの変数を通じてコルーチンを実行するように制御することで
いずれか1つのアクションのみしか実行されないように出来ます。1つのコルーチンが終了、あるいは停止されてから、次のコルーチンを実行することで
複数のアクションが実行されることを防ぎ、期待した挙動にすることが出来ます。

5.while文を持つコルーチンを止める場合


 注意点がありまして、StopCoroutineによって停止したコルーチン処理の内部にwhile文によるループ処理がある場合、タイミングによってはwhileの処理が動いてしまうことがあります。
そのため、StopCoroutineや、コルーチン変数を別のコルーチンメソッドで上書きしていたり、Nullにしていても動いてしまうような場合には
while文自体も止めるようにすると、この現象を回避できます。