Unity の Addressables でダウンロードアセットのデータサイズを取得する
※ これは 2022/09/02 時点の Unity 2022.1.15f1 Addressables v1.20.5 Windows 11 の情報です
最新版では動作が異なる可能性がありますのでご注意ください
前回引き続き Addressables を使いつつ、今回はリモートアセットのダウンロードサイズをダウンロード前に取得して表示したい
前回のリモートアセット更新に追加する形で、ダウンロードする画像アセットのサイズを取得する
やることは Test.cs
の変更だけ
using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using UnityEngine.UI; public class Test : MonoBehaviour { [SerializeField] private Image cafeImage = null; [SerializeField] private Image mochaImage = null; private Image thumbnailImage = null; private AsyncOperationHandle<Sprite> handle = default; private const string RemoteLoadPath = @"http://localhost/StandaloneWindows64/{0}/"; private static string OriginalRootPath = null; private static string CurrentRootPath = null; private AssetBundle currentBundle = null; private string currentName = null; private Hash128 currentHash = default; public async void Start() { // Addresables 初期化 var locator = await Addressables.InitializeAsync().Task; // 初期化時のルートパス取得 var info = Addressables.GetLocatorInfo(locator.LocatorId); OriginalRootPath = info.HashLocation.InternalId.Replace(Path.GetFileName(info.HashLocation.InternalId), ""); // アドレス書き換えを有効化 Addressables.InternalIdTransformFunc = MylIdTransform; await SetCatAsset("Cafe"); } private static string MylIdTransform(IResourceLocation location) { // ルートパスを置き換える if (location.InternalId.StartsWith(OriginalRootPath)) { return location.InternalId.Replace(OriginalRootPath, CurrentRootPath); } return location.InternalId; } private async Task SetCatAsset(string catName) { Cat.Name = catName; this.thumbnailImage = catName switch { "Cafe" => this.cafeImage, "Mocha" => this.mochaImage, _ => null }; // ルートパスの再評価 CurrentRootPath = string.Format(RemoteLoadPath, Cat.Name); // リモートカタログに変更があれば更新する var catalogs = await Addressables.CheckForCatalogUpdates(true).Task; if (catalogs != null && catalogs.Count > 0) { var locators = await Addressables.UpdateCatalogs(catalogs, true).Task; // リモートアセットの取得先を確認 if (locators[0].Locate("Assets/Sprites/cat.png", typeof(Sprite), out var locations)) { // リモートアセットの URL は Dependencies に入っている foreach(var location in locations[0].Dependencies) { UnityEngine.Debug.Log($"--------------> uri={Addressables.InternalIdTransformFunc(location)}"); if (location.Data is AssetBundleRequestOptions sizeData) { #if UNITY_EDITOR EditorUtility.DisplayDialog($"{location.PrimaryKey}", $"{sizeData.BundleSize:#,0} bytes", "OK"); #endif } } var option = locations .SelectMany(x => x.Dependencies) .Select(x => x.Data) .OfType<AssetBundleRequestOptions>() .First(); var newName = option.BundleName; var newHash = Hash128.Parse(option.Hash); if (this.currentBundle != null) { UnityEngine.Debug.Log($"--------------> {this.currentName}【{this.currentHash}】 -> {newName}【{newHash}】"); // 同じ名前で内容(Hash)が異なる AssetBundle がないか調べる if (this.currentName.Equals(newName) && this.currentHash != newHash) { // アセットのインスタンスは残したまま、古い AssetBundle を解放してキャッシュからも破棄する this.currentBundle.Unload(false); if (Caching.IsVersionCached(newName, this.currentHash)) { Caching.ClearCachedVersion(newName, this.currentHash); } } } // BundleName と Hash を保持しておく this.currentName = newName; this.currentHash = newHash; } } AsyncOperationHandle download = default; try { // AssetBundle を抽出するために Load 前に Download download = Addressables.DownloadDependenciesAsync("Assets/Sprites/cat.png"); var resources = await download.Task as List<IAssetBundleResource>; this.currentBundle = resources[0].GetAssetBundle(); // Addressables 経由で Sprite を読み込んで表示 this.handle = Addressables.LoadAssetAsync<Sprite>("Assets/Sprites/cat.png"); this.thumbnailImage.sprite = await this.handle.Task; } finally { // Load が終わったら Download ハンドルは用済みなので解放 if (download.IsValid()) { Addressables.Release(download); } } } /// <summary> /// Mocha ボタン押下イベントハンドラ /// </summary> public async void OnMochaButtonClicked() { await SetCatAsset("Mocha"); } public void OnDestroy() { // いらなくなったら handle を Release する if (this.handle.IsValid()) { Addressables.Release(this.handle); } } }
Addressables.GetDownloadSizeAsync()
を使うとダウンロード済みだったり、今回みたいにアプリ実行中にアセット更新して差し替える場合ちゃんとサイズが取得できないことがある
そのため、下記の箇所で IResourceLocation.Data
を AssetBundleRequestOptions
にキャストして直接 BundleSize
を取得する
if (location.Data is AssetBundleRequestOptions sizeData) { #if UNITY_EDITOR EditorUtility.DisplayDialog($"{location.PrimaryKey}", $"{sizeData.BundleSize:#,0} bytes", "OK"); #endif }
これをお試し
同じアドレスのリモートアセットでも Cafe と Mocha で画像が異なるのでちゃんと別のサイズとして取得できた