问园会馆 发表于 2023-3-27 11:43

Unity 使用 Addressable 加载 XLua 代码的一种实现方式

2023.3.24:unity 2021.3.20
刚刚学习,希望能指出问题,轻喷。
主要思路是使用 Addressable 完全加载 XLua 的代码,使用字典存取资源
Lua文件是直接勾选的的最上层文件夹进行打包:



使用Lua标签进行批量读取:

-- 可以使用另一个重载api,资源必须全部正确读取后,handle的状态才为成功。


在自定义的装载器中从字典中装载:



<hr/>教训:

因为我默认字典里面的资源名称是 "LuaScript/Game/GameApp.lua.txt",而实际上是 "GameApp.lua"。加上我调试能力很差,导致这个小问题花了很长时间调试。应该先输出一下,看看是什么名字,然后再继续往下写。
<hr/>代码:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class GameLauncher : MonoBehaviour
{
    /// <summary>
    /// 是否开始执行update中的lua代码
    /// </summary>
    bool isStartLua = false;
    /// <summary>
    /// Lua虚拟机
    /// </summary>
    XLua.LuaEnv luaEnv = null;
    /// <summary>
    /// 加载的Lua资源的handle
    /// </summary>
    public AsyncOperationHandle<IList<TextAsset>> LuaHandle { get; private set; }

    private void Awake() {
      this.gameObject.AddComponent<XLuaManger>();
    }
    // Start is called before the first frame update
   public void Start()
    {
      luaEnv = XLuaManger.Instance.Luaenv;
      #region 加载c#框架资源

      #endregion

      #region 更新资源
      LodeUpdateResourse();
      #endregion

      #region 加载Lua资源
      StartCoroutine(LoadLuaAddressable());
      #endregion

      #region 执行Lua代码
      StartCoroutine(EnterLua());
      #endregion
    }


    // Update is called once per frame
    void Update()
    {
      if (isStartLua) {
            luaEnv.DoString("Main.update()");
      }
    }

    publicvoid FixedUpdate() {
      if (isStartLua) {
            luaEnv.DoString("Main.FixedUpdate()");
      }
    }

    private void LateUpdate() {
      if (isStartLua) {
            luaEnv.DoString("Main.LateUpdate()");
      }
    }

    /// <summary>
    /// 更新资源
    /// </summary>
    /// <exception cref="NotImplementedException"></exception>
    private void LodeUpdateResourse() {
      Debug.Log("更新资源...");
      //加载完毕
      Debug.Log("更新资源完毕...");
    }

    /// <summary>
    /// 加载Lua脚本
    /// </summary>
    private IEnumerator LoadLuaAddressable() {
      LuaHandle = Addressables.LoadAssetsAsync<TextAsset>("Lua", (textAsset) => {
            XLuaManger.Instance.LuaTextAssetsDic.Add(textAsset.name, textAsset);
      });
      // 异步操作结束后执行后续代码
      yield return LuaHandle;
      if (LuaHandle.Status == AsyncOperationStatus.Succeeded) {

            // 添加自定义的装载器
            luaEnv.AddLoader(XLuaManger.Instance.LuaScriptLoader);
            Debug.Log("Lua资源加载成功,进入lua...");
            isStartLua = true;
      } else {
            Debug.LogError("Lua资源加载失败");
      }
    }

    /// <summary>
    /// 进入Lua脚本
    /// </summary>
    private IEnumerator EnterLua() {
      //等待加载完毕
      while (isStartLua == false) {
            yield return isStartLua == false;
      }
      //完成加载后进入Lua脚本
      Debug.Log("进入Lua脚本...");
      luaEnv.DoString("require('Main')");
      luaEnv.DoString("Main.Start()");
    }
   
}

<hr/>using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.AddressableAssets;
/// <summary>
/// XLua启动器
/// 单例,保证唯一
/// </summary>
public class XLuaManger : Singleton<XLuaManger>
{
    private string LuaScriptFloder = "LuaScript";
    private string LuaScriptPath = null;
    public XLua.LuaEnv Luaenv { get; private set; }
    public Dictionary<string, TextAsset> LuaTextAssetsDic = new Dictionary<string, TextAsset>();
    override public void Awake() {
      base.Awake();
      DontDestroyOnLoad(this);
      Luaenv = new XLua.LuaEnv();
      
    }

    private void Start() {
    }

    /// <summary>
    /// 自定义的装载器
    /// </summary>
    /// <param name="filepath"></param>
    /// <returns></returns>
    public byte[] LuaScriptLoader(ref string filepath) {
      #region 从本地文件读取
      /*
#if UNITY_EDITOR
      //传入 game.init 转换成 game/inin.lua.txt
      filepath = filepath.Replace(".", "/") + ".lua.txt";
      LuaScriptPath = Path.Combine(Application.dataPath, LuaScriptFloder, filepath);
      byte[] result = System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(LuaScriptPath));
#else
      //发布版本使用ab包读取lua代码
      LuaScriptPath = “”;

#endif
      return result;
      */
      #endregion

      //传入 game.init 转换成 game/inin.lua.txt
      filepath = filepath + ".lua";
      // 通过字典获取资源。
      Debug.Log(LuaTextAssetsDic);
      TextAsset result = LuaTextAssetsDic;
      Debug.Log(result);
      return result.bytes;
    }

    override public void OnDestroy() {
      Luaenv.Dispose();
    }
}
<hr/>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 需要子类在awake中实现 DontDestroyOnLoad(gameObject);
/// </summary>
/// <typeparam name="T"></typeparam>
public class Singleton<T> : MonoBehaviour where T : Singleton<T> {
    private static T _instance;
    public static T Instance {
      get {
            //调用时若为空则创建
            if( _instance == null ) {
                _instance = new GameObject($"{typeof(T)}").AddComponent<T>();
            }
            return _instance;
      }
    }
    public virtual void Awake() {
      //awake初始化时已经存在_instance,销毁自身
      if (_instance != null) {
            Destroy(gameObject);
      } else {
            _instance = (T)this;
      }
    }
    public static bool IsInitialized {
      get { return _instance != null; }
    }

    public virtual void OnDestroy() {
      if (_instance == this) {
            _instance = null;
      }
    }
}
<hr/>print("hello world!")
print("hello XLua!")
local GameApp =require("GameApp")
Main = {}

-- Start
local function Start()
    print("Main.Start...")
    -- 初始化lua框架
    -- end
    -- 进入游戏
    GameApp.EnterGame()
    -- end
end
Main.Start = Start

-- update
local function update()
    -- print("Main.update...")
end
Main.update = update

-- FixedUpdate
local function FixedUpdate()
    -- print("Main.FixedUpdate...")
end
Main.FixedUpdate = FixedUpdate

-- LateUpdate
local function LateUpdate()
    -- print("Main.LateUpdate...")
end
Main.LateUpdate = LateUpdate<hr/>local GameApp = {}
GameApp.EnterGame = function ()
    print("GameApp.Started...")
    -- 读取资源
    -- 实例化资源
end
return GameApp
页: [1]
查看完整版本: Unity 使用 Addressable 加载 XLua 代码的一种实现方式