IAsyncOperationExtensions:
using System;
using System.Runtime.CompilerServices;
using UnityEngine.ResourceManagement.AsyncOperations;
public static class IAsyncOperationExtensions
{
public static AsyncOperationAwaiter GetAwaiter(this AsyncOperationHandle operation)
{
return new AsyncOperationAwaiter(operation);
}
public static AsyncOperationAwaiter<T> GetAwaiter<T>(this AsyncOperationHandle<T> operation) where T : class
{
return new AsyncOperationAwaiter<T>(operation);
}
public readonly struct AsyncOperationAwaiter : INotifyCompletion
{
readonly AsyncOperationHandle _operation;
public AsyncOperationAwaiter(AsyncOperationHandle operation)
{
_operation = operation;
}
public bool IsCompleted => _operation.Status != AsyncOperationStatus.None;
public void OnCompleted(Action continuation) => _operation.Completed += (op) => continuation?.Invoke();
public object GetResult() => _operation.Result;
}
public readonly struct AsyncOperationAwaiter<T> : INotifyCompletion where T : class
{
readonly AsyncOperationHandle<T> _operation;
public AsyncOperationAwaiter(AsyncOperationHandle<T> operation)
{
_operation = operation;
}
public bool IsCompleted => _operation.Status != AsyncOperationStatus.None;
public void OnCompleted(Action continuation) => _operation.Completed += (op) => continuation?.Invoke();
public T GetResult() => _operation.Result;
}
}
AddressablesManager:
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
using UnityEngine.ResourceManagement.AsyncOperations;
namespace AddressablesManagement
{
public class AddressablesManager : MonoBehaviour
{
private static AddressablesManager _instance;
private bool _currentlyLoading;
private Scene _currentlyLoadingScene;
#region properties
/// <summary>
/// 当前是否正在加载对象
/// </summary>
public bool CurrentlyLoading
{
get { return _currentlyLoading; }
private set { _currentlyLoading = value; }
}
/// <summary>
/// 该类的实例对象
/// </summary>
public static AddressablesManager Instance
{
get
{
if (_instance == null)
{
Create();
}
return _instance;
}
}
#endregion
private void Awake()
{
if (_instance == null)
{
_instance = this;
DontDestroyOnLoad(this);
}
else
{
Destroy(this);
}
}
#region public methods
/// <summary>
/// 加载场景
/// </summary>
/// <param name="sceneName">要加载场景的名称</param>
/// <param name="loadMode">场景加载的方式</param>
public Task<Scene> LoadScene(string sceneName, LoadSceneMode loadMode)
{
_currentlyLoadingScene = default;
_currentlyLoadingScene.name = "";
var handle = Addressables.LoadSceneAsync(sceneName, loadMode);
handle.Completed += AddressablesManager_OnSceneLoadCompleted;
if (string.IsNullOrEmpty(_currentlyLoadingScene.name))
{
Task.Delay(1);
}
return Task.Run(() => _currentlyLoadingScene);
}
private void AddressablesManager_OnSceneLoadCompleted(AsyncOperationHandle<SceneInstance> obj)
{
if (obj.Status == AsyncOperationStatus.Succeeded)
{
_currentlyLoadingScene = obj.Result.Scene;
}
}
/// <summary>
/// 按照给定模式(Single/Additive)加载场景到当前场景中
/// </summary>
/// <param name="sceneName">加载场景的名称</param>
/// <param name="loadMode">场景加载模式</param>
public async Task OnlyLoadScene(string sceneName, LoadSceneMode loadMode)
{
await Task.Run(() => Addressables.LoadSceneAsync(sceneName, loadMode));
}
/// <summary>
/// 从内存中异步卸载给定场景。
/// </summary>
/// <param name="scene">要卸载的场景对象</param>
public async Task UnloadScene(SceneInstance scene)
{
Addressables.UnloadSceneAsync(scene);
}
/// <summary>
/// 实例化对象并且给定位置和旋转
/// </summary>
/// <param name="path">要实例化对象的名称</param>
/// <param name="position">实例化对象的位置</param>
/// <param name="rotation">实例化对象的旋转</param>
/// <returns>返回要实例化的游戏对象集</returns>
public async Task<GameObject> InstantiateGameObject(string path, Vector3 position, Quaternion rotation)
{
return await Addressables.InstantiateAsync(path, position, rotation);
}
/// <summary>
/// 实例化游戏中的默认位置和旋转位置。
/// </summary>
/// <param name="path">游戏对象所在的项目路径。</param>
/// <returns>返回要实例化的游戏对象集</returns>
public async Task<GameObject> InstantiateGameObject(string path)
{
return await Addressables.InstantiateAsync(path, Vector3.zero, Quaternion.identity);
}
/// <summary>
/// 将 T 类型的对象加载到内存中。
/// </summary>
/// <typeparam name="T">所要加载对象的类型</typeparam>
/// <param name="path">要在可寻址系统中加载的对象的路径。</param>
/// <returns>返回 T 类型的对象。</returns>
public async Task<T> Load<T>(string path) where T : class
{
return await Addressables.LoadAssetAsync<T>(path);
}
/// <summary>
/// 按给定路径预加载对象的所有依赖项
/// </summary>
/// <param name="path">要从中加载依赖项的对象的路径。</param>
public async Task DownloadDependencies(string path)
{
await Addressables.DownloadDependenciesAsync(path);
}
/// <summary>
/// 将给定标签的所有资源加载到内存中。
/// </summary>
/// <typeparam name="T">索要加载资源的类型</typeparam>
/// <param name="label">在要加载的对象的可寻址对象中标记标签。</param>
/// <param name="callback">加载后执行的回调</param>
/// <returns>返回包含 T 类型元素的列表。</returns>
public async Task<List<T>> LoadAssetsByLabel<T>(string label, Action<T> callback = null) where T : class
{
return await Addressables.LoadAssetsAsync<T>(label, callback) as List<T>;
}
/// <summary>
/// 从内存中释放预制件并销毁其在当前活动场景中的实例。
/// </summary>
/// <param name="obj">要释放的预制件的游戏对象引用。</param>
public void ReleaseInstance(ref GameObject obj)
{
if (obj != null)
Addressables.ReleaseInstance(obj);
}
/// <summary>
/// 从内存中释放给定对象。
/// </summary>
/// <typeparam name="T">要释放的对象的类型。</typeparam>
/// <param name="obj">要释放的对象引用。</param>
public void ReleaseAsset<T>(ref T obj) where T : class
{
if (obj != null)
Addressables.Release(obj);
}
#endregion
/// <summary>
/// 创建以可寻址管理器为组件的游戏对象。
/// </summary>
private static void Create()
{
new GameObject("AddressablesManager").AddComponent<AddressablesManager>();
}
private void OnApplicationQuit()
{
StopAllCoroutines();
}
}
}
以下脚本为使用示例脚本:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.ResourceManagement.ResourceProviders;
namespace AddressablesManagement
{
public class AddressablesExample : MonoBehaviour
{
public GameObject loneGameObject;
public GameObject[] testObjects = new GameObject[50];
public List<Material> materials;
public List<Sprite> _sprites;
public List<string> listTest;
public Sprite sprite;
private Vector3 startingPos;
private Scene sceneToLoad;
void Start()
{
// materials = new List<Material>(3);
// startingPos = transform.position;
LoadScene("SceneTest", LoadSceneMode.Single);
// InstantiateSingleObject("TestSphere");
// TestInstantiateObjects();
// TestLoadByLabel();
// LoadSprite("BG");
// TestLoadByLabel_Sprite();
// LoadFromList(listTest);
}
async void TestLoadByLabel()
{
materials = await AddressablesManager.Instance.LoadAssetsByLabel<Material>("materials");
}
async void TestLoadByLabel_Sprite()
{
_sprites = await AddressablesManager.Instance.LoadAssetsByLabel<Sprite>("sprites");
}
/// <summary>
/// 生成多个物体
/// </summary>
async void TestInstantiateObjects()
{
Vector3 pos = startingPos;
for (int i = 0; i < testObjects.Length; i++)
{
testObjects[i] = await AddressablesManager.Instance.InstantiateGameObject("TestObject");
testObjects[i].transform.position = pos;
pos += new Vector3(2f, 0, 0);
}
}
/// <summary>
/// 根据路径加载对象
/// </summary>
/// <param name="path"></param>
async void InstantiateSingleObject(string path)
{
loneGameObject = await AddressablesManager.Instance.InstantiateGameObject(path);
}
/// <summary>
/// 根据路径加载图片
/// </summary>
/// <param name="path">精灵路径</param>
async void LoadSprite(string path)
{
sprite = await AddressablesManager.Instance.Load<Sprite>(path);
}
/// <summary>
/// 加载场景
/// </summary>
/// <param name="sceneName"></param>
/// <param name="loadSceneMode"></param>
async void LoadScene(string sceneName, LoadSceneMode loadSceneMode)
{
sceneToLoad = await AddressablesManager.Instance.LoadScene(sceneName, loadSceneMode);
}
/// <summary>
/// 卸载场景
/// </summary>
/// <param name="scene"></param>
async void UnloadScene(SceneInstance scene)
{
await AddressablesManager.Instance.UnloadScene(scene);
}
}
}