5.Lua管理器和加载AB包中的Lua脚本

5.CSharp调用Lua-Lua管理器


5.1 知识点

创建Lua管理器,实现单例和一些常用方法。目的是保证Lua解析器唯一。同时封装了执行lua脚本方法和大G表属性

public class LuaManager : BaseSingletonInCSharp<LuaManager>
{
    private LuaEnv luaEnv;
    
    /// <summary>
    /// 初始化解析器
    /// </summary>
    public void Init()
    {
        //已经初始化了 别初始化 直接返回
        if (luaEnv != null)
            return;
        //初始化
        luaEnv = new LuaEnv();
        //加载lua脚本 重定向
        luaEnv.AddLoader(MyCustomLoader);
    }

    //自定义加载路径
    private byte[] MyCustomLoader(ref string filePath)
    {
        //通过函数中的逻辑 去加载 Lua文件 
        
        //参数filePath 是 require执行的 lua脚本文件名 比如上面执行的Main
        //我们需要拼接 lua 脚本所在路径,例如统一放在 Assets 下的 LuaScripts 文件夹下
        //注意要把lua脚本文件名和.lua后缀也加上 因为不在Resources下 不需要.txt后缀了
        string path = Application.dataPath + "/LuaScripts/" + filePath + ".lua";
        Debug.Log(path);

        //判断lua脚本文件名所在的路径是否存在
        if (File.Exists(path))
        {
            //存在的话 从 所在的路径的lua脚本中 读取二进制数据 并将其以字节数组的形式返回
            return File.ReadAllBytes(path);
        }
        else
        {
            //不存在则读取失败
            Debug.Log("MyCustomLoader重定向失败,文件名为" + filePath);
        }

        return null;
    }

    /// <summary>
    /// 传入lua文件名 执行lua脚本
    /// </summary>
    /// <param name="fileName"></param>
    public void DoLuaFile(string fileName)
    {
        string str = string.Format("require('{0}')", fileName);
        DoString(str);
    }

    /// <summary>
    /// 执行Lua语言
    /// </summary>
    /// <param name="str"></param>
    public void DoString(string str)
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器未初始化");
            return;
        }
        luaEnv.DoString(str);
    }

    /// <summary>
    /// 释放lua 垃圾
    /// </summary>
    public void Tick()
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器未初始化");
            return;
        }
        luaEnv.Tick();
    }

    /// <summary>
    /// 销毁解析器
    /// </summary>
    public void Dispose()
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器未初始化");
            return;
        }
        try
        {
            luaEnv.Dispose();
            luaEnv = null;
            Debug.Log("释放成功");
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex.Message);
        }

    }
}

给Lua脚本打成AB包


注意暂时要把lua脚本改成.txt后缀,才能打包成功

假如出现报错就清空代码后再打


打包成功后记得右键刷新,可能才能在StreamingAssets文件夹刷出来

执行AB包中的Lua脚本

在Lua管理器中添加重定向到AB包路径的方法

/// <summary>
/// 初始化解析器
/// </summary>
public void Init()
{
    //已经初始化了 别初始化 直接返回
    if (luaEnv != null)
        return;
    //初始化
    luaEnv = new LuaEnv();
    //加载lua脚本 重定向
    luaEnv.AddLoader(MyCustomLoader);//先找指定的LuaScripts文件夹有没有这个脚本
    luaEnv.AddLoader(MyCustomAssetBundleLoader);//再找AB包中有没有
}

//Lua脚本会放在AB包 Lua脚本打成AB包的时候加了.txt后缀
//最终我们会通过加载AB包再加载其中的Lua脚本资源 来执行它
//重定向加载AB包中的Lua脚本
private byte[] MyCustomAssetBundleLoader(ref string filePath)
{
    Debug.Log("进入AB包加载 重定向函数");

    
    // //假如没有AB包管理器 要自己手动写加载AB包代码
    // //从AB包中加载lua文件
    // //拼出AB包路径 
    // string path = Application.streamingAssetsPath + "/luascripts";
    // //加载AB包
    // AssetBundle assetBundle = AssetBundle.LoadFromFile(path);
    // //加载Lua文件 因为打成AB包的时候加了.txt后缀 所以加载类型是TextAsset 加上.lua后缀
    // TextAsset luaTextAsset = assetBundle.LoadAsset<TextAsset>(filePath + ".lua");


    
    //通过我们的AB包管理器 加载的lua脚本资源
    TextAsset luaTextAsset = AssetBundleManager.Instance.LoadAssetBundleResource<TextAsset>("luascripts", filePath + ".lua");
    //加载成功把Lua文件转成byte数组并返回 不成功返回空打印报空信息
    
    
    //把Lua文件转成byte数组并返回
    if (luaTextAsset != null)
        return luaTextAsset.bytes;
    else
        Debug.Log("MyCustomAssetBundleLoader重定向失败,文件名为:" + filePath);
    return null;
}

在测试脚本中执行文件

print('我是Lua脚本 Lesson05_CSharp调用Lua_Lua管理器')
public class Lesson05_CSharp调用Lua_Lua管理器 : MonoBehaviour
{
    void Start()
    {
        LuaManager.Instance.Init();

        //LuaManager.Instance.DoString("require('Lesson05_CSharp调用Lua_Lua管理器')");

        LuaManager.Instance.DoLuaFile("Lesson05_CSharp调用Lua_Lua管理器");
    }

}

注意事项

  • 由于LuaScripts文件夹下的lua脚本后缀被改成.txt,所以不能重定向到LuaScripts文件夹下,会重定向到AB包中。

实际开发中的处理

  • 实际开发中不会在lua脚本后加.txt后缀,只有测试热更新功能是否正常或最终打包才会,之后会做一个工具,可以一键修改lua脚本后缀.txt,和一键还原后缀为.lua。现在先把文件夹后缀改回.lua

Lua脚本是否加.txt总结

在Resources下要加.txt,自定义加载路径中不用加,打成AB包的时候要加.txt。


5.2 知识点代码

Lesson05_CSharp调用Lua_Lua管理器.lua

print('我是Lua脚本 Lesson05_CSharp调用Lua_Lua管理器')

LuaManager

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using XLua;

public class LuaManager : BaseSingletonInCSharp<LuaManager>
{
    //执行Lua语言的函数
    //释放垃圾
    //销毁
    //重定向
    private LuaEnv luaEnv;


    /// <summary>
    /// 得到Lua中的_G
    /// </summary>
    public LuaTable Global
    {
        get
        {
            return luaEnv.Global;
        }
    }


    /// <summary>
    /// 初始化解析器
    /// </summary>
    public void Init()
    {
        //已经初始化了 别初始化 直接返回
        if (luaEnv != null)
            return;
        //初始化
        luaEnv = new LuaEnv();
        //加载lua脚本 重定向
        luaEnv.AddLoader(MyCustomLoader);//先找指定的LuaScripts文件夹有没有这个脚本
        luaEnv.AddLoader(MyCustomAssetBundleLoader);//再找AB包中有没有
    }

    //自定义加载路径
    private byte[] MyCustomLoader(ref string filePath)
    {
        //通过函数中的逻辑 去加载 Lua文件 
        Debug.Log("进入自定义加载 重定向函数");
        //参数filePath 是 require执行的 lua脚本文件名 比如上面执行的Main
        //我们需要拼接 lua 脚本所在路径,例如统一放在 Assets 下的 LuaScripts 文件夹下
        //注意要把lua脚本文件名和.lua后缀也加上 因为不在Resources下 不需要.txt后缀了
        string path = Application.dataPath + "/LuaScripts/" + filePath + ".lua";
        Debug.Log(path);

        //判断lua脚本文件名所在的路径是否存在
        if (File.Exists(path))
        {
            //存在的话 从 所在的路径的lua脚本中 读取二进制数据 并将其以字节数组的形式返回
            return File.ReadAllBytes(path);
        }
        else
        {
            //不存在则读取失败
            Debug.Log("MyCustomLoader重定向失败,文件名为" + filePath);
        }


        return null;
    }


    //Lua脚本会放在AB包 Lua脚本打成AB包的时候加了.txt后缀
    //最终我们会通过加载AB包再加载其中的Lua脚本资源 来执行它
    //重定向加载AB包中的Lua脚本
    private byte[] MyCustomAssetBundleLoader(ref string filePath)
    {
        Debug.Log("进入AB包加载 重定向函数");

        
        // //假如没有AB包管理器 要自己手动写加载AB包代码
        // //从AB包中加载lua文件
        // //拼出AB包路径 
        // string path = Application.streamingAssetsPath + "/luascripts";
        // //加载AB包
        // AssetBundle assetBundle = AssetBundle.LoadFromFile(path);
        // //加载Lua文件 因为打成AB包的时候加了.txt后缀 所以加载类型是TextAsset 加上.lua后缀
        // TextAsset luaTextAsset = assetBundle.LoadAsset<TextAsset>(filePath + ".lua");


        
        //通过我们的AB包管理器 加载的lua脚本资源
        TextAsset luaTextAsset = AssetBundleManager.Instance.LoadAssetBundleResource<TextAsset>("luascripts", filePath + ".lua");
        //加载成功把Lua文件转成byte数组并返回 不成功返回空打印报空信息
        
        
        //把Lua文件转成byte数组并返回
        if (luaTextAsset != null)
            return luaTextAsset.bytes;
        else
            Debug.Log("MyCustomAssetBundleLoader重定向失败,文件名为:" + filePath);
        return null;
    }


    /// <summary>
    /// 传入lua文件名 执行lua脚本
    /// </summary>
    /// <param name="fileName"></param>
    public void DoLuaFile(string fileName)
    {
        string str = string.Format("require('{0}')", fileName);
        DoString(str);
    }

    /// <summary>
    /// 执行Lua语言
    /// </summary>
    /// <param name="str"></param>
    public void DoString(string str)
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器未初始化");
            return;
        }
        luaEnv.DoString(str);
    }

    /// <summary>
    /// 释放lua 垃圾
    /// </summary>
    public void Tick()
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器未初始化");
            return;
        }
        luaEnv.Tick();
    }

    /// <summary>
    /// 销毁解析器
    /// </summary>
    public void Dispose()
    {
        if (luaEnv == null)
        {
            Debug.Log("解析器未初始化");
            return;
        }
        try
        {
            luaEnv.Dispose();
            luaEnv = null;
            Debug.Log("释放成功");
        }
        catch (System.Exception ex)
        {
            Debug.Log(ex.Message);
        }

    }
}

Lesson05_CSharp调用Lua_Lua管理器

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Lesson05_CSharp调用Lua_Lua管理器 : MonoBehaviour
{
    void Start()
    {
        LuaManager.Instance.Init();

        //LuaManager.Instance.DoString("require('Lesson05_CSharp调用Lua_Lua管理器')");

        LuaManager.Instance.DoLuaFile("Lesson05_CSharp调用Lua_Lua管理器");
    }

}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏