EditorではAddressableのロードを早くする

ビルドしたプレイヤーに比べてUnity Editor上のAddressableのロードがやけに遅いのは
AddressableAssetSettings.asset の simulatedLoadDelay がデフォルトで0.1に設定されているからでした。
0にすれば下記コードと同じ速度になりました。


以下、元の記事。


AddressableをIDisposableで管理するの続きです。

Addressable、めっちゃ便利だけどEditorでもロードに少し時間がかかってしまい反復テストに向いてないんですよね。
そこで、Editor限定でロードを早くしてみました。
直接読み込むことで速度を早くしているので、Addressableのシミュレート機能は無効になります。お気をつけください。

UnityEditorのメニューから速度を調整できます。

コード

「AddressableをIDisposableで管理する」のコードと組み合わせてお使いください。

AddressableLoaderMenu.cs
using System;
using System.Linq;
using System.Threading;
using Cysharp.Threading.Tasks;
using UnityEditor;

namespace KyubunsSandbox.Editor
{
    public static class AddressableLoaderMenu
    {
        private static string PlayerPrefsKey => $"{PlayerSettings.productName}.Addressable";
        private const int Default = 0;
        private const int Fast = 1;
        private const int Slow = 2;

        [InitializeOnEnterPlayMode]
        private static void InitAddressableLoader(EnterPlayModeOptions options)
        {
            var v = EditorPrefs.GetInt(PlayerPrefsKey, 0);
            if (v == Default) AddressableWrapper.AddressableLoader = new AddressableWrapper.DefaultAddressableLoader();
            if (v == Fast) AddressableWrapper.AddressableLoader = new EditorOptimizedAddressable();
            if (v == Slow) AddressableWrapper.AddressableLoader = new EditorSlowAddressable();
        }

        public class EditorOptimizedAddressable : AddressableWrapper.IAddressableLoader
        {
            public UniTask<IDisposableAsset<TObject>> LoadAssetAsync<TObject>(string address, CancellationToken cancellationToken) where TObject : UnityEngine.Object
            {
                return LoadAssetInternal<TObject>(address, cancellationToken);
            }

            public static UniTask<IDisposableAsset<TObject>> LoadAssetInternal<TObject>(string address, CancellationToken cancellationToken) where TObject : UnityEngine.Object
            {
                foreach (var entity in UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject.Settings.groups.SelectMany(x => x.entries))
                {
                    if (entity.address == address)
                    {
                        return UniTask.FromResult<IDisposableAsset<TObject>>(new DisposableAsset<TObject>((TObject) entity.TargetAsset, () => { }));
                    }
                }

                throw new Exception($"{address} is not found");
            }
        }

        public class EditorSlowAddressable : AddressableWrapper.IAddressableLoader
        {
            public async UniTask<IDisposableAsset<TObject>> LoadAssetAsync<TObject>(string address, CancellationToken cancellationToken) where TObject : UnityEngine.Object
            {
                await UniTask.Delay(TimeSpan.FromSeconds(UnityEngine.Random.Range(0f, 1f)));
                return await EditorOptimizedAddressable.LoadAssetInternal<TObject>(address, cancellationToken);
            }
        }

        [MenuItem("Addressable/Default")]
        public static void AddressableDefault() => EditorPrefs.SetInt(PlayerPrefsKey, Default);

        [MenuItem("Addressable/Fast")]
        public static void AddressableFast() => EditorPrefs.SetInt(PlayerPrefsKey, Fast);

        [MenuItem("Addressable/Slow")]
        public static void AddressableSlow() => EditorPrefs.SetInt(PlayerPrefsKey, Slow);

        [MenuItem("Addressable/Default", true)]
        public static bool AddressableDefaultValidate()
        {
            var v = EditorPrefs.GetInt(PlayerPrefsKey, 0);
            Menu.SetChecked("Addressable/Default", v == Default);
            Menu.SetChecked("Addressable/Fast", v == Fast);
            Menu.SetChecked("Addressable/Slow", v == Slow);
            return true;
        }
    }
}