📗

【Unity】UniRx/UniTask大全

2024/08/29に公開

はじめに

初めての方も、そうでない方もこんにちは!
現役ゲームプログラマーのたむぼーです。
自己紹介を載せているので、気になる方は見ていただければ嬉しいです!

今回は
 UnityのUniRx/UniTask大全
として、僕がよく使う機能を紹介します

https://zenn.dev/tmb/articles/1072f8ea010299

導入方法

UniRx - UPM for GitHub

https://github.com/neuecc/UniRx.git?path=Assets/Plugins/UniRx/Scripts

UniTask - UPM for GitHub

https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask

導入手順

UPM(Unity Package Manager)で追加します
Window → Package Manager → + → Add pacage from git URL

UniRx

■AddToについて

AddToとはAddToの引数に指定されたオブジェクトが破棄されたタイミングで、Subscribeで生成された購読処理をDisposeするための関数

■クリック処理

・クリックした

_button.OnClickAsObservable().Subscribe(
  _ => Debug.Log("クリックした処理");
).AddTo(this);

・クリック開始

_button.OnPointerDownAsObservable().Subscribe(
  _ => Debug.Log("クリック開始した処理");
).AddTo(this);

・クリック終了

_button.OnPointerUpAsObservable().Subscribe(
  _ => Debug.Log("クリック終了した処理");
).AddTo(this);

■オブジェクトの破壊時処理

・objが破壊されたときの処理

obj.OnDestroyAsObservable().Subscribe(
  _ => Debug.Log("obj破壊時の処理");
).AddTo(this);

UniTask

■待機

・イベントまで待つ

// _isEventがtrueになるまで待つ
await UniTask.WaitUntil(() => _isEvent);

・更新タイミングでイベントまで待つ

// Updateのタイミングで_isEventがtrueになるまで待つ
await UniTask.WaitUntil(() => _isEvent, PlayerLoopTiming.Update);

・時間まで待つ

// _waitTimeの指定秒数まで待つ
await UniTask.Delay(TimeSpan.FromSeconds(_waitTime));

・更新タイミングで時間まで待つ

// Updateのタイミングで_waitTimeの指定秒数まで待つ
await UniTask.Delay(
  TimeSpan.FromSeconds(_waitTime),
  delayTiming: PlayerLoopTiming.Update
);

・1フレームまで待つ

// 1フレームだけ待つ
await UniTask.Yield();

・更新タイミングまで待つ

// Updateのタイミングまで待つ(更新タイミングは色々ある
await UniTask.Yield(PlayerLoopTiming.Update);

・指定フレームまで待つ

// _frameのフレーム数だけ待つ
await UniTask.DelayFrame(_frame);

・更新タイミングで指定フレームまで待つ

// Updateのタイミングで_frameのフレーム数だけ待つ
await UniTask.DelayFrame(_frame, PlayerLoopTiming.Update);

・すべて完了するまで待つ

// runActionとrunWaitUntilが完了するまで待機
UniTask runAction = UniTask.Run(() => onAction?.Invoke());
UniTask runWaitUntil = UniTask.WaitUntil(() => _isEvent);
await UniTask.WhenAll(runAction, runWaitUntil);
【おまけ】UniTaskのキャンセル補助する処理
CancellationTokenHelper.cs
using System.Threading;

namespace Utils
{
    public class CancellationTokenHelper
    {
        /// <summary> Cts </summary>
        public CancellationTokenSource Cts { get; private set; }

        /// <summary> Ctsトークン </summary>
        public CancellationToken Token => Cts.Token;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public CancellationTokenHelper()
        {
            Reset();
        }
        
        /// <summary>
        /// デストラクタ
        /// </summary>
        ~CancellationTokenHelper()
        {
            Dispose();
        }

        /// <summary>
        /// リセット
        /// </summary>
        public void Reset()
        {
            Dispose();
            Cts = new CancellationTokenSource();
        }

        /// <summary>
        /// 破棄
        /// </summary>
        public void Dispose()
        {
            if (Cts != null)
            {
                Cts.Cancel();
                Cts.Dispose();
                Cts = null;
            }
        }
    }
}
使い方
using UnityEngine;
using Cysharp.Threading.Tasks;
using System.Threading;

namespace Example
{
    public class ExampleUniTask
    {
        private bool _isInitialize = false;
        private CancellationTokenHelper _ctsHelper;

        /// <summary>
        /// 初期化
        /// </summary>
        public void Initialize()
        {
            if (_isInitialize)
            {
                return;
            }
            
            // ヘルパーのインスタンスを生成
            _ctsHelper = new CancellationTokenHelper();
            
            // UniTaskの関数に引数でTokenを渡す
            ExampleUniTaskAsync(_ctsHelper.Token).Forget();
            
            _isInitialize = true;
        }

        /// <summary>
        /// 廃棄
        /// </summary>
        public void Dispose()
        {
            // 不要になったらDisposeする
            _ctsHelper.Dispose();
            _isInitialize = false;
        }

        /// <summary>
        /// 非同期でバックボタンの同期
        /// </summary>
        private async UniTaskVoid ExampleUniTask(CancellationToken token)
        {
          // キャンセルしていない時はループ
            while (! token.IsCancellationRequested)
            {
              // Updateまで待機
                await UniTask.Yield(PlayerLoopTiming.Update, token);
            }
        }
    }
}

Discussion