xLuaUnity热更新学习(2) - lua调用C#

Lua调用C# lua不能直接访问C#,只能先从C#调用Lua脚本后再用Lua调用C# lua调用C#类 -- Lua调用C#类知识点 print("***Lua调用C#类知识点") -- CS.命名空间.类名 -- CS.UnityEngine.类名 -- 使用C#类实例化对象,默

Lua调用C#

lua不能直接访问C#,只能先从C#调用Lua脚本后再用Lua调用C#

lua调用C#类

-- Lua调用C#类知识点

print("***Lua调用C#类知识点")

-- CS.命名空间.类名

-- CS.UnityEngine.类名

  

-- 使用C#类实例化对象,默认调用的是无参构造

local obj1 = CS.UnityEngine.GameObject()

  

-- 为了方便使用和节约性能通过定义全局变量存储C#中的类

UE = CS.UnityEngine;

GameObject = UE.GameObject;

Debug = UE.Debug;

Vector3 = UE.Vector3;

local obj2 = GameObject("测试")

  

-- 类中的静态对象可以直接使用类.来调用

local obj3 = GameObject.Find("测试")

  

-- 对象的成员变量也是对象名.来调用

print(obj3.transform.position)

  

-- 成员方法要用:调用

obj3.transform:Translate(Vector3.forward)

  
  

--[[

public class TestLua

{

    public void speak(string str)

    {

        Debug.Log("testlua");

        Debug.Log(str);

    }

}

  

namespace Test

{

    public class TestLua2

    {

        public void speak(string str)

        {

            Debug.Log("testlua2");

            Debug.Log(str);

        }

    }

}

]]

  

-- 自定义类没命名空间直接用 CS.类名 有命名空间就CS.命名空间.类名

local obj4 = CS.TestLua()

obj4:speak("omg")

  

local obj5 = CS.Test.TestLua2()

obj5:speak("omg")

  

-- 继承Mono的类不能直接new

local obj6 = GameObject("脚本测试") -- 实例化一个新的类

-- xlua提供的typeof()可以得到类的Type

-- xlua不支持无参泛型所以要用AddComponent的重载方法

obj6:AddComponent(typeof(CS.TestLuaMono)); -- 这里的TestLuaMono是一个继承了Mono的自定义类

lua调用C#枚举

-- 枚举调用规则和类调用一样 CS.命名空间.枚举名.枚举成员


PrimitiveType = UE.PrimitiveType


local obj = GameObject.CreatePrimitive(PrimitiveType.Cube)

obj.name = "枚举立方体"

-- 自定义枚举跟Unity自带枚举调用一样  CS[.命名空间].枚举名.枚举成员
-- 有命名空间就带命名空间没有就算
--[[
public enum TestEnum
{
    S1,
    S2
}

]]

-- 枚举转换
-- 数值转枚举
MyEnum = CS.TestEnum
local a = MyEnum.__CastFrom(1)
print(a) -- S2 1

-- 字符串转枚举
local b = MyEnum.__CastFrom("S1")
print(b) -- S1 0

lua调用C#List和Dictionary

print("***lua调用list和dictionary")

--[[
public class TestLuaListAndDic
{
    public int[] i_arr = new int[5] { 1, 2, 3, 4, 5 };
    public List<int> li_arr = new List<int>();
    public Dictionary<string,int>  dic_si = new Dictionary<string, int>();

    public void Test1(int[] arr)
    {
        for (var i = 0; i < arr.Length; i++)
        {
            Debug.Log(arr[i]);
        }
    }
}

]]
local obj = CS.TestLuaListAndDic()

-- 数组长度
print(obj.i_arr.Length)
  
-- 数组元素
print(obj.i_arr[0])

-- 遍历 lua索引从1开始但c#是从0开始
-- 且lua这里相对于<=所以要用长度-1
for i = 0,obj.i_arr.Length-1 do
    print(obj.i_arr[i])
end

-- 创建数组 要使用C#中Array类的静态方法CreateInstance
-- 第一个参数是C#中的数据类型 第二个参数是长度
Array = CS.System.Array
int = CS.System.Int32
obj:Test1(Array.CreateInstance(typeof(int),5))

-- lua 调用list相关方法
-- 成员方法调用用 :
-- 成员方法调用用 :
-- 成员方法调用用 :
obj.li_arr:Add(1)
obj.li_arr:Add(2)
obj.li_arr:Add(3)
obj.li_arr:Remove(2)
for i = 0, obj.li_arr.Count-1 do
    print(obj.li_arr[i])
end

-- lua创建List对象
-- 这里相对于声明一个类CS.System.Collections.Generic.List(这里的是list里存什么类型)
List_String = CS.System.Collections.Generic.List(CS.System.String) -- 相对于List<String>
local l_s = List_String() -- 相对于 new List<String>
l_s:Add("aaa")
print(l_s[0])

-- lua 调用dictionary相关方法
-- 用法和C#一样
obj.dic_si:Add("qwq",7)
print(obj.dic_si["qwq"]) -- lua中创建的字典通过obj.dic_si["qwq"]得不到值,如果要通过键获取/设置值要用 对象名:get_Item([key]) 对象名:set_Item([k,v])

-- 遍历
for k,v in pairs(obj.dic_si) do
    print(k,v)
end


-- 在lua创建一个字典对象

local Dic_S_V3 = CS.System.Collections.Generic.Dictionary(CS.System.String,Vector3) -- 相对于Dictionary<String,Vector3>

local dic1 = Dic_S_V3()
dic1:Add("vf",Vector3.forward);
 -- lua中创建的字典通过obj.dic_si["qwq"]得不到值,如果要通过键获取/设置值要用 对象名:get_Item([key]) 对象名:set_Item([k,v])
print(dic1['vf'])

lua调用C# 拓展方法

print("***lua调用C#中拓展方法")

--[[
public static class TestLuaFuncExtendTools
{
    public static void move(this TestLuaFuncExtend obj)
    {
        Debug.Log("move");
    }
}

public class TestLuaFuncExtend
{
    public string name = "test";

    public void speak(string str)
    {
        Debug.Log(str);
    }

    public static void eat()
    {
        Debug.Log("eat");
    }
}
]]

TLFE = CS.TestLuaFuncExtend;

TLFE.eat()

local obj1 = TLFE()

print(obj1.name)

-- 成员方法

obj1:speak()

-- 拓展方法

-- 且需要在拓展类前面加上[LuaCallCSharp] 然后用xLua生成代码

-- 建议lua中用使用的类都加上该特性,可以提升性能

obj1:move() -- 使用拓展方法和使用成员方法一样使用:

lua调用C# ref和out方法

print("***lua调用C#中ref和out方法")
--[[
public class TestLuaRefOrOutFunc
{
    public int refFun(ref int a,int b)
    {
        a += b;
        return a+b;
    }
    public int outFun(out int a,int b)
    {
        a = 1;
        a += b;
        return a+b;
    }
    public int allFun(ref int a, out int b)
    {
        b = a;
        a += b;
        return a+b;
    }
}
]]

TC1 = CS.TestLuaRefOrOutFunc

local obj1 = TC1()
-- ref参数会以多返回值的形式返回得lua

local ab,a = obj1:refFun(10,5); -- 如果函数存在返回值,第一个值就是函数返回值,后续就算ref的结果从左到右一一对应且ref要一个默认值

print(ab)

print(a)
-- out同理ref

ab,a = obj1:outFun(5); -- out可以不用传一个默认值占位

print(ab)

print(a)

ab,a = obj1:allFun(5); -- out可以不用传一个默认值占位

print(ab)

print(a)

lua调用C# 重载函数

print("***lua调用C#中重载函数")
--[[
public class TestLuaFuncRw
{
    public void func1()
    {
        Debug.Log("hello world");
    }
    public void func1(string str)
    {
        Debug.Log("str");
    }
    public void func1(int a, int b)
    {
        Debug.Log(a+b);
    }
}
]]

TC2 = CS.TestLuaFuncRw

local obj1 = TC2()

-- lua调用C#重载函数直接调用就行了
-- 但因为lua数值类型只有number对C#中多精度的重载函数支持不好,使用时会出现预料之外的结果
obj1:func1()
obj1:func1("qwq")
obj1:func1(3,4)
-- 解决重载函数合糊的问题

-- xlua提供了解决方案 反射机制

-- 这种方法只做了解 尽量别用

-- Type是反射的关键类

-- 得到函数相关信息

local m1 = typeof(CS.TestLuaFuncRw):GetMethod("func1",{typeof(CS.System.Int32),typeof(CS.System.Int32)})

-- typeof(类名):GetMethod(重载方法名,{typeof(参数1类型),typeof(参数2类型),..})

-- 通过xlua提供的方法转成lua函数来使用

local f1 = xlua.tofunction(m1)

f1(obj1,8,8) -- 这里的第一个参数是调用者也就是实例对象

-- 如果是静态方法就第一个参数就不用传实例对象

lua调用C# 委托和事件

print("***lua调用C#中委托和实践")
--[[
public class TestLuaAction
{
    public UnityAction Action;

    public event UnityAction eventAction;

    public void doEvent()
    {
        if(eventAction != null) eventAction.Invoke();
    }
}
]]

TC3 = CS.TestLuaAction

local obj1 = TC3()

-- lua中第一次往委托中加函数

-- 需要先进行赋值然后才能继续加函数

obj1.Action = function ()

    print("helloworld")

end

-- 不建议这样写建议声明一个变量接收函数这样方便移除

obj1.Action = obj1.Action + function ()

    print("helloworld2")

end

-- 建议这样写

local fun1 = function ()

    print("helloworld3")

end

obj1.Action = obj1.Action + fun1

obj1.Action();

obj1.Action = obj1.Action - fun1

obj1.Action()

-- 清空委托中所有存储的函数

obj1.Action = nil

-- 清空就得重新赋值一边才能再加

-- 事件的写法和委托不一样

obj1:eventAction("+",fun1);

obj1:eventAction("+",fun1);

obj1:eventAction("-",fun1);

obj1:doEvent()


-- 事件不能直接赋nil清空

-- 在C#类声明一个成员方法在c#里面将事件变量赋null

-- 然后在lua里调用

lua使用C# 二维数组

print("***lua调用C#中二维数组")

--[[
public class TestLuaArray
{
    public int[,] arrs = new int[,]{{1,2,3},{1,2,3}};
}
]]

TC4 = CS.TestLuaArray

local obj2 = TC4()
-- 获取长度
print(obj2.arrs:GetLength(0)) -- 行长度

print(obj2.arrs:GetLength(1)) -- 列长度

-- print(obj2.arrs.Length)

-- 获取元素

print(obj2.arrs:GetValue(0,0)) -- 用数组自带的成员方法参数1行索引,参数2列索引

-- 遍历

for i = 0,obj2.arrs:GetLength(0) - 1 do

    for j = 0,obj2.arrs:GetLength(1) - 1 do

        print(obj2.arrs:GetValue(i,j))

    end

end

lua使用C# 的null和nil比较

-- 判空 nil和null没法进行==比较
-- 要用对象名:Equals(nil)进行比较
-- 但如果对象本身就是null 则会报错
function isNull(obj)
	if obj == nil or obj:Equals(nil)
		return true
	return false
end

给C# 的系统类添加特性

public static class ClassName{
	[CSharpCallLua] 
	// 会给这个列表内的所有类型加上特性
	public static List<Type> list = new List<Type>(){
		typeof(UnityAction<float>) // 要加特性的系统类
	}
	[LiaCallCSharp] 
	// 会给这个列表内的所有类型加上特性
	public static List<Type> list2 = new List<Type>(){
		typeof(UnityAction<float>) // 要加特性的系统类
	}
}

一定要在静态类中,改变后要重新生成代码

lua使用C# 中的协程

print("***lua调用C#协程")

-- 在场景中新建一个空物体

local obj = GameObject("协程")

-- 给创建的空物体添加一个继承Mono的脚本

local mono = obj:AddComponent(typeof(CS.TestLuaMono));

-- 利用这个脚本开启协程

-- 协程函数

fun = function ()

    local a= 1

    while a do

        a = a+1

        -- 不能使用yield return

        -- 使用lua中的协程返回

        print(a)

        if(a>10) then

            mono:StopCoroutine(c1); -- 停止和c#中一样

        end

        coroutine.yield(WaitForSeconds(1))

    end

end

-- 不能直接将lua函数传入协程开启

-- 得先调用xlua.util的cs_generator()方法

util = require("xlua.util")

c1 = mono:StartCoroutine(util.cs_generator(fun))

lua 使用C# 中的泛型函数

print("***lua调用泛型函数")

--[[

public class TestLuaTFunc
{
    public void fun1<T>(T a, T b)
    {
        Debug.Log(a);
    }
}
]]
local obj = CS.TestLuaTFunc();
-- 不支持 obj:fun1(1,2)
-- 支持有约束有参数的泛型函数
-- 不支持·没有约束的泛型函数
-- 不支持·有约束·没参数的泛型函数
-- 不支持·非class的约束


-- 让不能用的泛型函数能用的流程
-- 有限制只有Mono打包支持,il2cpp打包,如果泛型参数是引用类型才可以使用
-- 获取通用函数
local ge_fun1 = xlua.get_generic_method(CS.TestLuaTFunc,"fun1") -- 参数1:类名,参数2:函数名字符串

-- 指定泛型类型

local fun1_int = ge_fun1(CS.System.Int32)

-- 调用

fun1_int(obj,1,2) -- 非静态函数第一个参数要传调用对象
LICENSED UNDER CC BY-NC-SA 4.0
评论