IUniTaskAsyncEnumerableを使って操作の先行入力を実現する
public class Sandbox1 : MonoBehaviour
{
public void Start()
{
var channel = Channel.CreateSingleConsumerUnbounded<ICommand>();
SetupWriter(channel.Writer);
SetupReader(channel.Reader).Forget();
}
private void SetupWriter(ChannelWriter<ICommand> channelWriter)
{
Observable
.EveryUpdate()
.Where(_ => Input.GetKeyDown(KeyCode.A))
.Subscribe(_ =>
{
Debug.Log($"Write CommandA {Time.time:0.00}");
channelWriter.TryWrite(new CommandA { Time = Time.time });
})
.AddTo(this);
Observable
.EveryUpdate()
.Where(_ => Input.GetKeyDown(KeyCode.B))
.Subscribe(_ =>
{
Debug.Log($"Write CommandB {Time.time:0.00}");
channelWriter.TryWrite(new CommandB { Time = Time.time });
})
.AddTo(this);
}
private async UniTask SetupReader(ChannelReader<ICommand> channelReader)
{
await foreach (var command in channelReader.ReadAllAsync(this.GetCancellationTokenOnDestroy()))
{
Debug.Log($"アニメ開始 {command} {command.Time:0.00}");
await UniTask.Delay(TimeSpan.FromSeconds(1));
Debug.Log($"アニメ修了 {command} {command.Time:0.00}");
}
}
}
public interface ICommand
{
float Time { get; }
}
public class CommandA : ICommand
{
public float Time { get; set; }
}
public class CommandB : ICommand
{
public float Time { get; set; }
}説明を簡単にするため、SingleConsumerUnboundedChannelを使うことにします。channelWriter.TryWrite すると、どんどんQueueに積まれていきます。channelReader.ReadAsync または channelReader.ReadAllAsync などで、それを先頭から読んでいけます。
これによりAボタンやBボタンをたくさん入力しても、アニメは順番に再生される。という先行入力が実現できます。