きゅぶろぐ

きゅぶんずの ぶろぐができて べんりだな

IDisposableの寿命をシーンに紐付ける

ああ〜このリソース、Sceneの寿命に紐付けたいな〜って時ありますよね。

var disposable = Disposable.Create(() => {});
disposable.AddTo(Lifespan.Scene);

これを実現するのが以下のコード。

using System;
using UnityEngine;
using UniRx;
using Object = UnityEngine.Object;

namespace Sandbox
{
    public static class DisposableExtension
    {
        public static GameObject SceneLifespanGameObject;
        public static GameObject ApplicationLifespanGameObject;

        public static T AddTo<T>(this T disposable, Lifespan lifespan) where T : IDisposable
        {
            switch (lifespan)
            {
                case Lifespan.Scene:
                    if (SceneLifespanGameObject == null)
                    {
                        SceneLifespanGameObject = new GameObject("SceneLifespan");
                    }
                    disposable.AddTo(SceneLifespanGameObject);
                    return disposable;

                case Lifespan.Application:
                    if (ApplicationLifespanGameObject == null)
                    {
                        ApplicationLifespanGameObject = new GameObject("ApplicationLifespan");
                        Object.DontDestroyOnLoad(ApplicationLifespanGameObject);
                    }
                    disposable.AddTo(ApplicationLifespanGameObject);
                    return disposable;

                default:
                    throw new ArgumentOutOfRangeException(nameof(lifespan), lifespan, null);
            }
        }
    }

    public enum Lifespan
    {
        Scene,
        Application,
    }
}

また、おすすめしたいのがLifespan.Application。
これはDontDestroyOnLoadしたGameObjectに寿命を紐付けてくれます。
「つまりキャンセルされないってことじゃないの?CancellationToken.Noneと何が違うの?」
という点ですが、これはDisabling Domain ReloadingしているEditor上でもちゃんとキャンセルされ、
次の実行時に影響を出さない。という点で優秀です。