ゲームを作っていて、敵の攻撃やこちらの照準の動きなどは今まで通りで、それとは独立して画面の一部で1秒ごとに1から20までカウントアップしてそのカウントを表示したいとしましょう。よくあるケースです。特別の攻撃で「20秒間しか使えません」みたいな。あるいは10枚、20枚の静止画をアニメーションさせるため順に表示するとき、0.2秒ごとに絵を切り替えるとか。ぼくは今までこれを言わば自作のタイマで解決していました。再利用できるようにちゃんと仕組みをこしらえておけば、まあ不都合無く便利に使えます。しかし、処理の流れが分かりにくくなるなど、何とかならないものか……と思ってはいたのです。
コルーチンという仕組みがあります。存在自体は知っていましたが、使おうという気がなく、今まで放っておいたものです。しかし今回試してみて……スバラシイ!!!! そこで備忘録を兼ね、ここに基本的な使い方を載せておきます。しつこいようですがサンプルのコードは飾りは一切なし、が初心者にはありがたいのです。ギリギリ、ポイントのみをコードにしておくのが分かりやすい!!
(使用例1)ゲームの進行と並行して1,2,3,……と20まで1秒ごとにカウントアップする
//カウントアップ開始 StartCoroutine(countA()); //-------------- //コルーチンの定義 IEnumerator countA() { for (int i = 0; i < 20; i++) { Debug.Log("●" + i.ToString()); yield return new WaitForSeconds(1f); } }
これだけです。countA()をどこかで定義しておけば、好きなところで
StartCoroutine(countA());
を実行するだけでカウントアップが始まります。ここではforループを使っています。while(true)ループにし、条件によってループを抜ける(breakで)ようにすればそれでもできるでしょう。
(使用例2)カウントアップを独立して2つ、行う。片方は0.5秒ごと
//カウントアップ開始 StartCoroutine(countA()); StartCoroutine(countB()); //---------------------- IEnumerator countA() { for (int i = 0; i < 20; i++) { Debug.Log("●" + i.ToString()); yield return new WaitForSeconds(1f);//1秒待つ } } //----------------------------------------- IEnumerator countB() { for (int i = 0; i < 10; i++) { Debug.Log("▲" + i.ToString()); yield return new WaitForSeconds(0.5f);//0.5秒待つ } }
バラバラにカウントアップされていることを確認しましょう。もちろん3つでも4つでも大丈夫。
(使用例3)countA()(1秒ごとに20回)が終わったらcountB()(0.5秒ごとに10回)を実行する
//カウントアップ開始 StartCoroutine(count()); //----------------------------------------- IEnumerator count() { yield return StartCoroutine(countA()); yield return StartCoroutine(countB()); } //----------------------------------------- IEnumerator countA() { for (int i = 0; i < 20; i++) { Debug.Log("●" + i.ToString()); yield return new WaitForSeconds(1f); } } //----------------------------------------- IEnumerator countB() { for (int i = 0; i < 10; i++) { Debug.Log("▲" + i.ToString()); yield return new WaitForSeconds(0.5f); } }
これも便利です。
yield return StartCoroutine(xxx);
を続けて書けばいくらでも「あれが終わったら次はこれ、その次はこちら、……」とできます。具体的には……このアニメーションに続いてあの動作を、とか、スプラッシュ画面の表示が終わったらステージ1を開始し、ステージ1が終わったらステージ2の開始、とか。例えば時間をチェックすればこういったゲームの進行の管理はできますが(今まではそうしていました)、コルーチンを使った方がずっと楽だと思います。ステージ間に何かを挟むなど、変更も容易です。
もっと早く使い始めていれば相当、時間の節約ができたと思います。なお、コルーチンはちょっと見るとマルチスレッドみたいな感じですが、違うのだそう。スレッドとしてはひとつでやっているみたいです。調べてみてください。