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