ゲーム開発の入門書の一番最初で「毎フレーム描画処理を挟む必要があるので、こうは書けません。」って言ってくるサンプルコードあるじゃないですか。
あれ、あのまま書けたらめっちゃ良いですよね。という話です。
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で入力を待つと、アニメーション中にボタン連打されても無視出来る、みたいなメリットもあります。