【中級者向けUnity講座】RPG編 part3 『プレイヤーからの入力を待つ』


はじめに

皆様こんにちは。個人でゲーム制作をしております、kenと申します。
この講座では、実際にゲームを作りながら「こういう事をするなら、こういう風にすると良いと思うよ。詳しくは自分で調べてね。」という感じで、ゲームの作り方、Unityの機能やアセット等を軽く紹介して行きます。

前回、プレイヤーからの入力を取得する方法を紹介したので、今回はその続きで入力を待つ方法をいくつか紹介します。
ラムダ式とか値の破棄などC#のちょっと特殊な書き方をしているので、知らない方は以下の記事で予習しておくと読みやすくなると思います。
ラムダ式 - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
値の破棄 - xin9le.net

if文で待つ

1番簡単な待ち方はは以下のコードのようにUpdate内にif文を書く方法ですね。

public class WaitInputExample : MonoBehaviour {

    void Update() {
        if (Input.GetButtonDown("Cancel")) {
            //Cancelボタンが押された時の処理
        }
    }

}

しかし、この書き方はコードが読みづらくなり易いので、私は好きじゃないです。

コルーチンで待つ

まず、コルーチンって何やねん!という方には以下の記事がオススメです。
【C#/Unity】コルーチン(Coroutine)とは何なのか

コルーチンにはWait〜という名前の、処理を中断する関数がいくつか有りますが、WaitWhileを使うと引数に渡した関数がfalseを返すまで処理を中断出来るので、入力を待ちたい時に便利です。以下のようなコードで入力を待つ事が出来ます。

public class WaitWhileExample : MonoBehaviour {

    void Start() {
        StartCoroutine(Example());
    }

    IEnumerator Example() {
        yield return new WaitWhile(() => !Input.GetButtonDown("Cancel"));
        //Cancelボタンが押された時の処理
    }

}

これのtrue版のWaitUntilというものもありますが、こちらは条件を満たしていても強制的に1フレーム消費してしまうので、ちょっと使いづらいです。

UniRxで待つ

UniRxを使うと以下のように書けます。コルーチンよりスッキリ書けていい感じです。

public class UniRxExample : MonoBehaviour {

    void Start() {
        this.UpdateAsObservable()
        .Where(_ => Input.GetButton("Cancel"))
        .Subscribe(_ => Debug.Log("Cancelボタンが押された!"));
    }

}

UniRxとは何ぞや?という方には以下の記事がオススメです。
UniRx(ユニアールエックス)の基本的な使い方と具体的な利用例【Unity】【UniRx】

UniRxはちょっと癖があるので慣れが要りますが、使いこなせると非常に便利です。
しかし、無闇に多用するとコードが読みづらくなってしまう事もあるので注意が必要です。

async、await & UniTaskで待つ

個人的には、UniTaskを使うのが1番好きです。
UniTaskを使うと以下のように書けます。

public class UniTaskExample : MonoBehaviour {

    void Start() {
        _ = UpdateLoop();
    }

    async UniTask UpdateLoop() {
        while (true) {
            //ループのタイミングをUpdateと同期させて、このループをUpdateの代わりとして使う
            await UniTask.Yield(PlayerLoopTiming.Update);

            //Cancelボタンが押されるまでここで処理を中断する
            await UniTask.WaitUntil(()=>Input.GetButtonDown("Cancel"));

            //Cancelボタンが押された時の処理をここに書く
        }
    }

}

UniTaskとはC#の標準機能であるTaskをUnity向けに最適化し、更にコルーチン風の機能を付け足したものです。
UniTaskを学ぶには、まずTaskを理解しなければいけません。

以下の記事を読めばTaskを大体理解出来ると思います。
初心者のためのTask.Run(), async/awaitの使い方

更にUniTaskを理解するのには、以下の記事がオススメです。
UniTask – Unityでasync/awaitを最高のパフォーマンスで実現するライブラリ

まとめ

ツクールなどのゲーム制作ツールのように簡単に処理を中断する方法は無いものかと色々試してみましたが、UniTaskが1番それっぽい感じで書けると思います。

次回は、キャラの移動に合わせてカメラを動かす方法をいくつか紹介しようと思います。
次回⇒【中級者向けUnity講座】RPG編 part4『キャラにカメラを追従させる』