【XLua】Xlua基本用法

安装方法

从github打开腾讯的xlua页面下载xlua包解压复制到Assets文件夹下即可

自定义单例加载器

namespace Code.Rookie
{
    //https://shenjun-coder.github.io/LuaBook/大佬的博客
    public class XLuaEnv
    {
        public static XLuaEnv Instance = new XLuaEnv();

        private LuaEnv _luaEnv;

        private XLuaEnv()
        {
            _luaEnv = new LuaEnv();
            _luaEnv.AddLoader(ProjectLoader);
        }

        /*
         * 自定义加载器,会优先于系统内置加载器执行,当自定义加载器加载到文件以后,后续的加载器则不会执行
         * 当Lua代码执行require()函数时,自定义加载器会尝试获得文件的内容
         * filepath:被加载Lua文件的路径
         * 如果需要加载的文件不存在,返回null
         */
        private byte[] ProjectLoader(ref string filepath)
        {
            //因为 Application.dataPath在上线的代码中无法获得,所以上线时,需要将lua的存储路径,指向到Application.persistentDataPath
            string path = Application.dataPath;
            string delPath = "Assets";
            path = path.Substring(0, path.Length - delPath.Length) + "DataPath/Lua/" + filepath + ".lua";
            if (File.Exists(path))
            {
                return File.ReadAllBytes(path);
            }
            else
            {
                return null;
            }
        }

        /*
         * 释放luaEva
         */
        public void Dispose()
        {
            _luaEnv.Dispose();
            Instance = null;
        }

        public object[] DoString(string code)
        {
            return _luaEnv.DoString(code);
        }

        public LuaTable Global
        {
            get { return _luaEnv.Global; }
        }
    }
}

lua调用C#

lua调用静态类

c#脚本
namespace Code.C2L
{
    public class LuaCallStatic : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallStatic')");//lua脚本位置
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public static class TestStatic
    {
        public static int ID = 99;

        public static string Name { get; set; }

        public static string Output()
        {
            return "static";
        }

        public static void Default(string str = "abc")
        {
            Debug.Log(str);
        }
    }
}
lua脚本
--lua调用静态类

--调用规则(CS.命名空间.类名.变量/函数)
print(CS.Code.C2L.TestStatic.ID)

CS.Code.C2L.TestStatic.Name = "luanb"
print(CS.Code.C2L.TestStatic.Name)

print(CS.Code.C2L.TestStatic.Output())
--使用默认值
CS.Code.C2L.TestStatic.Default()
--使用lua传递的值
CS.Code.C2L.TestStatic.Default("def")

输出结果

在这里插入图片描述

lua调用对象

c#代码
namespace Code.C2L
{
    public class LuaCallObject : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallObject')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public class Npc
    {
        public string Name;

        public int Level { get; set; }

        public Npc()
        {
        }

        public Npc(string name)
        {
            Name = name;
        }

        public string Output()
        {
            return Name;
        }
    }
}
lua代码
--lua实例化类

--通过调用构造函数创建对象
local obj = CS.Code.C2L.Npc()
print(obj.Name)


local obj = CS.Code.C2L.Npc("lua")
print(obj.Name)

--调用对象的方法,用“:”不能用“.”,因为对象引用成员变量时,会隐形调用this,等同于lua中的self
print(obj:Output())

--使用lua在unity中实例化GameObject对象,添加一个碰撞体
local box = CS.UnityEngine.GameObject("luaCreate")
box:AddComponent(typeof(CS.UnityEngine.BoxCollider))
输出结果

在这里插入图片描述

lua调用结构体

c#代码
namespace Code.C2L
{
    public class LuaCallStruct : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallStruct')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public struct TestStruct
    {
        public string Name;

        public string Output()
        {
            return Name;
        }
    }
}
lua代码
--和创建对象一样
local obj=CS.Code.C2L.TestStruct()

obj.Name="lua"

print(obj.Name)
print(obj:Output())
输出结果

在这里插入图片描述

lua调用枚举

c#代码
namespace Code.C2L
{
    public class LuaCallEnum : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallEnum')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public enum TestEnum
    {
        TotalWar,
        Wot
    }
}
lua代码
print(CS.Code.C2L.TestEnum.TotalWar)
print(type(CS.Code.C2L.TestEnum.Wot))--userdata

--装换获得枚举值,使用索引获取越界不会报错,使用字符串不存在就会报错
print(CS.Code.C2L.TestEnum.__CastFrom(0))
print(CS.Code.C2L.TestEnum.__CastFrom("Wot"))
输出结果

在这里插入图片描述

lua调用对象继承

c#代码
namespace Code.C2L
{
    public class LuaCallExtend : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallExtend')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public class TestExtend
    {
        public void Output()
        {
            Debug.Log("类本身带的方法");
        }
    }

    [LuaCallCSharp]//类扩展,需要给扩展方法编写的静态类添加,否则lua无法调用到
    public static class MyExtend
    {
        public static void Show(this TestExtend obj)
        {
            Debug.Log("类扩展实现的方法");
        }
    }
}
lua代码
local obj=CS.Code.C2L.TestExtend()

obj:Output()
obj:Show()
输出结果

在这里插入图片描述

lua调用委托

c#代码
namespace Code.C2L
{
    public class LuaCallDelegate : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallDelegate')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public delegate void DelegateLua();

    public class TestDelegate
    {
        public static DelegateLua Static;
        public DelegateLua Dynamic;

        public static void StaticFunc()
        {
            Debug.Log("c#静态函数");
        }
    }

    public delegate void EventLua();

    public class TestEvent
    {
        public static event EventLua Static;

        public static void StaticFunc()
        {
            Debug.Log("这是静态函数");
        }

        public static void CallStatic()
        {
            Static?.Invoke();
        }

        public event EventLua Dynamic;

        public void CallDynamic()
        {
            Dynamic?.Invoke();
        }
    }
}
lua代码
CS.Code.C2L.TestDelegate.Static = CS.Code.C2L.TestDelegate.StaticFunc
CS.Code.C2L.TestDelegate.Static()
--静态委托使用完以后必须要释放
CS.Code.C2L.TestDelegate.Static = nil

local func = function()
    print("这是lua的函数")
end

--覆盖添加委托
CS.Code.C2L.TestDelegate.Static = func
--加减操作之前要判断委托是否有值
if (CS.Code.C2L.TestDelegate == nil) then
    CS.Code.C2L.TestDelegate.Static = func
else
    CS.Code.C2L.TestDelegate.Static = CS.Code.C2L.TestDelegate.Static + func
end

CS.Code.C2L.TestDelegate.Static = CS.Code.C2L.TestDelegate.Static - func
--调用之前应该确定委托有值
if (CS.Code.C2L.TestDelegate ~= nil) then
    CS.Code.C2L.TestDelegate.Static()
end

CS.Code.C2L.TestDelegate.Static = nil

local obj=CS.Code.C2L.TestDelegate()
obj.Dynamic=func
obj.Dynamic()

obj.Dynamic=nil


--lua添加事件
CS.Code.C2L.TestEvent.Static("+",CS.Code.C2L.TestEvent.StaticFunc)
CS.Code.C2L.TestEvent.CallStatic()
CS.Code.C2L.TestEvent.Static("-",CS.Code.C2L.TestEvent.StaticFunc)

local func = function()
    print("这是lua的函数")
end

local obj=CS.Code.C2L.TestEvent()
obj:Dynamic("+",func)
obj:CallDynamic()
obj:Dynamic("-",func)
输出结果

在这里插入图片描述

lua调用泛型

c#代码
namespace Code.C2L
{
    public class LuaCallGenericType : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallGenericType')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public class TestGenericType
    {
        public void Output<T>(T data)
        {
            Debug.Log("泛型方法:"+data.ToString());
        }

        public void Output(float data)
        {
            Output<float>(data);
        }

        public void Output(string data)
        {
            Output<string>(data);
        }
    }
}
lua代码
local obj=CS.Code.C2L.TestGenericType()

obj:Output(123)
obj:Output("lua")
输出结果

在这里插入图片描述

lua调用OutRef

c#代码
namespace Code.C2L
{
    public class LuaCallOutRef : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('C2L/LuaCallOutRef')");
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public class TestOutRef
    {
        public static string Func1()
        {
            return "Func1";
        }

        public static string Func2(string str1, out string str2)
        {
            str2 = "Func2 out";
            return "Func2";
        }

        public static string Func3(string str1, ref string str2)
        {
            str2 = "Func3 ref";
            return "Func3";
        }

        public static string Func4(ref string str1, string str2)
        {
            str1 = "Func4 ref";
            return "Func4";
        }
    }
}
lua代码
local r1 = CS.Code.C2L.TestOutRef.Func1()
print(r1)

--c# out返回的变量,会赋值给lua的第二个接受返回值的变量
local out2
local r2, out1 = CS.Code.C2L.TestOutRef.Func2("lua", out2)
print(r2, out1, out2)

--c# ref返回的变量,会赋值给lua的第二个接受返回值的变量
local ref2
local r3, ref1 = CS.Code.C2L.TestOutRef.Func3("root", ref2)
print(r3, ref1, ref2)

--即使out ref作为第一个参数,其结果依然会以lua的第二个返回值进行返回
local ref2
local r4, ref1 = CS.Code.C2L.TestOutRef.Func4(ref2, "root")
print(r4, ref1, ref2)

输出结果

在这里插入图片描述

C#调用lua

C#调用变量

lua代码
num=100
rate=99.99
isLua=true
name="lua"
c#代码
namespace Code.L2C
{
    public class CsharpCallVariable : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('L2C/CsharpCallVariable')");
            //luaEnv提供了一个成员变量Global,它可以用于c#获取lua的全局变量
            //Global的数据类型是c#实现的luaTable,luaTable的xLua实现的c#和lua中表对应的数据结构
            //xLua会将lua中的全局变量以Table的方式全部存储在Global中
            //通过运行环境,导出全局变量,类型是luaTable
            //luaTable是c#的数据对象,用于和lua中的大G表对应
            LuaTable g = XLuaEnv.Instance.Global;
            //从lua中将全局变量提取出来,<全局变量的类型>(全局变量的名称)
            //如果获取不存在的变量会报错,如果获取类型错误则会使用默认值
            int num = g.Get<int>("num");
            float rate = g.Get<float>("rate");
            bool isLua = g.Get<bool>("isLua");
            string name = g.Get<string>("name");

            Debug.Log(num + "  " + rate + "  " + isLua + "  " + name);
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }
}
输出结果

在这里插入图片描述

C#调用方法

lua代码
func1 = function()
    print("这是Lua中的func1")
end

func2 = function(name)
    print("这是Lua中的func2,参数是:" .. name)
end


func3 = function()
    return "这是lua中的func3"
end

func4 = function()
    return "这是lua中的func4",100
end

c#代码
namespace Code.L2C
{
    public delegate void Func1();

    public delegate void Func2(string name);

    public delegate string Func3();

    [CSharpCallLua]
    public delegate void Func4(out string name, out int id);

    public class CsharpCallFunction : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('L2C/CsharpCallFunction')");
            LuaTable g = XLuaEnv.Instance.Global;

            //lua的函数,会导出为c#的委托类型
            Func1 func1 = g.Get<Func1>("func1");
            func1();

            Func2 func2 = g.Get<Func2>("func2");
            func2("admin");

            Func3 func3 = g.Get<Func3>("func3");
            Debug.Log(func3());

            Func4 func4 = g.Get<Func4>("func4");
            string name;
            int id;
            func4(out name, out id);
            Debug.Log(name + "  " + id);
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }
}
输出结果

新版本unity使用[CSharpCallLua]不起作用,回头解决一波

C#调用table

lua代码
Core={}
Core.ID=100
Core.Name="root"
Core.IsLua=false

Core.Func1=function (name)
    print("这是Core表的Func1函数,接收到c#数据"..name)
end

Core.Func2=function ()
    return "这是Core表的Func2函数"
end

Core.Func3=function (self)
    print("这是Core表的Func3函数,Core表的成员变量Name是"..self.Name)
end

function Core:Fun4()
    print("这是Core表的Func4函数,Core表的成员变量Name是"..self.Name)
end
c#代码
namespace Code.L2C
{
    public class CsharpCallTable : MonoBehaviour
    {
        private void Start()
        {
            XLuaEnv.Instance.DoString("require('L2C/CsharpCallTable')");

            UseStruct();
        }

        public void UseStruct()
        {
            LuaTable g = XLuaEnv.Instance.Global;
            LuaCore core = g.Get<LuaCore>("Core");
            Debug.Log(core.Name);
        }

        private void OnDestroy()
        {
            XLuaEnv.Instance.Dispose();
        }
    }

    public delegate string OneStringReturn();

    [CSharpCallLua]
    public delegate void TransMy(LuaCore table);

    public struct LuaCore
    {
        public int ID;
        public string Name;
        public bool IsLua;

        public OneStringReturn Func1;
        public OneStringReturn Func2;
        public TransMy Func3;
        public TransMy Func4;
    }
}
输出结果
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Xlua的Plugins是用来支持在Unity中使用Lua语言的插件。下面是使用Xlua Plugins的基本流程: 1. 下载Xlua插件 可以在Xlua官网下载最新版本的Xlua插件。 2. 将Xlua插件导入Unity项目 将下载好的Xlua插件导入到Unity项目中。 3. 创建Lua脚本 在Unity项目中创建一个.lua文件,编写Lua脚本代码。 4. 将Lua脚本打包成.bytes文件 使用luajit工具将Lua脚本打包成.bytes文件。将打包好的.bytes文件拖入Unity项目中。 5. 在C#脚本中调用Lua脚本 在C#脚本中使用Xlua插件提供的API调用Lua脚本。例如: ```csharp using XLua; using UnityEngine; public class LuaScript : MonoBehaviour { private LuaEnv luaEnv; private void Awake() { luaEnv = new LuaEnv(); luaEnv.DoString("require 'example'"); } private void OnDestroy() { luaEnv.Dispose(); } } ``` 以上代码创建了一个LuaEnv对象,在Awake方法中加载了Lua脚本文件example.lua,最后在OnDestroy方法中释放了LuaEnv对象。 6. 在Lua脚本中调用C#方法和属性 在Lua脚本中可以通过XLua提供的API调用C#方法和属性。例如: ```lua local gameObject = CS.UnityEngine.GameObject('TestObject') local transform = gameObject.transform transform.position = CS.UnityEngine.Vector3(0, 0, 0) local time = CS.UnityEngine.Time.deltaTime print(time) ``` 以上代码创建了一个GameObject对象,并且获取了它的Transform组件,设置了Transform组件的位置。最后打印了当前帧的时间。 这就是使用Xlua Plugins的基本流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值