見出し画像

【Unity】UniTaskについて

UniTaskはUnityで「待つ」処理を簡単に書けるアセットです。コルーチンより簡単に書けて高機能です。
乗り換えたいとは思っていましたが、停止するときの記述に癖があり、なんとなくコルーチンを使ってしまっていました。
基本的に参考記事を貼り付けただけの手抜き記事となります。


1.UniTaskとコルーチンの違い

2.UniTaskの導入方法と基本機能

ダウンロード先

3.UniTaskのキャンセル方法

以下の記事の「CancellationTokenを使った処理の中断ーA. CancellationTokenをawaitする相手に渡す」が一番簡単かな?と思います。

using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;

namespace Sample.Coroutines
{
    public class CubeMover2A : MonoBehaviour
    {
        private void Start()
        {
            // CancellationTokenの取得
            var ct = this.GetCancellationTokenOnDestroy();

            MoveLoopAsync(ct).Forget();
        }

        /// <summary>
        /// 指定したポイントを周回し続ける
        /// </summary>
        private async UniTask MoveLoopAsync(CancellationToken ct)
        {
            // 無限にループし続ける
            while (true)
            {
////////////////////中略//////////////////////
            }
        }

        /// <summary>
        /// 目的地に向かって一定速度で移動する
        /// </summary>
        private async UniTask MoveToAsync(Vector3 target, float speed, CancellationToken ct)
        {
            // 目的地値に到達するまで無限ループする
            while (true)
            {
////////////////////中略//////////////////////
                if (distance < speed * Time.deltaTime)
                {
                    // ゴールに十分近いならゴールに移動して終了
                    transform.position = target;
                    // 終了
                    return;
                }
                else
                {
                    // ゴールまで距離があるなら一定速度で移動
                    var direction = delta.normalized;
                    transform.position += direction * (speed * Time.deltaTime);

                    // !!ここ!!
                    await UniTask.Yield(ct);
                }
            }
        }

        private void OnGUI()
        {
            if (GUI.Button(new Rect(0, 0, 150, 50), "Destroy"))
            {
                Destroy(gameObject);
            }
        }
    }
}

ただ、基本的に自分はChatGPTとCopilotに殆どコードを書いてもらっていますし、こと細かに覚える必要はないと思っています。

ただ以下のことは覚える必要があります。
・UniTaskはアタッチしているオブジェクトの破壊、非アクティブ化などでは止まらない。
・UniTaskを止めるためにはCancellationTokenを発行し、UniTaskを止めたいタイミングでcancellationTokenSource.Cancel();等を実行する必要がある。

ChatGPTにUniTaskを使用したコードを書いてもらう

以下ChatGPTに作ってもらったUniTaskのコード例です。
指示は次の通りです。

UniTaskを使用したスクリプトをアタッチしているオブジェクトが以下の状態になった時、UniTaskも同時に停止するようにしてほしい。
・非アクティブになったとき
・破壊されたとき
・アプリを終了したとき

using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEngine;

public class UniTaskController : MonoBehaviour
{
    // CancellationTokenSourceを使用して、UniTaskをキャンセル可能にします。
    private CancellationTokenSource cancellationTokenSource;

    private void Awake()
    {
        cancellationTokenSource = new CancellationTokenSource();
    }

    private void Start()
    {
        // 例として非同期メソッドを実行します。
        RunAsyncMethod(cancellationTokenSource.Token).Forget();
    }

    // 任意の非同期メソッド
    private async UniTaskVoid RunAsyncMethod(CancellationToken cancellationToken)
    {
        try
        {
            // 非同期処理をここに書きます。
            // 例:1秒待つ
            await UniTask.Delay(1000, cancellationToken: cancellationToken);

            Debug.Log("Task completed successfully.");
        }
        catch (OperationCanceledException)
        {
            Debug.Log("Task was canceled.");
        }
    }

    private void OnDisable()
    {
        // オブジェクトが非アクティブになった場合にキャンセル
        cancellationTokenSource.Cancel();
    }

    private void OnDestroy()
    {
        // オブジェクトが破壊された場合にもキャンセル
        cancellationTokenSource.Cancel();
    }

    private void OnApplicationQuit()
    {
        // アプリが終了する際にもキャンセル
        cancellationTokenSource.Cancel();
    }
}

シーンが遷移した際にDontDestroyOnLoadのオブジェクト以外は全てDestroyされるため、シーン遷移についてはキャンセル処理を分けて考える必要はないようです。

4.UnityのイベントシステムからUniTask関数を呼び出す方法

非同期メソッドを同期的に呼び出すために、以下のようなヘルパーメソッドを定義してボタンのイベントに紐づけます。

    public void TriggerDelayGoToScene() {
        DelayGoToScene().Forget();  // Forgetを使って非同期タスクをファイアー&フォゲットする
    }

その他参考記事


この記事が気に入ったらサポートをしてみませんか?