您当前的位置: 首页 >  unity

莉萝爱萝莉

暂无认证

  • 9浏览

    0关注

    58博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Unity-Xlua

莉萝爱萝莉 发布时间:2022-09-27 10:55:08 ,浏览量:9

目录
        • 1. Xlua
          • 1. 简介
          • 2. 基本使用
          • 3. 通过Loader自定义require加载路径
          • 4. C#访问Lua
          • 5. C#访问Lua中的全局function
          • 6. Lua访问C#
        • 2. Xlua热更新
          • 1. 启用热更新
          • 2. 补丁开发过程
          • 3. 补丁应用实例
          • 4. 函数重载问题
            • 5. 热更新报错:xlua.access,no field __Hotfix0_Update
            • 6. 标识热更新的简介办法

1. Xlua 1. 简介
  1. Xlua下载地址:https://github.com/Tencent/xLua 在右侧 Releases 中获取
  2. 导入包中 Assets 文件夹下的Plugins和XLua
2. 基本使用
  1. LuaEnv 类用于在Unity中运行lua代码
private LuaEnv luaEnv;
void Start()
{
    // 创建 Lua 虚拟机
    luaEnv = new LuaEnv();
    // 运行 lua 代码
    luaEnv.DoString(@"print('Hello xlua')");
    // 运行 Unity 代码
    luaEnv.DoString(@"CS.UnityEngine.Debug.Log('Hello Unity')");
}

private void OnDestroy()
{
    // 释放
    luaEnv.Dispose();
}
  1. 从Resources目录下可加载lua代码并执行,因为lua后缀文件并不能让unity识别,所以后缀需改为lua.text
  2. 利用lua指令 require 'path' ,可在Resources目录下自动加载后缀为lua.text的文件
//创建 LuaEnv 类
LuaEnv luaEnv = new LuaEnv();
// 1. 加载并运行
TextAsset ta = Resources.Load("hello");
luaEnv.DoString(ta.text);
// 2. 自动加载运行
luaEnv.DoString("require 'hello'");
3. 通过Loader自定义require加载路径
  1. 使用方法 AddLoader 添加加载路径函数,返回值为脚本数据,入参为 require 路径
  2. 使用 File.ReadAllText(path) 获取路径下脚本文本,使用 System.Text.Encoding.UTF8.GetBytes(data) 将文本转化为字节数组
void Start()
{
    // 创建 LuaEnv 类
    LuaEnv luaEnv = new LuaEnv();
    luaEnv.AddLoader(MyLoader);
    luaEnv.DoString("require 'stream'");
    // 释放
    luaEnv.Dispose();
}

private byte[] MyLoader(ref string filePath)
{
    string path = Application.streamingAssetsPath + "/" + filePath + ".lua.txt";
    print(path);
    string data = File.ReadAllText(path);
    return System.Text.Encoding.UTF8.GetBytes(data);
}
4. C#访问Lua
  1. 获取Lua中的全局变量 luaEnv.Global.Get(string)
// 必须先运行脚本,内存中生成变量后方可获取数值
// 创建 LuaEnv 类
LuaEnv luaEnv = new LuaEnv();
// 2. 自动加载运行
luaEnv.DoString("require 'hello'");

// 仅当为整数时可正常获取,否则返回0
int iValue = luaEnv.Global.Get("value");
float fValue = luaEnv.Global.Get("value");
string data = luaEnv.Global.Get("data");
bool flag = luaEnv.Global.Get("flag");
  1. 获取Lua中的table
    1. 用类获取(获得的是复制份,修改并不能更改原表)
    LuaData luaData = luaEnv.Global.Get("table");
    public class LuaData
    {
        public int value;
        public string data;
        public bool flag;
    }
    
    1. 接口(接口为public且添加特性CSharpCallLua,若发现仍无法正常运行,可在 Xlua 栏下 -> Clear Generated Code -> Generated Code)
    ILuaData luaData = luaEnv.Global.Get("table");
    luaData.value = 234;
    luaData.say(2);
    
    [CSharpCallLua]
    public interface ILuaData
    {
        int value { get; set; }
        string data { get; set; }
        bool flag { get; set; }
        void say(int time);
    }
    
    table = {
        value = 100,
        data = "liluo",
        flag = false,
    }
    function table:say(time)
        print(self.data .. "第" .. time .. "次" .. "说")
    end
    
    1. 字典和列表
    // 返回键值对数据
    Dictionary luaData = luaEnv.Global.Get("table");
    // 返回单纯的列表数据
    List luaList = luaEnv.Global.Get("table");
    
    1. LuaTable
    LuaTable tab = luaEnv.Global.Get("table");
    print(tab.Get("data"));
    print(tab.Get("value"));
    print(tab.Get("flag"));
    foreach (var key in tab.GetKeys())
        print(tab.Get(key.ToString()));
    
5. C#访问Lua中的全局function
  1. Action 方式
luaEnv= new LuaEnv();
Action act = luaEnv.Global.Get("Add");
act("I say");
act = null;
// 若采用自定义委托
[CSharpCallLua]
delegate int Add(int a, int b);
function Add(data)
    print(data)
end
  1. 自定义委托 需为委托添加特性 CSharpCallLua
Add act = luaEnv.Global.Get("Add");
int a, b;
// 额外的返回值用out接收
print(act(2, 3, out a, out b));
print(a + ", " + b);
act = null;
// 应为public,若发现仍无法正常运行,可 Generated Code
[CSharpCallLua]
public delegate int Add(int a, int b, out int resA, out int resB);
function Add(a, b)
    return a + b, a, b
end
  1. LuaFunction
// 创建 LuaEnv 类
luaEnv = new LuaEnv();
LuaFunction func = luaEnv.Global.Get("Add");
// 获得返回值列表
object[] os = func.Call(1, 2);
foreach (object data in os)
{
	print(data);
}
function Add(a, b)
    return a + b, a, b
end
6. Lua访问C#
-- 新建对象
CS.UnityEngine.GameObject()
CS.UnityEngine.GameObject("obj")
-- 访问成员属性和方法
print(CS.UnityEngine.Time.deltaTime)
CS.UnityEngine.Time.timeScale = 0.5
local camera = CS.UnityEngine.GameObject.Find("Main Camera")
camera.name = "luaupdate"
CS.UnityEngine.GameObject.Destroy(camera:GetComponent("Camera"))

注意:对于非静态对象,调用成员方法,第一个参数需要传该对象,建议用冒号语法糖,如下

testobj:DMFunc()
2. Xlua热更新 1. 启用热更新
  1. 想要启用热更新,首先要在项目设置的玩家中添加脚本定义符号 HOTFIX_ENABLE 并应用,这时Xlua选单中就会额外出现一个 Hotfix Inject In Editor (注意:各平台需要分别设置) 在这里插入图片描述
  2. 添加 Xlua 中的 Tools 文件夹到 Assets 同级目录下
  3. 重新生成lua代码 (Xlua 栏下 -> Clear Generated Code -> Generated Code)
  4. 点击Xlua选单中的 Hotfix Inject In Editor 注入代码到编辑器
  5. 添加程序集:将 Unity\2020.3.8f1c1\Editor\Data\Managed 路径下的 Unity.Cecil.Pdb.dll Unity.Cecil.Mdb.dll Unity.Cecil.dll 三个配置文件加入工程的 Assets\XLua\Src\Editor目录下
2. 补丁开发过程
  1. 首先开发业务代码
  2. 在所有可能出现问题的类上打上hotfix的标签,在所有lua调用CSharp的方法上打上LuaCallCSharp,在所有CSharp调用Lua的方法上打上CSharpCallLua
  3. 修改bug时只需要更新Lua文件,修改资源时(声音,模型,贴图,图片,UI)只需要更新ab包。用户只需要去下载lua文件跟ab包。
3. 补丁应用实例
  1. 注意:补丁注册必须要在所有脚本之前,否则无法保证补丁应用成功!(比如对Start函数的修改)

  2. 想要添加补丁,需要为想要修改的类添加 Hotfix 热更新特性,再为将要修改的函数添加 LuaCallCSharp 特性,该类便可被热更新捕获 编写lua代码,调用函数 xlua.hotfix(CS.class, 'functionName', function(self)) 更新函数,其中class为添加 Hotfix 热更新特性的类,functionName为添加 LuaCallCSharp 特性的函数名,function为替换的函数,self为类本身

    [Hotfix]
    public class Treasour : MonoBehaviour
    {
        public GameObject gold;
        public GameObject diamands;
        public Transform cavas;
        [LuaCallCSharp]
        private void CreatePrize()
        {
            for (int i = 0; i             
关注
打赏
1663903574
查看更多评论
0.0886s