rustum 发表于 2021-8-13 22:50

xlua 学习教程 XLua 学习笔记记录

untiy 学习讨论群 184386599
1:直接去官网下载 https://github.com/Tencent/xLua
下载解压文件
2:创建一个Unity空项目
3:选择 xlua-》Assets 下的plugins +xlua 文件 放到Unity工程Assets下


直接代码了:里面有全部的注释和遇到的一些问题,有些问题也还不知道原因,可能是版本不兼容先记录一下
using System;using System.Collections;using System.Collections.Generic;using System.IO;using UnityEngine;using XLua;//引入命名空间public class Test : MonoBehaviour{    LuaEnv luaEnv;//lua虚拟机 来运行lua 代码    // Start is called before the first frame update    void Start()    {      luaEnv = new LuaEnv();      //LoadLua_1();      //LoadLua_2();      //LoadLua_3();      //CSCallLua();      LuaCallCSharp();    }    /// <summary>    /// 第一种加载lua 代码方式 不建议使用    /// </summary>    public void LoadLua_1()    {      luaEnv.DoString("print('hello World Lua')");//输出      //luaEnv.DoString("print('hello World Lua2222')");//输出    }    /// <summary>    /// 第二种加载lua 代码方式 建议使用    /// 先创建一个 testlua.lua 文件    /// </summary>    public void LoadLua_2()    {      //Resources 根据文件类型自动加载文件后缀, 这个就变成了 testlua.txt 所以这样写会加载不出来      //所以要把这个文件区分是lua文件就要再加个后缀 testlua.lua.txt      //TextAsset textAsset = Resources.Load<TextAsset>("testlua.lua");      //luaEnv.DoString(textAsset.ToString());      //这种方式使用mylua.lua.txt 必须是这个后缀require 引入并执行文件里面的代码      //require实际上是调一个个的loader去加载,有一个成功就不再往下尝试,全失败则报文件找不到。      //目前xLua除了原生的loader外,还添加了从Resource加载的loader,需要注意的是因为Resource只支持有限的后缀      //放Resources下的lua文件得加上txt后缀          luaEnv.DoString("require 'myLua'");       //这个loader 只能从Resoruce 里面加载lua文件   }    /// <summary>    /// 加载lua文件 自定义loader    /// </summary>    public void LoadLua_3()    {      luaEnv.AddLoader(OurSetLoder); //添加加载lua 文件的loader      luaEnv.DoString("require 'test'");    }    /// <summary>    /// 自定义的 loader 当lua 虚拟机添加了自定义的loader 时会先执行这个自定义的loader   /// </summary>    /// <param name="filePath"></param>    /// <returns></returns>    private byte[] OurSetLoder(ref string filePath)    {      Debug.Log("OurSetLoder--- fliePath = " + filePath);      //在这个地方就可以对自己的代码做加密解密的工作      //这是一段lua代码 需要转成byte 文件      //string str = "print('测试自定义loader')";      //return System.Text.Encoding.UTF8.GetBytes(str);      //通过自定义的文件目录来加载lua文件lua存放路径      string luaPath = Application.dataPath + "/lua/"+ filePath+ ".lua.txt";      byte[] tempBytes = System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(luaPath));      return tempBytes;    }    /// <summary>    /// 访问lua 文件定义的变量-------------------------------------------------------------------------------------------------    /// </summary>    public void CSCallLua()    {      //lua虚拟机编译lua 文件      LoadLua_3();      //CSCallLuaGlobalVal();      CSCallLuaTable();    }    /// <summary>    /// C#访问lua 全局变量    /// </summary>    public void CSCallLuaGlobalVal()    {      //注意 类型, 和变量名 要对应lua number 对应 C# int float double         int hp = luaEnv.Global.Get<int>("hp");      float mp = luaEnv.Global.Get<float>("mp");      string name = luaEnv.Global.Get<string>("name");      bool canFly = luaEnv.Global.Get<bool>("canFly");      Debug.Log("hp = " + hp + "mp = " + mp + "name = " + name + "canFly = " + canFly);    }    //对应lua HeroTable 的类 属性也可不不读取完 但是必须对应对应的属性name hp 必须是public   public class Hero    {      public string name;      public int hp ;      public Skills[] skills;      public void PrintSkills()      {            if (skills.Length == 0)            {                Debug.LogError("没有读取到数组");                return;            }             for (int i=0; i< skills.Length;i++)            {                Debug.Log("name = "+ skills.name + " hart" + skills.hart + " cd" + skills.cd);            }      }      public string GetName()      {            return name;      }      public int GetHp()      {            return hp;      }    }    //对应lua SkillTable 的类    public class Skills    {      public string name;      public int hart ;      public int cd ;    }    //使用接口 ----------------必须加这个untiy 2018不兼容 只有2017才行       public interface IHero    {      string name { get; set; }      int hp { get; set;}      Skills[] skills { get; set; }    }        public interface ISkills    {      string name { get; set; }      int hart { get; set; }      int cd { get; set; }    }    /// <summary>    /// C# 访问lua table   /// </summary>    public void CSCallLuaTable()    {      // 1、映射到普通class或struct 定义一个class,有对应于table的字段的public属性,而且有无参数构造函数都可以      //这种方式下xLua会帮你new一个实例,并把对应的字段赋值过去。      //table的属性可以多于或者少于class的属性。可以嵌套其它复杂类型。      //要注意的是,这个过程是值拷贝,如果class比较复杂代价会比较大。而且修改class的字段值不会同步到table,反过来也不会      //Hero hero = luaEnv.Global.Get<Hero>("Hero");      //Debug.Log("hero.name = " + hero.GetName() + "   hero.hp = " + hero.GetHp());      //hero.PrintSkills();      //2、映射到一个interface 这种方式依赖于生成代码(如果没生成代码会抛InvalidCastException异常),-------------      //代码生成器会生成这个interface的实例,如果get一个属性,生成代码会get对应的table字段,      //如果set属性也会设置对应的字段。甚至可以通过interface的方法访问lua的函数      //接口是一个引用拷贝 在接口里面改变了 lua 变量 lua 变量原始值也会改变      //接口需要测试,2018 不兼容一直报错(需要清理然后重新生成一下代码)推荐使用的事这种方式      //IHero hero = luaEnv.Global.Get<IHero>("Hero");      //Debug.Log("hero.name = " + hero.name + "   hero.hp = " + hero.hp);      //if (hero.skills.Length == 0)      //{      //    Debug.LogError("没有读取到数组");      //    return;      //}      //for (int i = 0; i < hero.skills.Length; i++)      //{      //    Debug.Log("IHero name = " + hero.skills.name + " IHerohart" + hero.skills.hart + " IHerocd" + hero.skills.cd);      //}      //3.通过Dictionary 来映射只能拿到有 table 里面有key 的键值对 {3,4,5} 这种拿不到      //Dictionary<string, object> dic = luaEnv.Global.Get<Dictionary<string, object>>("Hero");      //foreach (string key in dic.Keys)      //{      //    Debug.Log("key = " + key + "value = " + dic);      //}      //4.通过list 来映射 list 只能映射{3,4,5}里面的值 不能映射table有key的值      //List<object> list = luaEnv.Global.Get<List<object>>("Hero");      //foreach (object obj in list)      //{      //    Debug.Log("obj = " + obj);      //}      //5.通过luatablexlua自定义 好像也只能得到带key 值的数据      //LuaTable luaTab = luaEnv.Global.Get<LuaTable>("Hero");      //Debug.Log("name = "+ luaTab.Get<string>("name") + "hp= "+ luaTab.Get<string>("hp"));      //访问lua 里面的全局函数      //不带参数的函数      //Action act = luaEnv.Global.Get<Action>("CallLua");      //act();      //act = null; //这个被lua虚拟机引用 清空才能dipose lua虚拟机      带参数的函数 1 也需要生成代码      //Action<int,int> act1 = luaEnv.Global.Get<Action<int,int>>("CallLua");      //act1(1,2);      //act1 = null;      //通过定义委托类型      //CallLua callLua = luaEnv.Global.Get<CallLua>("CallLua");      //callLua(3, 4);      //callLua = null;      有返回值 这个总是报错也不知道咋回事 也重新生成代码了还是不行 ref 也可以      //CallLuaAdd callLuaAdd = luaEnv.Global.Get<CallLuaAdd>("CallLuaAdd");      //int num = callLuaAdd(3, 4);      //Debug.Log("num =" + num);      //callLuaAdd = null;      //多个返回值依次类推 这个总是报错也不知道咋回事      //CallLuaAdd1 callLuaAdd1 = luaEnv.Global.Get<CallLuaAdd1>("CallLuaAdd1");      //int resa;      //int resb;      //int num = callLuaAdd1(3, 4,out resa,out resb);      //Debug.Log("num =" + num+ "resa =" + resa + "resb =" + resb);      //callLuaAdd1 = null;      //通过luaFuntion 多参数返回 不建议使用 性能慢      LuaFunction luaFun = luaEnv.Global.Get<LuaFunction>("CallLuaAdd1");      object[] objs = luaFun.Call(6, 7);      foreach (object o in objs)      {            Debug.Log("xxxx-----o = "+ o);      }    }    //定义委托和 lua里面函数名一样 并且加上CSharpCallLua 标签        delegate void CallLua(int a, int b);    //有返回值        delegate int CallLuaAdd(int a, int b);    //多个返回参数        delegate int CallLuaAdd1(int a, int b, out int resa, out int resb);    /// 访问lua 文件定义的变量-------------------------------------------------------------------------------------------------    /// <summary>    /// lua 调用C#    /// </summary>    public void LuaCallCSharp()    {      luaEnv.AddLoader(OurSetLoder); //添加加载lua 文件的loader      luaEnv.DoString("require 'luaCallCSharp'");      //local newObj = CS.UnityEngine.GameObject("Cube") CS开头      //静态属性通过类访问      // CS.UnityEngine.Time.deltaTime   CS.UnityEngine.Time.timeScale = 0.5          //小技巧:如果需要经常访问的类,可以先用局部变量引用后访问,除了减少敲代码的时间,还能提高性能:      //local GameObject = CS.UnityEngine.GameObject      //GameObject.Find('helloworld')      //访问C#成员属性,方法      //直接 Gameobjec.name          //.funcName(类对象,参数) 第一个参数默认对象本身:funcName(参数)    }    /// <summary>    ///   /// </summary>    private void OnDestroy()    {      luaEnv.Dispose(); //释放虚拟机 GC 等    }}对应的lua 文件 自定义文件夹的文件 test.lua.txt


print("通过lua文件加载test--------- hello world xLua");hp = 1000mp = 100.5name = "哪吒"canFly = trueprint("C#读取lua的table")Hero ={        name = "孙悟空",        hp = 200000,        skills =         {       {                name = "寒冰掌",                hart = 100,                cd = 3       },          {                name = "火云拳",                hart = 110,                cd = 4       }        },        1,2}function CallLua()print("Hero :CallLua")endfunction CallLua(a,b)print("Hero :CallLua"..a .." b= "..b);endfunction CallLuaAdd(a,b)        return a+b;endfunction CallLuaAdd1(a,b)        return a+b,a,b;end--默认带一个self参数代表当前表function Hero:Talk(str)print("Hero :Talk str= "..str)end--第一个参数要传递表function Hero:TalkOne(self,str)print("Hero .TalkOne str= " .. str)endluaCallCSharp.lua.txt 这个文件里面只有一句代码其他可以自己随便添加: local newObj = CS.UnityEngine.GameObject("Cube")
Resources 文件夹下的lua文件 只有一句输出


untiy 学习讨论群 184386599
页: [1]
查看完整版本: xlua 学习教程 XLua 学习笔记记录