Skip to content

Instantly share code, notes, and snippets.

@jeffvella
Last active December 11, 2023 12:26
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jeffvella/d41835d045902cc863228bbc32e9c4a3 to your computer and use it in GitHub Desktop.
Save jeffvella/d41835d045902cc863228bbc32e9c4a3 to your computer and use it in GitHub Desktop.
AddressablesLoader
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
using Object = UnityEngine.Object;
public class AddressableLabels
{
public const string Default = "default";
public const string Initialization = "initialization";
public const string Instantiate = "instantiate";
}
public class AddressablesLoader : MonoBehaviour
{
void Awake()
{
Addressables.ResourceManager.CreateChainOperation(AssetCache.LoadAsync(AddressableLabels.Initialization),
op1 => Addressables.LoadAssetsAsync<GameObject>(AddressableLabels.Instantiate, go => Instantiate(go)));
}
}
public static class AssetCache
{
private static Dictionary<string, CachedAssetResource> _assetReferences = new Dictionary<string, CachedAssetResource>();
public static AsyncOperationHandle DownloadResourcesHandle { get; private set; }
public static AsyncOperationHandle<IList<Object>> LoadAssetsHandle { get; private set; }
private static Dictionary<string, AsyncOperationHandle> _ops;
private static AsyncOperationHandle<IList<Object>> _loadChain;
private static Dictionary<int, string> _keysByIndex = new Dictionary<int, string>();
private static Dictionary<string, int> _indexByKey = new Dictionary<string, int>();
public delegate void AssetCacheEventHandler();
public static event AssetCacheEventHandler LoadCompleted;
public static AsyncOperationHandle<IList<Object>> LoadAsync(object key)
{
DownloadResourcesHandle = Addressables.DownloadDependenciesAsync(key);
// Now go through each addressable and cache the object.
LoadAssetsHandle = Addressables.ResourceManager.CreateChainOperation(DownloadResourcesHandle, LoadAssets);
return LoadAssetsHandle;
}
public static T Instantiate<T>(object key) where T : Object
{
// doesn't work yet on labels etc
return UnityEngine.Object.Instantiate(GetAsset<T>(key));
}
private static AsyncOperationHandle<IList<Object>> LoadAssets(AsyncOperationHandle arg)
{
//if (arg.Result is IEnumerable<IAssetBundleResource> bundles)
//{
// foreach (var bundleResource in bundles)
// {
// if (bundleResource is VirtualAssetBundle virtualAssetBundle)
// {
// Debug.Log($"VirtualAssetBundle: {virtualAssetBundle.Name}");
// }
// else
// {
// var bundle = bundleResource.GetAssetBundle();
// Debug.Log($"Bundle: {bundle?.name}");
// }
// }
//}
var locs = Addressables.ResourceLocators;
var toLoad = new List<IResourceLocation>();
var index = 0;
for (int i = 0; i < locs.Count; i++)
{
var loc = locs[i];
foreach (object objKey in loc.Keys)
{
if (!(objKey is string key))
continue;
if (!Guid.TryParse(key, out Guid keyGuid))
continue;
loc.Locate(key, typeof(UnityEngine.Object), out var locationsFromKey);
// Everything except those with a RuntimeKey have already been excluded;
var location = locationsFromKey[0];
var entry = new CachedAssetResource
{
RunTimeKeyGuid = keyGuid,
RunTimeKeyString = key,
ResourceLocation = location
};
toLoad.Add(location);
_assetReferences[location.ToString()] = entry;
_assetReferences[key] = entry;
_keysByIndex[index] = key;
_indexByKey[key] = index;
index++;
//Debug.Log($"Processed Addressable: Key={key}, Path={location}");
}
}
_loadChain = Addressables.LoadAssetsAsync<UnityEngine.Object>(toLoad, OnItemsLoadCompleted);
_loadChain.Completed += LoadChain_Completed;
return _loadChain;
}
private static void LoadChain_Completed(AsyncOperationHandle<IList<Object>> obj)
{
for (int i = 0; i < obj.Result.Count; i++)
{
var resource = _assetReferences[_keysByIndex[i]];
resource.Asset = obj.Result[i];
}
var handler = LoadCompleted;
handler?.Invoke();
//Debug.Log($"LoadChain_Completed: TotalAssets={obj.Result.Count}");
}
private static void OnItemsLoadCompleted(Object obj)
{
//Debug.Log($"Loaded Asset: {obj.name}");
}
public class CachedAssetResource
{
public IResourceLocation ResourceLocation;
public Object Asset;
public Guid RunTimeKeyGuid;
public string RunTimeKeyString;
}
public static T GetAsset<T>(object runtimeKey) where T : UnityEngine.Object
{
var key = EvaluateKey(runtimeKey);
if (_assetReferences.TryGetValue(key, out var assetReference))
{
return (T)assetReference.Asset;
}
return default;
}
private static string EvaluateKey(object obj)
{
return (string)(obj is IKeyEvaluator evaluator ? evaluator.RuntimeKey : obj);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment