Created
May 3, 2020 16:10
-
-
Save jeffvella/779736613a6d36b26aac0029cfa71f72 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
using UnityEngine.AddressableAssets; | |
using UnityEngine.ResourceManagement.AsyncOperations; | |
using UnityEngine.ResourceManagement.ResourceLocations; | |
using UnityEngine.ResourceManagement.ResourceProviders; | |
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) | |
{ | |
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Unity.Collections; | |
using Unity.Entities; | |
using UnityEngine; | |
using UnityEngine.AddressableAssets; | |
/// <summary> | |
/// Implicitly convertable version of AssetReference, that can be stored in components. | |
/// Holds the RuntimeKey used to find it again at runtime through Addressables. | |
/// </summary> | |
public struct NativeAssetReference : IComponentData, IEquatable<NativeAssetReference>, IKeyEvaluator | |
{ | |
public NativeString512 RuntimeKey; | |
public int Hash; | |
public static implicit operator AssetReference(NativeAssetReference instance) | |
{ | |
return new AssetReference(instance.RuntimeKey.ToString()); | |
} | |
public static implicit operator NativeAssetReference(AssetReference instance) | |
{ | |
Debug.Assert(instance.RuntimeKeyIsValid(), $"The AssetReference is not valid. Key={instance.RuntimeKey}"); | |
var key = (string)instance.RuntimeKey; | |
var nativeKey = new NativeString512(key); | |
var result = new NativeAssetReference | |
{ | |
RuntimeKey = nativeKey, | |
Hash = CreateHash(key) | |
}; | |
return result; | |
} | |
public bool IsValid => Hash != 0; | |
public static int CreateHash(string input) | |
{ | |
var hash = 0; | |
foreach (var t in input) | |
hash = (hash << 5) + hash + t; | |
return hash; | |
} | |
public bool Equals(NativeAssetReference other) => Hash == other.Hash; | |
public override bool Equals(object obj) => obj is NativeAssetReference other && Equals(other); | |
public override int GetHashCode() => Hash; | |
public override string ToString() => $"{Hash}, Key={RuntimeKey.ToString()}"; | |
object IKeyEvaluator.RuntimeKey => RuntimeKey.ToString(); | |
bool IKeyEvaluator.RuntimeKeyIsValid() => IsValid; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment