BZ易风

导航

 

配置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);
    }
}

 

posted on 2021-03-17 11:05  BZ易风  阅读(299)  评论(0编辑  收藏  举报