using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; #if UNITY_EDITOR using UnityEditor; #endif /// <summary> /// Creates an AssetReference that is restricted to having a specific Component. /// * This is the class that inherits from AssetReference. It is generic and does not specify which Components it might care about. A concrete child of this class is required for serialization to work. /// * At edit-time it validates that the asset set on it is a GameObject with the required Component. /// * At runtime it can load/instantiate the GameObject, then return the desired component. API matches base class (LoadAssetAsync & InstantiateAsync). /// </summary> /// <typeparam name="TComponent">The component type.</typeparam> public class ComponentReference<TComponent> : AssetReference { /// <inheritdoc /> public ComponentReference(string guid) : base(guid) { } /// <inheritdoc /> public new AsyncOperationHandle<TComponent> InstantiateAsync(Vector3 position, Quaternion rotation, Transform parent = null) { return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.InstantiateAsync(position, Quaternion.identity, parent), GameObjectReady); } /// <inheritdoc /> public new AsyncOperationHandle<TComponent> InstantiateAsync(Transform parent = null, bool instantiateInWorldSpace = false) { return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.InstantiateAsync(parent, instantiateInWorldSpace), GameObjectReady); } /// <inheritdoc /> public AsyncOperationHandle<TComponent> LoadAssetAsync() { return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.LoadAssetAsync<GameObject>(), GameObjectReady); } /// <inheritdoc /> AsyncOperationHandle<TComponent> GameObjectReady(AsyncOperationHandle<GameObject> arg) { var comp = arg.Result.GetComponent<TComponent>(); return Addressables.ResourceManager.CreateCompletedOperation<TComponent>(comp, string.Empty); } /// <summary> /// Validates that the assigned asset has the component type /// </summary> /// <param name="obj"></param> /// <returns></returns> public override bool ValidateAsset(Object obj) { var go = obj as GameObject; return go != null && go.GetComponent<TComponent>() != null; } /// <summary> /// Validates that the assigned asset has the component type, but only in the Editor /// </summary> /// <param name="path"></param> /// <returns></returns> public override bool ValidateAsset(string path) { #if UNITY_EDITOR //this load can be expensive... var go = AssetDatabase.LoadAssetAtPath<GameObject>(path); return go != null && go.GetComponent<TComponent>() != null; #else return false; #endif } /// <inheritdoc /> public void ReleaseInstance(AsyncOperationHandle<TComponent> op) { // Release the instance var component = op.Result as Component; if (component != null) { Addressables.ReleaseInstance(component.gameObject); } // Release the handle Addressables.Release(op); } }