TaskとMessageBrokerを活用してゲームロジックを書くとこんなシンプルに書ける

ゲーム開発の入門書の一番最初で「毎フレーム描画処理を挟む必要があるので、こうは書けません。」って言ってくるサンプルコードあるじゃないですか。
あれ、あのまま書けたらめっちゃ良いですよね。という話です。

UniRx, UniTask, TaskMessageBrokerを使います。

MessageBrokerは、ゲームロジックから周りにイベントを通知してアニメーションなどを行わせるためのもの。
AsyncReactivePropertyは、ゲームロジックに対して入力を入れるためのもの。

public TaskMessageBroker MessageBroker { get; } = new TaskMessageBroker();
public AsyncReactiveProperty<IOperation> Operation = new AsyncReactiveProperty<IOperation>(null);
passButton.onClick.AddListener(() => Operation.Value = new Pass());

MessageBroker.Subscribe<AttackLog>(async log =>
{
    await UniTask.Delay(1000); // アニメーションとか
}).AddTo(this);

while (!(state.Phase is GameFinished))
{
    ICommand command;
    var operation = await Operation.WaitAsync();

    if (operation is Pass)
    {
        command = new PassCommand(CurrentPlayer);
    }
    else throw new Exception($"Unknown operation {operation}");

    var logs = state.Apply(command);
    await MessageBroker.PublishAsync(logs); // Subscribeしている全てのイベントが終わるまで待つ
}

本来ゲームのコードってこう書きたかったと思うんですよね。
必要なところで必要な入力だけを受け取って、アニメーション処理などは外部に逃して終わるまで待つだけ。
外側でアニメーションが0秒で終わろうが、100秒かかろうが、ここでは知ったこっちゃありません。
WaitAsyncで入力を待つと、アニメーション中にボタン連打されても無視出来る、みたいなメリットもあります。