Unity官方案例-Addressables-Sample-笔记(3)-ComponentReference(自定义组件引用)

记录一下Addressables-Sample项目中的脚本和学习的笔记,主要是熟悉API及其使用方式.方便日后工作查询.

项目地址:

github: Addressables-Sample

Unity官方教程

Bilibili-Unity官方教程 Addressables【中文字幕】

3.ComponentReference

此示例创建一个自己的泛型AssetReference,该AssetReference仅限于具有特定组件。

3.1 Scenes/SampleScene

Scripts/ComponentReference - ComponentReference

using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class ComponentReference<TComponent> : AssetReference
{
    public ComponentReference(string guid) : base(guid)
    {
    }
    
    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);
    }
   
    public new AsyncOperationHandle<TComponent> InstantiateAsync(Transform parent = null, bool instantiateInWorldSpace = false)
    {
        return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.InstantiateAsync(parent, instantiateInWorldSpace), GameObjectReady);
    }
    public AsyncOperationHandle<TComponent> LoadAssetAsync()
    {
        return Addressables.ResourceManager.CreateChainOperation<TComponent, GameObject>(base.LoadAssetAsync<GameObject>(), GameObjectReady);
    }

    AsyncOperationHandle<TComponent> GameObjectReady(AsyncOperationHandle<GameObject> arg)
    {
        var comp = arg.Result.GetComponent<TComponent>();
        return Addressables.ResourceManager.CreateCompletedOperation<TComponent>(comp, string.Empty);
    }

    public override bool ValidateAsset(Object obj)
    {
        var go = obj as GameObject;
        return go != null && go.GetComponent<TComponent>() != null;
    }
    
    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
    }

    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);
    }

}


  • 这是从AssetReference继承的类。它是通用的,没有指定它可能关心哪些组件。序列化工作需要此类的具体子类。
  • 在编辑时,它会验证其上的资产集是否是具有所需组件的游戏对象。
  • 在运行时,它可以加载/实例化游戏对象,然后返回所需的组件。API匹配基类(LoadAssetAsync和InstanceEasync)。

Scripts/ColorChanger - ColorChanger & ComponentReferenceColorChanger

using System;
using UnityEngine;

public class ColorChanger : MonoBehaviour
{
    public void SetColor(Color col)
    {
        var rend = GetComponent<MeshRenderer>();
        var material = rend.material;
        material.color = col;
    }
}

[Serializable]
public class ComponentReferenceColorChanger : ComponentReference<ColorChanger>
{
    public ComponentReferenceColorChanger(string guid)
        : base(guid) { }
}
    

  • 我们选择关注的组件类型。
  • 请注意,此文件包含ComponentReference的具体版本。这是必要的,因为如果您的游戏代码只是指定了一个ComponentReference,它就无法序列化或显示在检查器中。这个ComponentReferenceColorChanger使序列化和inspector UI工作。
  • 应通过ComponentReference类中的ReleaseInstance()释放ComponentReference。要直接发布实例,请参阅ReleaseInstance实现以了解需求。

Scripts/Spawner

using System;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;

public class Spawner : MonoBehaviour
{
    public ComponentReferenceColorChanger ColorShifterReference;
    public ColorChanger ColorShifterDirect;

    int m_Counter = 10000;

    void FixedUpdate()
    {
        m_Counter++;
        if (m_Counter == 15)
        {
            //note that this could work as an Instantiate or a Load. 
            //ColorShifterReference.LoadComponentAsync().Completed += LoadDone;
            ColorShifterReference.InstantiateAsync().Completed += InstantiateDone;
        }
        else if (m_Counter > 30)
        {
            ColorChanger changer = Instantiate(ColorShifterDirect);
            changer.SetColor(RandomColor());
            m_Counter = 0;
        }
    }

    //if using the LoadComponentAsync version above...
    void LoadDone(AsyncOperationHandle<ColorChanger> obj)
    {
        if (obj.Result != null)
        {
            ColorChanger changer = Instantiate(obj.Result);
            changer.SetColor(RandomColor());
        }
    }

    //if using the InstantiateComponentAsync version above...
    void InstantiateDone(AsyncOperationHandle<ColorChanger> obj)
    {
        if(obj.Result != null)
            obj.Result.SetColor(RandomColor());
    }

    
    
    Color RandomColor()
    {
        return new Color(UnityEngine.Random.Range(0.0f, 1.0f), UnityEngine.Random.Range(0.0f, 1.0f), UnityEngine.Random.Range(0.0f, 1.0f));
    }

}
  • 对前面两个脚本的应用.

猜你喜欢

转载自blog.csdn.net/kill566666/article/details/119151211