コルーチンについて
概要
特徴として通常の関数とは異なり、処理を途中で抜けて任意のタイミングで中断部分から処理を再開できる。
例えば、初心者の方が「キャラクターを1フレームに1ドットずつ100 ドット動かす」といった場合、下記のようにしてしまうことがあります。
for(int i=1; i<100; i++){ myChar.MoveToRight(1); }
これでは結果的に失敗で、これを実行すると1フレームで100ドット右に動いてしまいます。
ところが、「yeild」を1行入れることで、1フレームに1ドットずつ100ドット動かすことが出来るようになります。
for(int i=1; i<100; i++){ myChar.MoveToRight(1); yeild return 0; }
「yeild」を使用することで、関数の実行を一時的に中断し、次回にその関数が呼び出されたときにその続きを実行することが出来ます。
内部的には、オブジェクト指向のイテレータとなるため「IEnumerator」を使う。この機能により状態変数を減らせることが出来て便利です。
参考
コルーチンの準備
シーンの読み込み
UnityChan2Dのプロジェクトを使用して、コルーチンの動きを確認してみましょう。
UnityChan2D→Assets→Scenesにある「Introduction Demo」をクリックして、シーンの読み込みを行ってください。
弾としてコインのスプライトを生成
UnityChan2D→Demo→SpritesのCoin.pngをUnityChan2D→Spritesにコピーします。
Inspectorにて「Sprite Mode」を「Multiple」、「Pixels Per Unit」を「16」にします。
Sprite Editorにて「Type」をGridに変更、「Size」をX 16 Y 16で「Slice」ボタンを押下後、Applyします。
弾であるコインの設定
Coinが大きいので、Scaleを0.5にして小さくします。
またRigidBody 2Dを追加して「Gravity Scale」を「0」にし、「Freeze Rotation Z」をオンにします。
また、Circle Collider 2Dを追加します。
C#スクリプト作成
Assets/ScriptsにC# スクリプトの「Coin」を作成します。下記コードを入力してCoinにアタッチします。
アタッチ後、プレハブ化するためにAssets/Prefabs にCoinをドラッグ&ドロップします。
public class Coin : MonoBehaviour { public int speed = 2; private static int count = 0; void Start() { GetComponent<Rigidbody2D>().velocity = transform.right.normalized * speed; } void OnTriggerStay2D(Collider2D other) { if (other.tag == "DamageObject") { if(++count >= 6) Destroy(other.gameObject); // コインが6発当たれば敵を削除 Destroy(this.gameObject); } } void OnBecameInvisible() { Destroy(this.gameObject); // カメラから外れたら削除 } }
コルーチンの使い方
Unityでコルーチンを使用するケースのほとんどは、任意の時間(秒)処理を止めたい場合となります。
任意の時間(秒)処理を止める処理は下記コードとなります。
yield return new WaitForSeconds (秒数);
コルーチンは、IEnumeratorを返す関数として実装します。
IEnumerator Shot() { yield return new WaitForSeconds(1f); //1秒待機 }
コルーチンを呼ぶには、StartCoroutineメソッドで実行します。
StartCoroutine(“Shot”);
参照
Coinの発射
左クリックでコインが3連射されるようにプログラムを変更します。
Assets/ScriptsにC# スクリプトの「UnityChan2DController」を編集します。
private bool isRunning = false; public GameObject Coin; void Update() { if (m_state != State.Damaged) { float x = Input.GetAxis("Horizontal"); bool jump = Input.GetButtonDown("Jump"); Move(x, jump); // 左クリックでコイン発射 if (Input.GetButtonDown("Fire1")) StartCoroutine(“Shot”); // コルーチンを呼びます } } IEnumerator Shot() { if (isRunning) { yield break; } isRunning = true; // コインを3連射する for(int i = 0; i<3; i++) { Instantiate(Coin, new Vector2(transform.position.x + 0.5f, transform.position.y - 0.5f), Quaternion.identity); yield return new WaitForSeconds(1f); // 1秒待機 } isRunning = false; }