Help us understand the problem. What is going on with this article?

UnityでUniTaskな処理を直列に並べて処理をする

More than 1 year has passed since last update.

この記事は、UniRxとUniTaskが前提になります。
UniRxとUniTaskついてはまずこちらをご覧ください
https://github.com/neuecc/UniRx
https://github.com/Cysharp/UniTask

昨今、Unityが対応しているC#バージョンが上がってきたことにより、UniTaskなどで非同期な処理を書くことが多くなってきました。
しかしUnity上でゲーム表現のリッチ化などもあり、リソースの都合上並列で行うことにできない非同期処理の需要は細々とあるかとおもいます。
自分もそのようなものが必要になったので、UniTaskな処理をまとめてQueueに予約し、逐次的に処理をしていくSequentialProcessQueueというクラスをGist上に公開したので紹介します。

SequentialProcessQueue
https://gist.github.com/yKimisaki/0909e811f4959badba0ad7f8b3a2ee7e

以下はアバターのあるマルチプレイなゲームで、プレイヤーアバターを作るファクトリクラスを想定したものです。

SomeFactory.cs
class PlayerAvatarFactory : IDisposable
{
    SequentialProcessQueue queue;

    public SomeFactory()
    {
        // デフォルトはObservable.EveryUpdateですが、引数で変更することができます
        queue = new SequentialProcessQueue(MainThreadDispatchType.FixedUpdate);

        // SequentialProcessQueueで処理が走っているかはIsProcessingで受けることができます
        queue.IsProcess.Subscribe();
    }

    public void Dispose()
    {
        // 必ず不要になったらDisposeしてください
        queue.Dispose();
    }

    // いつプレイヤーが入ってくるかわからない
    public void OnJoinPlayer()
    {
        try
        {
            var cancellationTokenSource = new CancellationTokenSource();
            queue.ReserveProcess(CreatePlayerAvatarAsync, cancellationTokenSource.Token); // 処理を予約

            // 予約を個別にキャンセルできる
            // SequentialProcessQueueで処理が開始する前にキャンセルすればスキップされる
            cancellationTokenSource.Cancel();

            async UniTask CreatePlayerAvatarAsync()
            {
                // 並列にできないとても重い処理

                if (cancellationTokenSource.Token.IsCancellationRequested)
                {
                    // 個別でキャンセルされてる場合はこっち
                    return;
                }

                if (queue.AllQueueCancellation.IsCancellationRequested)
                {
                    // SequentialProcessQueueがDisposeされている等のキャンセルはこっち
                    return;
                }

                // 並列にできないとても重い処理
            }
        }
        catch (OperationCanceledException e)
        {
            // 既にCancellationTokenSourceがキャンセルされてる場合や
            // SequentialProcessQueueがDisposeされている場合は
            // ReserveProcessがOperationCanceledExceptionを吐く
        }
    }
} 
yKimisaki
書いてるものは個人の感想です
http://kimisaki.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away