分享一下个人Demo工程:https://github.com/IsaWinding/AddressableXluaFramework.git
分享Addressable 资源加载:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AssetManager
{
private static AssetManager instance;
public static AssetManager Instance { get { if (instance == null) instance = new AssetManager();return instance; } }
public UnityEngine.Transform PoolRoot;
private Dictionary<string, GameObjectLoader> pools = new Dictionary<string, GameObjectLoader>();
private Dictionary<GameObject, GameObjectLoader> lookup = new Dictionary<GameObject, GameObjectLoader>();
public AssetManager()
{
UnityEngine.Transform poolNode = new GameObject("[Asset Pool]").transform;
poolNode.transform.localPosition = Vector3.zero;
poolNode.transform.localScale = Vector3.one;
poolNode.transform.localRotation = Quaternion.identity;
GameObject.DontDestroyOnLoad(poolNode);
}
/// <summary>
/// 异步加载GameObject
/// </summary>
public void InstantiateAsync(string name, System.Action<GameObject> onFinish)
{
GameObjectLoader loader;
if (this.pools.TryGetValue(name, out loader)){
var obj = loader.Instantiate();
this.lookup.Add(obj, loader);
onFinish.Invoke(obj);
}
else{
loader = new GameObjectLoader(name);
var obj = loader.Instantiate();
this.pools.Add(name, loader);
this.lookup.Add(obj, loader);
onFinish.Invoke(obj);
}
}
/// <summary>
/// GameObject
/// </summary>
public GameObject Instantiate(string name)
{
GameObjectLoader loader;
if (this.pools.TryGetValue(name, out loader))
{
var obj = loader.Instantiate();
this.lookup.Add(obj, loader);
return obj;
}
else
{
loader = new GameObjectLoader(name);
var obj = loader.Instantiate();
this.pools.Add(name, loader);
this.lookup.Add(obj, loader);
return obj;
}
}
/// <summary>
/// 将资源释放回缓
/// </summary>
public void FreeGameObject(GameObject obj){
if (obj != null){
GameObjectLoader loader;
if (this.lookup.TryGetValue(obj, out loader)){
loader.Free(obj);
this.lookup.Remove(obj);
}
}
}
public void RemovePools(string name){
this.pools.Remove(name);
}
public void ReleaseAll(){
foreach (var item in this.pools.Values){
item.Release();
}
}
/// <summary>
/// 资源类型查找缓存表
/// </summary>
private Dictionary<string, UnityObjectLoader> assets = new Dictionary<string, UnityObjectLoader>();
public T LoadAsset<T>(string name) where T : UnityEngine.Object{
UnityObjectLoader loader;
if (this.assets.TryGetValue(name, out loader)){
var obj = loader.LoadAsset<T>();
return obj as T;
}
else{
loader = new UnityObjectLoader(name);
var obj = loader.LoadAsset<T>();
this.assets.Add(name, loader);
return obj as T;
}
}
/// <summary>
/// 引用计数自减1,减少为0后释放Addressable
/// </summary>
public void FreeAsset(string name){
UnityObjectLoader loader;
if (this.assets.TryGetValue(name, out loader)){
loader.Free();
}
}
}
资源加载实例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
class UnityObjectLoader : BaseLoader
{
private int objectRefCount = 0;
private Object object_;
public UnityObjectLoader(string name) : base(name){
this.object_ = null;
}
public Object LoadAsset<T>() where T : UnityEngine.Object{
if (object_ == null){
object_ = base.Load<T>();
}
this.objectRefCount++;
return object_;
}
public void Free(){
this.objectRefCount--;
Release();
}
public override void Release(){
if (this.objectRefCount <= 0){
base.Release();
object_ = null;
AssetManager.Instance.RemovePools(this.name);
}
}
}
Prefab 加载实例:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
class GameObjectLoader : BaseLoader{
/// 资源缓存列表
private Stack<GameObject> caches = new Stack<GameObject>();
/// 正在使用的列表
private HashSet<GameObject> references = new HashSet<GameObject>();
public GameObject prefab;
public GameObjectLoader(string name) : base(name){
this.prefab = null;
}
public GameObjectLoader(GameObject obj) : base(obj.name){
this.prefab = obj;
}
/// <summary>
/// 同步方法,确保已经加载好了
/// </summary>
public GameObject Instantiate(Transform parent)
{
GameObject obj = null;
if (caches.Count > 0){
obj = caches.Pop();
}
else{
obj = GameObject.Instantiate(this.prefab) as GameObject;
obj.name = this.name;
}
this.references.Add(obj);
return obj;
}
/// <summary>
/// 同步方法实例化对象
/// </summary>
public GameObject Instantiate(){
if (caches.Count > 0){
var obj = caches.Pop();
this.references.Add(obj);
return obj;
}
else{
if (this.prefab != null){
var obj = GameObject.Instantiate(this.prefab) as GameObject;
obj.name = this.name;
this.references.Add(obj);
return obj;
}
else{
this.prefab = base.Load<GameObject>();
var obj = GameObject.Instantiate(this.prefab) as GameObject;
obj.name = this.name;
base.Release();
this.references.Add(obj);
return obj;
}
}
}
public void Free(GameObject obj){
this.caches.Push(obj);
this.references.Remove(obj);
obj.transform.SetParent(AssetManager.Instance.PoolRoot);
}
public override void Release(){
foreach (var obj in this.caches){
GameObject.Destroy(obj.gameObject);
}
if (this.references.Count <= 0){
base.Release();
AssetManager.Instance.RemovePools(this.name);
}
}
}
资源加载实例:
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.Initialization;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine;
using System.Collections.Generic;
class BaseLoader
{
protected string name = string.Empty;
private AsyncOperationHandle handle;
private bool isLoad = false;
public BaseLoader(string name){
this.name = name;
this.isLoad = false;
}
/// <summary>
/// 加载资源
/// </summary>
public virtual void Load<T>(System.Action<T> onComplete) where T : UnityEngine.Object
{
if (this.isLoad){
if (handle.IsDone){
if (onComplete != null){
onComplete(handle.Result as T);
}
}
else
{
handle.Completed += (result) =>{
if (result.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
{
var obj = result.Result as T;
if (onComplete != null){
onComplete(obj);
}
}
else
{
if (onComplete != null){
onComplete(null);
}
Debug.LogError("Load name = " + name + " tpye = " + typeof(T).ToString() + " failed! ");
}
};
}
}
else
{
this.isLoad = true;
this.handle = Addressables.LoadAssetAsync<T>(name);
handle.Completed += (result) =>{
if (result.Status == UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationStatus.Succeeded)
{
var obj = result.Result as T;
if (onComplete != null){
onComplete(obj);
}
}
else{
if (onComplete != null){
onComplete(null);
}
Debug.LogError("Load name = " + name + " tpye = " + typeof(T).ToString() + " failed! ");
}
};
}
}
/// <summary>
/// 同步方法加载资源
/// </summary>
public virtual T Load<T>() where T : UnityEngine.Object{
this.isLoad = true;
this.handle = Addressables.LoadAssetAsync<T>(name);
T obj = this.handle.WaitForCompletion() as T;
this.isLoad = false;
return obj;
}
/// <summary>
/// 同时加载多个资源
/// </summary>
public virtual List<T> Loads<T>() where T : UnityEngine.Object{
this.isLoad = true;
this.handle = Addressables.LoadAssetsAsync<T>(name, (obj) => { });
List<T> objs = this.handle.WaitForCompletion() as List<T>;
return objs;
}
public virtual void Release(){
if (this.isLoad){
this.isLoad = false;
Addressables.Release(handle);
}
}
}
XLuaClient
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public enum LuaLoaderType{
LuaFile = 1,//lua的原文件读取模式
LuaAddressableTxt = 2,//addressable 资源的读取模式
}
public class XLuaClient : MonoBehaviour{
private static XLuaClient instance;
private Dictionary<string, byte[]> bytesMap = new Dictionary<string, byte[]>();
public static XLuaClient Instance { get { return instance; } }
private static LuaEnv luaEnv;
private const string FileRoot = "/XLuaFramework/Lua/";
private const string AddressLuaTxtRoot = "Assets/_ABs/LuaTxt/";
private LuaLoaderType loaderType = LuaLoaderType.LuaAddressableTxt;
private void Awake(){
instance = this;
luaEnv = new LuaEnv();
luaEnv.AddLoader(Loader);
GameObject.DontDestroyOnLoad(this);
}
public void OnClear(){
bytesMap.Clear();
}
public string LoadLuaString(string filePath){
string string_;
if (loaderType == LuaLoaderType.LuaFile){
string_ = GetLuaFileText(filePath);
}
else{
string_ = GetAddressableLuaString(filePath);
}
return string_;
}
public static string LoaderString(string filePath){
var realFilePath = Application.dataPath + FileRoot + filePath + ".lua";
var string_ = System.IO.File.ReadAllText(realFilePath);
return string_;
}
public static string GetAddressableLuaTxtPath(string pFilePath){
var path = AddressLuaTxtRoot + pFilePath + ".txt";
return path;
}
public string GetAddressableLuaString(string filePath){
var addressTxtPath = GetAddressableLuaTxtPath(filePath);
var luaAssetText = AssetManager.Instance.LoadAsset<TextAsset>(addressTxtPath);
return luaAssetText.text;
}
public string GetLuaFileText(string filePath){
var realFilePath = Application.dataPath + FileRoot + filePath + ".lua";
var string_ = System.IO.File.ReadAllText(realFilePath);
return string_;
}
private byte[] Loader(ref string filePath){
Debug.LogError("filePath" + filePath);
if (bytesMap.ContainsKey(filePath))
return bytesMap[filePath];
var fixPath = filePath.Replace('.','/');
var string_ = LoadLuaString(fixPath);
var bytes = System.Text.Encoding.UTF8.GetBytes(string_);
bytesMap.Add(filePath, bytes);
return bytes;
}
public void StartMain(){
luaEnv.DoString("require 'GameStartUp'");
}
public void DoString(string sring_){
luaEnv.DoString(sring_);
}
private void OnDestroy() {
luaEnv.Dispose();
}
}