LoginSignup
25
17

More than 3 years have passed since last update.

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

Posted at

この記事は、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を吐く
        }
    }
} 
25
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
17