配置XLua
本日内容unity创建的物体名、c#脚本名和lua脚本名保持一致
配置文件
1.解压压缩包
2.选中所有文件
3.复制到unity项目里,不是Assets文件夹里
4.不要动XLua的路径,不要把Xlua放到Plugins里面
测试XLua运行
1.创建空物体
2.挂载DoHelloWorldLua.cs文件
using System.Collections; using System.Collections.Generic; using UnityEngine; //引用命名空间XLua using XLua; public class DoHelloWorldLua : MonoBehaviour { void Start () { string lua = "print('Hello World')"; //需要要创建一个执行Lua的虚拟机(解析器), 通常该解析器只需要一个即可 LuaEnv luaenv = new LuaEnv(); //执行lua语句 luaenv.DoString(lua); //如果判断解析器不再需要,可以释放掉 luaenv.Dispose(); } }
配置自定义路径
1.XLua默认的lua文件加载路径及格式
lua问价格式是 xxx.lua.txt
DoLuaFile.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class DoLuaFile : MonoBehaviour { void Start () { //DoLuaFile lua的文件命名 string lua = "require('DoLuaFile')"; LuaEnv luaenv = new LuaEnv(); //一旦使用xLua去执行require语句时,是通过xLua的 “加载器” 去加载Lua文件 //xLua默认有一个加载器, 默认加载器的加载路径是 Assets/Resources, //也就是默认加载器只能加载Resources文件夹的lua文件,并且其子文件是不可以的 //默认加载器对于文件的命名有规范, 文件的后缀必须是.txt, 文件名必须是 lua的文件名.lua //最终文件的全部名字为: xxx.lua.txt 例如:DoLuaFile.lua.txt //注意: xLua执行的Lua文件必须是UTF8编码格式 luaenv.DoString(lua); } }
对应lua文件地址
格式
DoLuaFile.lua.txt内容
print('DO Lua File.....');
2.自定义加载路径
DoLuaLoader.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System.IO; public class DoLuaLoader : MonoBehaviour { void Start () { LuaEnv luaenv = new LuaEnv(); //自定义加载器的加载方式 //可以对解析器添加自定义的加载器 //参数是CustomLoader类型 //delegate byte[] CustomLoader(ref string filepath); //AddLoader方法能传入 返回值为byte[] 参数为ref 字符串类型的参数的方法 luaenv.AddLoader(FolderLoader); luaenv.AddLoader(FolderLoader1); //当xLua执行require语句时,会首先调用自定义加载器去加载Lua文件, //如果一个加载器加载到了文件,那么后续加载器不再调用 //如果所有的自定义加载器未找到,那么再调用默认加载器 //如果默认加载器也未找到,那么则报错 luaenv.DoString("require('DoFolderLua')"); } //如果自定义加载器的返回值为null,表示该加载器未找到文件 //需要将lua语言的字符串转使用UTF8换成字节数组 byte[] FolderLoader(ref string fileName) { Debug.Log("执行 Folder Loader的加载器方法: " + fileName); string path = Application.dataPath + "/Lua/" + fileName + ".lua"; //判断文件是否存在 if (File.Exists(path)) { return File.ReadAllBytes(path); } return null; } byte[] FolderLoader1(ref string fileName) { Debug.Log("执行 Folder1 Loader的加载器方法: " + fileName); return null; } }
Lua文件统一放到Lua文件夹下
DoLuaLoader.lua
print("Do Folder Lua ......")
XLua的管理类XLuaMgr
XLuaMgr.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System.IO; public class XLuaMgr { #region 单例 private static XLuaMgr instance; public static XLuaMgr Instance { get { if (instance == null) { instance = new XLuaMgr(); } return instance; } } private XLuaMgr() { luaenv = new LuaEnv(); //添加自定义的加载器 luaenv.AddLoader(FolderLoader); } #endregion //管理Lua解析器 private LuaEnv luaenv; public LuaEnv LuaEnv { get { return luaenv; } } //Assets目录下的Lua文件夹路径及其子文件夹路径 private List<string> folders; //该加载器只在Editor下有意义 byte[] FolderLoader(ref string fileName) { #if UNITY_EDITOR if (folders == null) { folders = new List<string>(); string luaPath = Application.dataPath + "/Lua/"; folders.Add(luaPath); //所有的子文件夹路径 string[] dirs = Directory.GetDirectories(luaPath); foreach (var child in dirs) { folders.Add(child + "/"); } } //依次判断每个文件夹是否有该文件 string name = fileName + ".lua"; for (int i = 0; i < folders.Count; i++) { if (File.Exists(folders[i] + name)) { return File.ReadAllBytes(folders[i] + name); } } #endif return null; } }
c#调用Lua文件
获取lua文件内的变量
GlobalDataLua.lua
print("Do Global Data Lua ... ...") --全局变量 a = 10 b = 2.6 c = true d = "string"
GlobalDataLua.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class GlobalDataLua : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('GlobalDataLua')"); //访问Lua文件中的全局变量 //xLua在执行Lua文件是, 会将Lua文件中的全局变量存储在一个Global //Global可以通过LuaEnv获取,类型是LuaTable类型 LuaTable global = XLuaMgr.Instance.LuaEnv.Global; //通过LuaTable的Get方法获取 //泛型为Lua变量的数据类型对应的C#类型, 参数就是Lua变量名 int a = global.Get<int>("a"); Debug.Log(a); float b = global.Get<float>("b"); Debug.Log(b); bool c = global.Get<bool>("c"); Debug.Log(c); string d = global.Get<string>("d"); Debug.Log(d); } }
获取lua的table
GlobalTableLua.lua
print("Global Table Lua ......") tab1 = { [1] = 12, name = "小明", age = 18, isMan = true, } tab2 = { name = "小刘", age = 30, isMan = true, Func = function () print("执行Lua Func的方法") end } tab3 = {"123", "456", "789", 12}
GlobalTableLua.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class GlobalTableLua : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('GlobalTableLua')"); //TableToClass(); //TableToInterface(); //TableToDictionary(); //TableToList(); TableToLuaTable(); } #region Class //第一种映射Table的方式,通过class或struct, 值类型复制 public class Tab1Class { //table中的有哪些键, 类中就有哪些变量 //变量名要与table中的键名保持一致,类型也要保持一致 public string name; public int age; public bool isMan; //类中使用委托类映射table的方法 } void TableToClass() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; //通过Get方法获取 Tab1Class t1 = global.Get<Tab1Class>("tab1"); Debug.Log(t1.name); Debug.Log(t1.age); Debug.Log(t1.isMan); } #endregion #region Interface //第二种映射Table的方式, 通过interface, 引用类型复制 //接口前必须加[CSharpCallLua]特性, 使用接口映射需要自动生成一些代码 //添加[CSharpCallLua]特性后,xlua会识别到自动生成一些配置的代码 //如果没有自动生成, 需要手动的执行XLua -> Generate Code [CSharpCallLua] public interface ITab2Interface { //接口中不允许定义变量的, 但是可以定义属性 //使用属性来映射table中的键值对 string name { set; get; } int age { set; get; } bool isMan { set; get; } //接口中使用方法来映射Table的方法 void Func(); } void TableToInterface() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; ITab2Interface t2 = global.Get<ITab2Interface>("tab2"); Debug.Log(t2.name); Debug.Log(t2.age); Debug.Log(t2.isMan); t2.Func(); } #endregion #region Dictionary List //第3种映射Table的方式, 通过Dictionary和List 值拷贝 void TableToDictionary() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; //使用字典进行映射, 只能映射到与字典的键相同类型,字典值相同类型的数据 Dictionary<string, object> t1 = global.Get<Dictionary<string, object>>("tab1"); foreach (var item in t1) { Debug.Log(item.Key + " -- "+ item.Value); } } void TableToList() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; //只能映射Table作为数组时的数据, 并且只能映射值与指定List的类型相同的值 List<string> t3 = global.Get<List<string>>("tab3"); for (int i = 0; i < t3.Count; i++) { Debug.Log(t3[i]); } } #endregion #region LuaTable //第四种方式, 通过LuaTable, 引用传递 void TableToLuaTable() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; LuaTable lt = global.Get<LuaTable>("tab1"); //获取name, age, isMan string name = lt.Get<string>("name"); Debug.Log(name); int age = lt.Get<int>("age"); Debug.Log(age); bool isMan = lt.Get<bool>("isMan"); Debug.Log(isMan); } #endregion }
获取lua的function
GlobalFunctionLua.lua
print("Global Function Lua ......") function Func1() print("Lua Func1") end function Func2(a, b) print("Lua Func2") return a + b end function Func3() return 12, true, "string" end
GlobalFunctionLua.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class GlobalFunctionLua : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('GlobalFunctionLua')"); //FunctionToDelegate1(); //FunctionToLuaFunction(); //FunctionToDelegate2(); FunctionToDelegate3(); } #region 通过委托进行映射 //定义委托类型, 返回值与参数与Lua中的要映射的方法一致 [CSharpCallLua] //注意: 定义委托要加特性 public delegate void Function1(); [CSharpCallLua] public delegate int Function2(int a, int b); void FunctionToDelegate1() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; Function1 f1 = global.Get<Function1>("Func1"); f1(); Function2 f2 = global.Get<Function2>("Func2"); int num = f2(10, 20); Debug.Log(num); } //映射多返回指的Lua方法 //多返回值的映射, 通过委托的 返回值、输出参数(out、ref)返回 //委托有返回值,Lua的第一个返回值对应委托的返回值, 从第二个返回值开始,依次对应委托的输出参数(out、ref) //委托没有返回值,Lua的从第一个返回值开始,依次对应委托的输出参数(out、ref) /* function Func3() return 12, true, "string" end * */ [CSharpCallLua] public delegate int Function3(out bool a, ref string str); [CSharpCallLua] public delegate void Function4(out int num, out bool a, ref string str); void FunctionToDelegate2() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; Function3 f3 = global.Get<Function3>("Func3"); bool outTwo; string outThree = ""; int outOne = f3(out outTwo, ref outThree); Debug.Log(outOne); Debug.Log(outTwo); Debug.Log(outThree); } void FunctionToDelegate3() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; Function4 f4 = global.Get<Function4>("Func3"); int outOne; bool outTwo; string outThree = ""; f4(out outOne,out outTwo, ref outThree); Debug.Log(outOne); Debug.Log(outTwo); Debug.Log(outThree); } #endregion #region 通过LuaFunction映射 void FunctionToLuaFunction() { LuaTable global = XLuaMgr.Instance.LuaEnv.Global; LuaFunction lf1 = global.Get<LuaFunction>("Func1"); //通过LuaFunction的Call方法调用 lf1.Call(); LuaFunction lf2 = global.Get<LuaFunction>("Func2"); object[] arr = lf2.Call(10, 21); Debug.Log(arr[0]); } #endregion }
Lua调用C#文件
lua创建新的unity物体
LuaNewObject.lua
print("Lua New Object ......") --C# UnityEngine.GameObject obj = new UnityEngine.GameObject(); --Lua 调用GameObject类的构造函数, 变量不需要定义类型,没有new关键字 --xLua 是支持C#的重载函数的,有局限性 --格式: CS.命名空间.类名(参数列表) local obj1 = CS.UnityEngine.GameObject("obj1") --简写方式 --使用一个变量来存储C#的类, GameObject就是C#的UnityEngine.GameObject类 --GameObject = CS.UnityEngine.GameObject --通常使用一个单独文件,来定义所有的Unity的常用类 require('UnityAPI') local obj2 = GameObject("obj2") local obj3 = GameObject("obj3")
此处可以引用一个定义好的UnityAPI的lua文件,就不用那么繁琐的调用了
例:UnityAPI.lua
GameObject = CS.UnityEngine.GameObject
LuaNewObject.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LuaNewObject : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('LuaNewObject')"); //UnityEngine.GameObject obj = new UnityEngine.GameObject(); } }
lua调用c#的静态方法
LuaCallStaticMember.lua
print("Lua Call Static Member ......") --调用C#的静态成员 --静态变量,静态属性 --C# UnityEngine.Time.deltaTime --Lua 调用静态变量与属性: CS.命名空间.类名.变量名或属性名 或 CS.类名.变量名或属性名 --print(CS.UnityEngine.Time.deltaTime) Time = CS.UnityEngine.Time print(Time.deltaTime) --静态方法 --C# UnityEngine.GameObject obj = UnityEngine.GameObject.Find("") --Lua 调用静态方法:CS.命名空间.类名.方法名(参数) 或 CS.类名.方法名(参数) --local obj = CS.UnityEngine.GameObject.Find("Main Camera") GameObject = CS.UnityEngine.GameObject local obj = GameObject.Find("Main Camera") --判断是否查找到 --[[ if obj ~= nil then print("找到了Main Camera") else print("未找到了Main Camera") end ]] --简写, lua认为除了false与nil,其余全是真(true) --obj不为nil, lua认为是true,证明找到了 if obj then print("找到了Main Camera") else print("未找到了Main Camera") end
LuaCallStaticMember.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LuaCallStaticMember : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallStaticMember')"); } }
lua调用c#非静态成员和内部类
LuaCallUnStaticMember.lua
print("Lua Call Un Static Member ......") --Lua访问非静态(实例)成员 --C# 调用实例成员 对象.成员名 --实例化一个对象,实例化的过程是调用构造函数的过程 local member = CS.UnStaticMemberClass() --实例变量、实例属性 --Lua 调用实例变量与属性 对象名.变量名或属性名 member.name = "小小名" print(member.name) print(member.Age) --实例方法 --Lua 调用实例方法 对象名:方法名() member:Function() --mebmer 是 UnStaticMemberClass 的对象 --BaseFunction 是 BaseClass 的方法 --UnStaticMemberClass 继承 BaseFunction --Lua支持通过子类对象 mebmer 调用父类的方法 BaseFunction lua支持继承 member:BaseFunction() --实例化内部类 --Lua 调用内部类 CS.命名空间.类名.内部类名 或 CS.类名.内部类名 local t = CS.LuaCallUnStaticMember.Test() print(t.name)
LuaCallUnStaticMember.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; public class LuaCallUnStaticMember : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallUnStaticMember')"); } //内部类 [LuaCallCSharp] public class Test { public string name = "Test"; } } //如果Lua要调用自定义的类时,定义类的最好加[LuaCallCSharp] //有了该特性, 会生成对应的配置代码 //如果没有该特性, Lua调用该类时, 会采用反射的方式, 反射的效率比直接调用要低, 有些平台上不支持 [LuaCallCSharp] public class UnStaticMemberClass : BaseClass { public string name = "小明"; public int Age { get { return 18; } } public void Function() { Debug.Log("执行C# UnStaticMemberClass类中的Function方法"); } } public class BaseClass { public void BaseFunction() { Debug.Log("执行C# BaseClass基类中的BaseFunction方法"); } }
lua支持部分c#的重载方法
LuaCallOverloadFunction.lua
print("Lua Call Overload Function ......") --xLua是支持C#的重载函数的 OverloadClass = CS.OverloadClass --[[ OverloadClass.Function() OverloadClass.Function(10) OverloadClass.Function("10") OverloadClass.Function(1, 2) ]] --xLua虽然支持重载,但是有局限, --当两个重载的参数个数相同,为int和float时,xLua区分不开 --因为Lua中只有number类型 OverloadClass.Function(10.2) OverloadClass.Func(10) //c#中该方法不需要参数,传参不报错,可以正常调用 OverloadClass.Func2() //c#的该方法需要参数,不传也不报错,也可以正常调用
LuaCallOverloadFunction.cs
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LuaCallOverloadFunction : MonoBehaviour { void Start () { XLuaMgr.Instance.LuaEnv.DoString("require('LuaCallOverloadFunction')"); } } [XLua.LuaCallCSharp] public class OverloadClass { public static void Func() { Debug.Log("Func"); } public static void Func2(string str) { Debug.Log("Func: " + str); } public static void Function() { Debug.Log("无参数的方法"); } public static void Function(int a) { Debug.Log("有一个 int 参数的方法: " + a); } public static void Function(float a) { Debug.Log("有一个 float 参数的方法: " + a); } public static void Function(int a, int b) { Debug.Log("有二个 int 参数的方法: " + a + " -- " + b); } public static void Function(string a) { Debug.Log("有一个 string 参数的方法: " + a); } }