xlua基础知识

xlua解析器

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;


public class Example : MonoBehaviour
{


    void Start()
    {
        //获得xlua的解析器
        LuaEnv env = new LuaEnv();

        //解析器运行Lua代码
        env.DoString("print('hello world');");

        //解析器释放
        env.Dispose();

    }
}

调用方法

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class DoString : MonoBehaviour
{


    void Start()
    {
        //luaCallCSharpCode();
        luaReturnData();
    }

    //lua中调用C#方法
    public void luaCallCSharpCode()
    {
        LuaEnv env = new LuaEnv();
        //lua中调用C#   CS.命名空间.类名.方法名(参数)
        env.DoString("CS.UnityEngine.Debug.Log('you good')");
        env.Dispose();
    }

    //lua返回值给C#
    public void luaReturnData()
    {
        LuaEnv env = new LuaEnv();
        var con = env.DoString("return 100,true");
        Debug.Log(con[0]);
        Debug.Log(con[1]);
        env.Dispose();
    }

}

加载lua脚本

默认加载器

要将lua脚本放在StreamingAssets文件夹下(自己创建的)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;

public class Loader : MonoBehaviour
{

    void Start()
    {
        LuaEnv env = new LuaEnv();
        //对应test.lua
        //内置加载器会扫描预制的目录,查找是否存在test.lua
        //xlua存在默认加载器,可在StreamingAssets文件夹中加载脚本
        env.DoString("require('test')");
        env.Dispose();
    }

}

AddLoader方法

  •  需要的是委托

自定义加载器

  • 自定义加载器会优先于内置的加载器
  • 当Lua代码执行require()函数时,自定义加载器会尝试获得文件的内容
  • 参数:被加载Lua文件的路径
  • xLua的解析环境,会执行我们自定义加载器返回的Lua代码
using UnityEngine;
using System.IO;
using XLua;

public class Loader : MonoBehaviour
{

    void Start()
    {
        LuaEnv env = new LuaEnv();
        
        //将自定义的加载器,加入到xlua的解析器环境中
        env.AddLoader(Envpath);
        env.DoString("require('test1')");
        env.Dispose();
    }

    private byte[] Envpath(ref string filepath)
    {
        //指向Assets路径
        string path = Application.dataPath;
        //该路径减掉7个字符(减掉Assets,包括一个/),加上自定义的路径,文件名,文件后缀名
        path = path.Substring(0, path.Length - 7) + "/DataPath/Lua/" + filepath + ".lua";
        //如果文件存在
        if (File.Exists(path))
        {
            //返回的是字节数组
            return File.ReadAllBytes(path);
        }
        else
        {
            return null;
        }

    }

}

自定义编辑器

  • 单例模式
  • 创建编辑器的构造函数
  • 自定义加载器,AddLoader在构造函数中执行
  • 执行lua脚本的方法DoString
  • 销毁编辑器
using UnityEngine;
using System.IO;
using XLua;

public class xluaEnv
{
    #region 单例模式

    private static xluaEnv instance;

    public static xluaEnv Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new xluaEnv();
            }
            return instance;
        }
    }

    #endregion

    #region 创建编辑器的构造函数 

    private LuaEnv _Env;

    private xluaEnv()
    {
        _Env = new LuaEnv();
        _Env.AddLoader(Envpath);
    }

    #endregion

    #region 自定义加载器

    private byte[] Envpath(ref string filepath)
    {
        string path = Application.dataPath;
        path = path.Substring(0, path.Length - 7) + "/DataPath/Lua/" + filepath + ".lua";
        if (File.Exists(path))
        {
            return File.ReadAllBytes(path);
        }
        else
        {
            return null;
        }

    }
    #endregion

    #region 执行lua脚本

    private object[] DoString(string code)
    {
        return _Env.DoString(code);
    }

    #endregion

    #region 销毁 

    public void Free()
    {
        _Env.Dispose();
        instance = null;
    }

    #endregion
}

lua调用C#

静态方法

C#代码

using UnityEngine;

namespace AJ
{
    public static class LuaCallStatic
    {
        public static int ID = 99;

        public static string Name
        {
            get;
            set;
        }

        public static string OutPut()
        {

            return "output返回";
        }

        public static void Default(string rb = "abs")
        {
            Debug.Log(rb);
        }


    }
}

lua代码

  • 规则:CS.命名空间.类名.变量名
--lua调用C#静态类

--规则CS.命名空间.类名.变量名

print(CS.AJ.LuaCallStatic.ID)


local x = CS.AJ.LuaCallStatic.Name
x = "admin"
print(x)

print(CS.AJ.LuaCallStatic.OutPut())

CS.AJ.LuaCallStatic.Default()
CS.AJ.LuaCallStatic.Default("canChange")

类对象

C#代码

public class LuaCallObject
{
    private string Name;

    public int HP
    {
        get;
        set;
    }

    public LuaCallObject()
    {

    }

    public LuaCallObject(string name)
    {
        this.Name = name;
    }

    public string OutPut()
    {
        return Name;
    }

}

lua代码

  • 规则CS.构造函数
  • 调用对象内的函数用 :
  • Lua实例化GameObject
--lua调用C#对象

--规则CS.构造函数

local object = CS.LuaCallObject()

--未赋值,nil
print(object.Name)

object.HP = 100
print(object.HP)

local object1 = CS.LuaCallObject("Tom")

--调用对象内的函数、
--用 :
print(object1:OutPut())

--Lua实例化GameObject
--参数为变量名
CS.UnityEngine.GameObject("LuaCreateGO")

结构体

C#代码

using UnityEngine;


public struct TestStruct
{
    public string Name;

    public string OutPut()
    {
        return Name;
    }

}

public class LuaCallStruct : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallStruct')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

Lua代码

  • 和对象调用一致
    规则CS.结构体
    这里不是构造方法
--lua调用C#结构体
--和对象调用一致
--规则CS.结构体
--这里不是构造方法

local object = CS.TestStruct()
print(object.Name)

print(object:OutPut())

枚举

C#代码

using UnityEngine;

public enum type
{
    Tom,
    Jerry,
    Dog
}

public class LuaCallenum : MonoBehaviour
{

    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallenum')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

lua代码

  • 规则:CS.命名空间.枚举名.枚举值
  • 枚举获得是userdata自定义数据类型
  • 转换获得枚举值 __CastFroom(参数)方法,参数可以是数值或字符串
--调用枚举
--CS.命名空间.枚举名.枚举值
local enum = CS.type.Tom

--枚举获得是userdata自定义数据类型
print(type(enum))
print(enum)
print(CS.type.Jerry)

--转换获得枚举值
print(CS.type.__CastFrom(0))
print(CS.type.__CastFrom("Dog"))

继承

C#代码

using UnityEngine;


public class Father
{
    public string name;

    public void Talk()
    {
        Debug.Log("父类的方法Talk");
    }

    public virtual void OverFunc()
    {
        Debug.Log("父类的虚方法");
    }
}

public class Child : Father
{
    public override void OverFunc()
    {
        Debug.Log("子类重写方法");
    }
}


public class LuaCallBase : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallBase')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

lua代码

--继承
--调用father
local father = CS.Father()
print(father.name)
father:Talk()
father:OverFunc()

local child = CS.Child()
child:OverFunc()

类的扩展

C#代码

  • 类扩展,需要给扩展方法编写的静态类添加[LuaCallCSharp],否则lua无法调用
using UnityEngine;
using XLua;


public class TestShow
{
    public void show()
    {
        Debug.Log("输出方法show");
    }
}

//类扩展,需要给扩展方法编写的静态类添加[LuaCallCSharp],否则lua无法调用
[LuaCallCSharp]
public static class IsExtend
{
    public static void ExtendFunc(this TestShow testShow)
    {
        Debug.Log("扩展类方法ExtendFunc");
    }
}


public class LuaCallExtend : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallExtend')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

lua代码:

--类的扩展
local testShow = CS.TestShow()

testShow:show()
testShow:ExtendFunc()

遇到问题:添加了 [LuaCallCSharp] 后,依然无法在lua中调用扩展的方法

解决方法:先 Clear Generate Code ,再 Generate Code 一遍

委托

C#代码

using UnityEngine;

public delegate void DeleShow();

public class IsDelegate
{
    public static DeleShow DeleStatic;

    public DeleShow Dymatic;

    public static void Show()
    {
        Debug.Log("委托方法输出");
    }
}

public class LuaCallDelegate : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallDelegate')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }

}

Lua代码

静态委托

  • 委托赋值不需要加括号
  • Lua中添加了函数到静态委托变量后,如果不再使用委托,要释放添加的委托
--委托
--注意委托赋值不需要加括号
CS.IsDelegate.DeleStatic = CS.IsDelegate.Show
CS.IsDelegate.DeleStatic()
--Lua中添加了函数到静态委托变量后,如果不再使用委托,要释放添加的委托
CS.IsDelegate.DeleStatic = nil
  •  添加lua中定义的方法
  • 可以添加多个方法
local func = function()
	print("Lua func show")
end

--覆盖添加委托
CS.IsDelegate.DeleStatic = func
CS.IsDelegate.DeleStatic = CS.IsDelegate.DeleStatic + CS.IsDelegate.Show
--这里输出func和Show两个方法的内容
CS.IsDelegate.DeleStatic()
CS.IsDelegate.DeleStatic = CS.IsDelegate.DeleStatic - func
--这里输出Show方法的内容
CS.IsDelegate.DeleStatic()
CS.IsDelegate.DeleStatic = nil

输出结果:

 

调用方法前判定

--调用前判定,防止为空时调用报错
if(CS.IsDelegate.DeleStatic ~= nil)
then
	CS.IsDelegate.DeleStatic()
end

 根据委托判定赋值方法

if(CS.IsDelegate.DeleStatic == nil)
then
	CS.IsDelegate.DeleStatic = func
else
	CS.IsDelegate.DeleStatic = CS.IsDelegate.DeleStatic + func
end

 动态委托

local obj = CS.IsDelegate()
obj.Dymatic = func
obj.Dymatic()
obj.Dymatic = nil

事件

C#代码

  • 定义事件
  • 定义响应事件的方法
using UnityEngine;

public delegate Event EventLua();

public class TestEvent
{
    public static event EventLua eventStatic;

    public static void StaticFunc()
    {
        Debug.Log("静态事件的方法输出");
    }

    //响应eventStatic事件
    public static void CallEventStatic()
    {
        eventStatic?.Invoke();
    }

    public event EventLua eventDynamic;

    public void DynamicFunc()
    {
        Debug.Log("动态事件方法输出");
    }

    //响应eventDynamic事件
    public void CallEventDynamic()
    {
        eventDynamic?.Invoke();
    }
}


public class LuaCallEvent : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallEvent')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

lua代码

  • 静态事件——规则:CS.类名.事件名("+",方法)
  • 动态事件——规则:CS.构造函数:事件名("-",方法)
--事件
CS.TestEvent.eventStatic("+",CS.TestEvent.StaticFunc)
CS.TestEvent.CallEventStatic()
CS.TestEvent.eventStatic("-",CS.TestEvent.StaticFunc)

local func = function()
	print("Lua func show")
end

local obj = CS.TestEvent()
obj:eventDynamic("+",func)
obj:CallEventDynamic()
obj:eventDynamic("-",func)

泛型

  • lua不支持泛型
  • 所以只能,在C#中将所有的泛型实现

C#代码

using UnityEngine;

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

    public void OutPut(string data)
    {
        OutPut<string>(data);
    }

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

public class LuaCallGenericType : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallGenericType')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

Lua代码

--解决泛型问题
CS.TestGeneric():OutPut("admin")
CS.TestGeneric():OutPut(12)

 

 实现创建物体,同时添加BoxCollider组件

  • xlua实现了typeof关键字,所以可以用类型API代替unity内置的泛型方法
local go = CS.UnityEngine.GameObject("CreateObject")
go:AddComponent(typeof(CS.UnityEngine.BoxCollider))

Out 和 Ref

C#代码

using UnityEngine;


public class TestOutRef
{
    public string testOut(string data)
    {
        return data;
    }

    public string testOut1(string data, out string test)
    {
        test = "testOut1 out";
        return data;
    }

    public string testRef1(string data, ref string test)
    {
        test = "testOut2 ref";
        return data;
    }

    public string testOut2(out string data, string test)
    {
        data = "testOut2 out";
        return test;
    }
}

public class LuaCallOutRef : MonoBehaviour
{
    void Start()
    {
        xluaEnv.Instance.DoString("require('LcallC/LuaCallOutRef')");
    }

    void OnDestroy()
    {
        xluaEnv.Instance.Free();
    }
}

lua代码

  • 在lua中,不需要out,ref 参数,只需要一个变量来接收out的值

--out ref

local obj = CS.TestOutRef()
print(obj:testOut("tom"))

local out1
local x,y = obj:testOut1("admin",out1)
print(x,y,out1)

local r1,ref2 = obj:testRef1("jerry")
print(r1,ref2)

local o2,out2 = obj:testOut2("dog")
print(o2,out2)

结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值