土屋つかさの技術ブログは今か無しか

土屋つかさが主にプログラミングについて語るブログです。

#unity 「特定条件まで待機しつつも毎フレームこれを実行したい」の実装方法を考える

 最近、こちらの記事*1を読んだのをきっかけに、UniTaskの勉強をしていました。
blog.kyubuns.dev
 勉強に使ったのはこちらの本。

 上記の記事にもある通り、「特定条件までawait(≒待機)しつつも毎フレームこれを実行したい」というロジックは、ゲームプログラミングではそりゃもう頻発します。というか、ゲームプログラミングの大半がこれだと言っても多分過言ではないです。この話自体はまた改めて記事にしたいと思っています。今回は土屋が現在作っているステートマシンではどういう実装になるか考えてみました。

 普通に組むと多分こんな感じになります。WaitMilliSecondsはステートに相当するクラスで、これがステートマシンにスタックされると、毎フレームUpdateが呼び出されます。

//待機ステートクラス
public class WaitMilliSeconds : StateMachine<TestWait>.State
{
    float elapsed;
    float waitTime;

    public WaitMilliSeconds(float waitTime)
    {
        this.waitTime = waitTime;
        elapsed = 0.0f;
    }

    protected internal override void Update()
    {
        //経過時間にΔ時間を加算する
        elapsed += Time.deltaTime;
        //経過時間が待機時間以上になった場合ステートを終了する
        if (elapsed >= waitTime) return;
        //ここで待機中処理を実行する
        //Debug.Log(elapsed);
        //
        //ステートを続行する(自分自身をスタックし直している)
        StateMachine.PushState(this);
        //スタックの走査を中断する(フレームを進める)
        StateMachine.EnableSuspend();
    }
}

 ステートマシン制御の泥臭い部分がコードに見えてしまってるけど、柔軟性とのトレードオフだと思うので、これくらいはいいかな……。もうちょっとRxについて勉強しないとこれが優位性があるのかはわからない感じ。
 ステートマシン自体の実装は1ファイルなんですが、実用性との兼ね合いでごりごりインターフェイスを変えてるので、公開するのはもう少し先になると思います。ひとまず最新版をgistに上げておきます。
StateMachine.cs · GitHub