mirror of
https://github.com/tuyoogame/YooAsset.git
synced 2026-06-09 20:23:42 +00:00
feat: refactor AssetReference
将资源弱引用的公共逻辑抽象到基类中,并新增对 Texture2D 的支持。
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
[CustomPropertyDrawer(typeof(GameObjectReference))]
|
||||
public class GameObjectReferenceDrawer : PropertyDrawer
|
||||
[CustomPropertyDrawer(typeof(AssetReference), true)]
|
||||
public class AssetReferenceDrawer : PropertyDrawer
|
||||
{
|
||||
private const float LineSpacing = 2f;
|
||||
|
||||
private Type _assetType;
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
SerializedProperty packageNameProp = property.FindPropertyRelative("_packageName");
|
||||
SerializedProperty assetGUIDProp = property.FindPropertyRelative("_assetGUID");
|
||||
|
||||
Type assetType = GetAssetType();
|
||||
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
{
|
||||
float lineHeight = EditorGUIUtility.singleLineHeight;
|
||||
@@ -19,19 +25,19 @@ public class GameObjectReferenceDrawer : PropertyDrawer
|
||||
// 绘制 PackageName
|
||||
packageNameProp.stringValue = EditorGUI.TextField(line, "Package Name", packageNameProp.stringValue);
|
||||
|
||||
// 加载 GameObject
|
||||
// 加载当前资源对象
|
||||
string assetGUID = assetGUIDProp.stringValue;
|
||||
GameObject current = null;
|
||||
UnityEngine.Object current = null;
|
||||
if (string.IsNullOrEmpty(assetGUID) == false)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(assetGUID);
|
||||
if (string.IsNullOrEmpty(assetPath) == false)
|
||||
current = AssetDatabase.LoadAssetAtPath<GameObject>(assetPath);
|
||||
current = AssetDatabase.LoadAssetAtPath(assetPath, assetType);
|
||||
}
|
||||
|
||||
// 绘制 GameObject
|
||||
// 绘制资源对象字段
|
||||
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 == null)
|
||||
@@ -46,7 +52,7 @@ public class GameObjectReferenceDrawer : PropertyDrawer
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制 AssetGUID
|
||||
// 绘制 AssetGUID(只读)
|
||||
line.y += lineHeight + LineSpacing;
|
||||
EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUI.TextField(line, "Asset GUID", assetGUIDProp.stringValue);
|
||||
@@ -54,8 +60,31 @@ public class GameObjectReferenceDrawer : PropertyDrawer
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
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
|
||||
guid: 53eb285fc3a7b614089a000f8c9c738c
|
||||
guid: ee2a8d68b06fc434c8d70a9e1d94caf6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -3,19 +3,19 @@ using UnityEngine;
|
||||
using YooAsset;
|
||||
|
||||
/// <summary>
|
||||
/// 游戏对象弱引用,序列化时只保存资源 GUID
|
||||
/// 资源弱引用基类
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class GameObjectReference
|
||||
public abstract class AssetReference
|
||||
{
|
||||
[SerializeField]
|
||||
private string _packageName = "DefaultPackage";
|
||||
protected string _packageName = "DefaultPackage";
|
||||
|
||||
[SerializeField]
|
||||
private string _assetGUID = "";
|
||||
protected string _assetGUID = "";
|
||||
|
||||
[NonSerialized]
|
||||
private AssetHandle _handle;
|
||||
protected AssetHandle _handle;
|
||||
|
||||
/// <summary>
|
||||
/// 资源所属的包裹名称
|
||||
@@ -27,6 +27,16 @@ public class GameObjectReference
|
||||
/// </summary>
|
||||
public string AssetGUID => _assetGUID;
|
||||
|
||||
/// <summary>
|
||||
/// 当前加载句柄(未加载时为 null)
|
||||
/// </summary>
|
||||
public AssetHandle Handle => _handle;
|
||||
|
||||
/// <summary>
|
||||
/// 该引用负责加载的资源类型,由子类指定
|
||||
/// </summary>
|
||||
public abstract Type AssetType { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 检查运行时引用键是否有效
|
||||
@@ -37,18 +47,18 @@ public class GameObjectReference
|
||||
return false;
|
||||
|
||||
var package = YooAssets.GetPackage(_packageName);
|
||||
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, typeof(GameObject));
|
||||
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, AssetType);
|
||||
return assetInfo.IsValid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步加载引用的游戏对象
|
||||
/// 异步加载引用的资源
|
||||
/// </summary>
|
||||
/// <returns>加载操作句柄</returns>
|
||||
public AssetHandle LoadAssetAsync()
|
||||
{
|
||||
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))
|
||||
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));
|
||||
|
||||
var package = YooAssets.GetPackage(_packageName);
|
||||
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, typeof(GameObject));
|
||||
var assetInfo = package.GetAssetInfoByGuid(_assetGUID, AssetType);
|
||||
_handle = package.LoadAssetAsync(assetInfo);
|
||||
return _handle;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 15552077c0d6ff441a4cd62af62b7d5a
|
||||
guid: 7de4fe4f4d6834c47977a97c7ad20bd3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 演示如何使用 GameObjectReference 弱引用加载并实例化游戏对象
|
||||
/// 演示如何使用 AssetReference 弱引用加载不同类型的资源
|
||||
/// </summary>
|
||||
public class AssetReferenceSample : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private GameObjectReference _reference;
|
||||
private AssetReferenceGameObject _prefabReference;
|
||||
|
||||
[SerializeField]
|
||||
private AssetReferenceTexture2D _textureReference;
|
||||
|
||||
private IEnumerator Start()
|
||||
{
|
||||
if (_reference.RuntimeKeyIsValid() == false)
|
||||
// 加载并实例化预制体
|
||||
if (_prefabReference.RuntimeKeyIsValid())
|
||||
{
|
||||
yield break;
|
||||
AssetHandle handle = _prefabReference.LoadAssetAsync();
|
||||
yield return handle;
|
||||
|
||||
if (handle.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
GameObject instance = handle.InstantiateSync(new InstantiateOptions(true, transform, false));
|
||||
if (instance == null)
|
||||
Debug.LogError($"Failed to instantiate GameObject reference '{_prefabReference.AssetGUID}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Failed to load GameObject reference '{_prefabReference.AssetGUID}': {handle.Error}.");
|
||||
}
|
||||
}
|
||||
|
||||
AssetHandle handle = _reference.LoadAssetAsync();
|
||||
yield return handle;
|
||||
// 加载纹理并赋值给渲染器材质
|
||||
if (_textureReference.RuntimeKeyIsValid())
|
||||
{
|
||||
AssetHandle handle = _textureReference.LoadAssetAsync();
|
||||
yield return handle;
|
||||
|
||||
if (handle.Status == EOperationStatus.Succeeded)
|
||||
{
|
||||
GameObject instance = handle.InstantiateSync(new InstantiateOptions(true, transform, false));
|
||||
if (instance == null)
|
||||
Debug.LogError($"Failed to instantiate GameObject reference '{_reference.AssetGUID}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError($"Failed to load GameObject reference '{_reference.AssetGUID}': {handle.Error}.");
|
||||
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()
|
||||
{
|
||||
_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