mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-06-22 21:03:43 +00:00
feat: refactor AssetReference
将资源弱引用的公共逻辑抽象到基类中,并新增对 Texture2D 的支持。
This commit is contained in:
@@ -1,16 +1,22 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
|
||||||
[CustomPropertyDrawer(typeof(GameObjectReference))]
|
[CustomPropertyDrawer(typeof(AssetReference), true)]
|
||||||
public class GameObjectReferenceDrawer : PropertyDrawer
|
public class AssetReferenceDrawer : PropertyDrawer
|
||||||
{
|
{
|
||||||
private const float LineSpacing = 2f;
|
private const float LineSpacing = 2f;
|
||||||
|
|
||||||
|
private Type _assetType;
|
||||||
|
|
||||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||||
{
|
{
|
||||||
SerializedProperty packageNameProp = property.FindPropertyRelative("_packageName");
|
SerializedProperty packageNameProp = property.FindPropertyRelative("_packageName");
|
||||||
SerializedProperty assetGUIDProp = property.FindPropertyRelative("_assetGUID");
|
SerializedProperty assetGUIDProp = property.FindPropertyRelative("_assetGUID");
|
||||||
|
|
||||||
|
Type assetType = GetAssetType();
|
||||||
|
|
||||||
EditorGUI.BeginProperty(position, label, property);
|
EditorGUI.BeginProperty(position, label, property);
|
||||||
{
|
{
|
||||||
float lineHeight = EditorGUIUtility.singleLineHeight;
|
float lineHeight = EditorGUIUtility.singleLineHeight;
|
||||||
@@ -19,19 +25,19 @@ public class GameObjectReferenceDrawer : PropertyDrawer
|
|||||||
// 绘制 PackageName
|
// 绘制 PackageName
|
||||||
packageNameProp.stringValue = EditorGUI.TextField(line, "Package Name", packageNameProp.stringValue);
|
packageNameProp.stringValue = EditorGUI.TextField(line, "Package Name", packageNameProp.stringValue);
|
||||||
|
|
||||||
// 加载 GameObject
|
// 加载当前资源对象
|
||||||
string assetGUID = assetGUIDProp.stringValue;
|
string assetGUID = assetGUIDProp.stringValue;
|
||||||
GameObject current = null;
|
UnityEngine.Object current = null;
|
||||||
if (string.IsNullOrEmpty(assetGUID) == false)
|
if (string.IsNullOrEmpty(assetGUID) == false)
|
||||||
{
|
{
|
||||||
string assetPath = AssetDatabase.GUIDToAssetPath(assetGUID);
|
string assetPath = AssetDatabase.GUIDToAssetPath(assetGUID);
|
||||||
if (string.IsNullOrEmpty(assetPath) == false)
|
if (string.IsNullOrEmpty(assetPath) == false)
|
||||||
current = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
current = AssetDatabase.LoadAssetAtPath(assetPath, assetType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制 GameObject
|
// 绘制资源对象字段
|
||||||
line.y += lineHeight + LineSpacing;
|
line.y += lineHeight + LineSpacing;
|
||||||
GameObject newAsset = (GameObject)EditorGUI.ObjectField(line, "Game Object", current, typeof(GameObject), false);
|
UnityEngine.Object newAsset = EditorGUI.ObjectField(line, assetType.Name, current, assetType, false);
|
||||||
if (newAsset != current)
|
if (newAsset != current)
|
||||||
{
|
{
|
||||||
if (newAsset == null)
|
if (newAsset == null)
|
||||||
@@ -46,7 +52,7 @@ public class GameObjectReferenceDrawer : PropertyDrawer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 绘制 AssetGUID
|
// 绘制 AssetGUID(只读)
|
||||||
line.y += lineHeight + LineSpacing;
|
line.y += lineHeight + LineSpacing;
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
EditorGUI.BeginDisabledGroup(true);
|
||||||
EditorGUI.TextField(line, "Asset GUID", assetGUIDProp.stringValue);
|
EditorGUI.TextField(line, "Asset GUID", assetGUIDProp.stringValue);
|
||||||
@@ -54,8 +60,31 @@ public class GameObjectReferenceDrawer : PropertyDrawer
|
|||||||
}
|
}
|
||||||
EditorGUI.EndProperty();
|
EditorGUI.EndProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||||
{
|
{
|
||||||
return EditorGUIUtility.singleLineHeight * 3 + LineSpacing * 2;
|
return EditorGUIUtility.singleLineHeight * 3 + LineSpacing * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通过反射获取字段对应子类的 AssetType
|
||||||
|
/// </summary>
|
||||||
|
private Type GetAssetType()
|
||||||
|
{
|
||||||
|
if (_assetType != null)
|
||||||
|
return _assetType;
|
||||||
|
|
||||||
|
Type fieldType = fieldInfo.FieldType;
|
||||||
|
|
||||||
|
// 兼容数组
|
||||||
|
if (fieldType.IsArray)
|
||||||
|
fieldType = fieldType.GetElementType();
|
||||||
|
// 兼容 List<T>
|
||||||
|
else if (fieldType.IsGenericType && typeof(IEnumerable).IsAssignableFrom(fieldType))
|
||||||
|
fieldType = fieldType.GetGenericArguments()[0];
|
||||||
|
|
||||||
|
var instance = (AssetReference)Activator.CreateInstance(fieldType);
|
||||||
|
_assetType = instance.AssetType;
|
||||||
|
return _assetType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 53eb285fc3a7b614089a000f8c9c738c
|
guid: ee2a8d68b06fc434c8d70a9e1d94caf6
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -3,19 +3,19 @@ using UnityEngine;
|
|||||||
using YooAsset;
|
using YooAsset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 游戏对象弱引用,序列化时只保存资源 GUID
|
/// 资源弱引用基类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class GameObjectReference
|
public abstract class AssetReference
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private string _packageName = "DefaultPackage";
|
protected string _packageName = "DefaultPackage";
|
||||||
|
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private string _assetGUID = "";
|
protected string _assetGUID = "";
|
||||||
|
|
||||||
[NonSerialized]
|
[NonSerialized]
|
||||||
private AssetHandle _handle;
|
protected AssetHandle _handle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 资源所属的包裹名称
|
/// 资源所属的包裹名称
|
||||||
@@ -27,6 +27,16 @@ public class GameObjectReference
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string AssetGUID => _assetGUID;
|
public string AssetGUID => _assetGUID;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前加载句柄(未加载时为 null)
|
||||||
|
/// </summary>
|
||||||
|
public AssetHandle Handle => _handle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 该引用负责加载的资源类型,由子类指定
|
||||||
|
/// </summary>
|
||||||
|
public abstract Type AssetType { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查运行时引用键是否有效
|
/// 检查运行时引用键是否有效
|
||||||
@@ -37,18 +47,18 @@ public class GameObjectReference
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var package = YooAssets.GetPackage(_packageName);
|
var package = YooAssets.GetPackage(_packageName);
|
||||||
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, typeof(GameObject));
|
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, AssetType);
|
||||||
return assetInfo.IsValid;
|
return assetInfo.IsValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步加载引用的游戏对象
|
/// 异步加载引用的资源
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>加载操作句柄</returns>
|
/// <returns>加载操作句柄</returns>
|
||||||
public AssetHandle LoadAssetAsync()
|
public AssetHandle LoadAssetAsync()
|
||||||
{
|
{
|
||||||
if (_handle != null)
|
if (_handle != null)
|
||||||
throw new InvalidOperationException("GameObject reference has already been loaded. Release it first.");
|
throw new InvalidOperationException($"{GetType().Name} has already been loaded. Release it first.");
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(_packageName))
|
if (string.IsNullOrEmpty(_packageName))
|
||||||
throw new ArgumentException("Package name is not set.", nameof(_packageName));
|
throw new ArgumentException("Package name is not set.", nameof(_packageName));
|
||||||
@@ -56,7 +66,7 @@ public class GameObjectReference
|
|||||||
throw new ArgumentException("Asset GUID is not set.", nameof(_assetGUID));
|
throw new ArgumentException("Asset GUID is not set.", nameof(_assetGUID));
|
||||||
|
|
||||||
var package = YooAssets.GetPackage(_packageName);
|
var package = YooAssets.GetPackage(_packageName);
|
||||||
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, typeof(GameObject));
|
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, AssetType);
|
||||||
_handle = package.LoadAssetAsync(assetInfo);
|
_handle = package.LoadAssetAsync(assetInfo);
|
||||||
return _handle;
|
return _handle;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 15552077c0d6ff441a4cd62af62b7d5a
|
guid: 7de4fe4f4d6834c47977a97c7ad20bd3
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GameObject 资源弱引用
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class AssetReferenceGameObject : AssetReference
|
||||||
|
{
|
||||||
|
public override Type AssetType => typeof(GameObject);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 764d480d7edd8cd48b8105dc6b24bd2a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -3,36 +3,58 @@ using UnityEngine;
|
|||||||
using YooAsset;
|
using YooAsset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 演示如何使用 GameObjectReference 弱引用加载并实例化游戏对象
|
/// 演示如何使用 AssetReference 弱引用加载不同类型的资源
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AssetReferenceSample : MonoBehaviour
|
public class AssetReferenceSample : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField]
|
[SerializeField]
|
||||||
private GameObjectReference _reference;
|
private AssetReferenceGameObject _prefabReference;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private AssetReferenceTexture2D _textureReference;
|
||||||
|
|
||||||
private IEnumerator Start()
|
private IEnumerator Start()
|
||||||
{
|
{
|
||||||
if (_reference.RuntimeKeyIsValid() == false)
|
// 加载并实例化预制体
|
||||||
|
if (_prefabReference.RuntimeKeyIsValid())
|
||||||
{
|
{
|
||||||
yield break;
|
AssetHandle handle = _prefabReference.LoadAssetAsync();
|
||||||
}
|
|
||||||
|
|
||||||
AssetHandle handle = _reference.LoadAssetAsync();
|
|
||||||
yield return handle;
|
yield return handle;
|
||||||
|
|
||||||
if (handle.Status == EOperationStatus.Succeeded)
|
if (handle.Status == EOperationStatus.Succeeded)
|
||||||
{
|
{
|
||||||
GameObject instance = handle.InstantiateSync(new InstantiateOptions(true, transform, false));
|
GameObject instance = handle.InstantiateSync(new InstantiateOptions(true, transform, false));
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
Debug.LogError($"Failed to instantiate GameObject reference '{_reference.AssetGUID}'.");
|
Debug.LogError($"Failed to instantiate GameObject reference '{_prefabReference.AssetGUID}'.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Debug.LogError($"Failed to load GameObject reference '{_reference.AssetGUID}': {handle.Error}.");
|
Debug.LogError($"Failed to load GameObject reference '{_prefabReference.AssetGUID}': {handle.Error}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载纹理并赋值给渲染器材质
|
||||||
|
if (_textureReference.RuntimeKeyIsValid())
|
||||||
|
{
|
||||||
|
AssetHandle handle = _textureReference.LoadAssetAsync();
|
||||||
|
yield return handle;
|
||||||
|
|
||||||
|
if (handle.Status == EOperationStatus.Succeeded)
|
||||||
|
{
|
||||||
|
var renderer = GetComponent<Renderer>();
|
||||||
|
if (renderer != null)
|
||||||
|
renderer.material.mainTexture = handle.AssetObject as Texture2D;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogError($"Failed to load Texture2D reference '{_textureReference.AssetGUID}': {handle.Error}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnDestroy()
|
private void OnDestroy()
|
||||||
{
|
{
|
||||||
_reference.ReleaseAsset();
|
_prefabReference?.ReleaseAsset();
|
||||||
|
_textureReference?.ReleaseAsset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture2D 资源弱引用
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class AssetReferenceTexture2D : AssetReference
|
||||||
|
{
|
||||||
|
public override Type AssetType => typeof(Texture2D);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0c6c6d8423826d24083eb0608e0fd023
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture3D 资源弱引用
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class AssetReferenceTexture3D : AssetReference
|
||||||
|
{
|
||||||
|
public override Type AssetType => typeof(Texture3D);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: be5c51911e8f45a45b7ed11af7d0b50c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Reference in New Issue
Block a user