找回密码
 立即注册
查看: 230|回复: 0

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

[复制链接]
发表于 2023-3-27 11:43 | 显示全部楼层 |阅读模式
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()");
        }
    }

    public  void 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[filepath];
        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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-5-4 11:58 , Processed in 0.102023 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表