十念 发表于 2024-8-12 21:31:35

Lua调用c#

1. 类

https://i-blog.csdnimg.cn/direct/7f4cc1974437442aa74b8ca878b5d762.png
--lua中使用C#的类非常简单
--固定套路
--CS.命名空间.类名
--Unity的类 比如 GameObject Transform等等 —— CS.UnityEngine.类名
--CS.UnityEngine.GameObject

--通过C#中的类 实例化一个对象 lua中没有new 所以我们直接 类名括号就是实例化对象
--默认调用的 相当于就是无参构造
local obj1 = CS.UnityEngine.GameObject()
local obj2 = CS.UnityEngine.GameObject("ABC")

--为了方便使用 并且节约性能 定义全局变量存储 C#中的类
--相当于取了一个别名
GameObject = CS.UnityEngine.GameObject
local obj3 = GameObject("ABC好爱同学们")

--类中的静态对象 可以直接使用.来调用
local obj4 = GameObject.Find("ABC")

--得到对象中的成员变量直接对象 . 即可
print(obj4.transform.position)
Debug = CS.UnityEngine.Debug
Debug.Log(obj4.transform.position)

Vector3 = CS.UnityEngine.Vector3
--如果使用对象中的 成员方法!!!!一定要加:
obj4.transform:Translate(Vector3.right)
Debug.Log(obj4.transform.position)

--自定义类 使用方法 相同只是命名空间不同而已
local t = CS.Test()
t:Speak("test说话")

local t2 = CS.MrTang.Test2()
t2:Speak("test2说话")

--继承了Mono的类
--继承了Mono的类 是不能直接new
local obj5 = GameObject("加脚本测试")
--通过GameObject的 AddComponent添加脚本
--xlua提供了一个重要方法 typeof 可以得到类的Type
--xlua中不支持 无参泛型函数所以 我们要使用另一个重载
obj5:AddComponent(typeof(CS.LuaCallCSharp))
https://i-blog.csdnimg.cn/direct/ab73ce80fcc747c29005d8a6231b97eb.png
--枚举调用
--调用Unity当中的枚举
--枚举的调用规则 和 类的调用规则是一样的
--CS.命名空间.枚举名.枚举成员
--也支持取别名
--同样 如果报错 需要在CustomSetting中去加上
PrimitiveType = CS.UnityEngine.PrimitiveType
GameObject = CS.UnityEngine.GameObject

local obj = GameObject.CreatePrimitive(PrimitiveType.Cube)

--自定义枚举 使用方法一样 只是注意命名空间即可
E_MyEnum =CS.E_MyEnum

local c = E_MyEnum.Idle
print(c)
--枚举转换相关
--数值转枚举
local a = E_MyEnum.__CastFrom(1)
print(a)
--字符串转枚举
local b = E_MyEnum.__CastFrom("Atk")
print(b)
https://i-blog.csdnimg.cn/direct/4a5268598a3444bdb22b8258db27d139.png
local obj = CS.Lesson3()

--Lua使用C#数组相关知识
--长度 userdata
--C#怎么用 lua就怎么用 不能使用#去获取长度
print(obj.array.Length)

--访问元素
print(obj.array)

--遍历要注意 虽然lua中索引从1开始
--但是数组是C#那边的规则 所以 还是得按C#的来
--注意最大值 一定要减1
for i=0,obj.array.Length-1 do
        print(obj.array)
end

--Lua中创建一个C#的数组 Lua中表示数组和List可以用表
--但是我要使用C#中???
--创建C#中的数组 使用 Array类中的静态方法即可
local array2 = CS.System.Array.CreateInstance(typeof(CS.System.Int32), 10)
print(array2.Length)
print(array2)
print(array2)
print(array2)

print("*********Lua调用C# list相关知识点***********")
--调用成员方法 用冒号!!!!!!
obj.list:Add(1)
obj.list:Add(2)
obj.list:Add(3)
--长度
print(obj.list.Count)
--遍历
for i=0,obj.list.Count - 1 do
        print(obj.list)
end
print(obj.list)

--在Lua中创建一个List对象
--老版本
local list2 = CS.System.Collections.Generic["List`1"]()
print(list2)
list2:Add("123")
print(list2)

--新版本 >v2.1.12
--相当于得到了一个 List<string> 的一个类别名 需要再实例化
local List_String = CS.System.Collections.Generic.List(CS.System.String)
local list3 = List_String()
list3:Add("5555555")
print(list3)

print("*********Lua调用C# dictionary相关知识点***********")
--使用和C#一致
obj.dic:Add(1, "123")
print(obj.dic)

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

--在Lua中创建一个字典对象
--相当于得到了一个 Dictionary<string, Vector3> 的一个类别名 需要再实例化
local Dic_String_Vector3 = CS.System.Collections.Generic.Dictionary(CS.System.String, CS.UnityEngine.Vector3)
local dic2 = Dic_String_Vector3()
dic2:Add("123", CS.UnityEngine.Vector3.right)
for i,v in pairs(dic2) do
        print(i,v)
end
--在Lua中创建的字典 直接通过键中括号得 得不到 是nil
print(dic2["123"])
print(dic2:TryGetValue("123"))
--如果要通过键获取值 要通过这个固定方法
print(dic2:get_Item("123"))
dic2:set_Item("123", nil)
print(dic2:get_Item("123"))

local Dic_String_String = CS.System.Collections.Generic.Dictionary(CS.System.String, CS.System.String)
local dic2 = Dic_String_String()
dic2:Add("id_1", "hello")
print(dic2:get_Item("id_1"))


for key, value in pairs(dic2) do
    print(key, value)
end
https://i-blog.csdnimg.cn/direct/30b7fdc9c6b3492cbcfdcb920f8656ce.png
//想要在Lua中使用拓展方法 一定要在工具类前面加上特定
//建议 Lua中要使用的类 都加上该特性 可以提升性能
//如果不加该特性 除了拓展方法对应的类 其它类的使用 都不会报错
//但是lua是通过反射的机制去调用的C#类效率较低

public static class Tools
{
    //Lesson4的拓展方法
    public static void Move(this Lesson4 obj)
    {
      Debug.Log(obj.name + "移动");
    }
}

public class Lesson4
{
    public string name = "EFT";

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

    public static void Eat()
    {
      Debug.Log("吃东西");
    }
}
Lesson4 = CS.Lesson4
--使用静态方法
--CS.命名空间.类名.静态方法名()
Lesson4.Eat()

--成员方法 实例化出来用
local obj = Lesson4()
--成员方法 一定用冒号
obj:Speak("CCC哈哈哈哈哈")

--使用拓展方法 和使用成员方法 一致
--要调用 C#中某个类的拓展方法 那一定要在拓展方法的静态类前面加上LuaCallCSharp特性
obj:Move()
https://i-blog.csdnimg.cn/direct/ec734ac8704c45da89da1a9d910e2ed7.png
Lesson5 = CS.Lesson5

local obj = Lesson5()

--ref参数 会以多返回值的形式返回给lua
--如果函数存在返回值 那么第一个值 就是该返回值
--之后的返回值 就是ref的结果 从左到右一一对应
--ref参数 需要传入一个默认值 占位置
--a 相当于 函数返回值
--b 第一个ref
--c 第二个ref
local a,b,c = obj:RefFun(1, 0, 0, 1)
print(a)
print(b)
print(c)
print("*********Lua调用C# out方法相关知识点***********")
--out参数 会以多返回值的形式返回给lua
--如果函数存在返回值 那么第一个值 就是该返回值
--之后的返回值 就是out的结果 从左到右一一对应
--out参数 不需要传占位置的值
local a,b,c = obj:OutFun(20,30)
print(a)
print(b)
print(c)


--混合使用时综合上面的规则
--ref需占位 out不用传
--第一个是函数的返回值之后 从左到右依次对应ref或者out
local a,b,c = obj:RefOutFun(20,1)
print(a)--300
print(b)--200
print(c)--400
https://i-blog.csdnimg.cn/direct/7ebff4997bea46bba37351afafda81b4.png
local obj = CS.Lesson6()

--虽然Lua自己不支持写重载函数
--但是Lua支持调用C#中的重载函数
print(obj:Calc())
print(obj:Calc(15, 1))

--Lua虽然支持调用C#重载函数
--但是因为Lua中的数值类型 只有Number
--对C#中多精度的重载函数支持不好 傻傻分不清
--在使用时 可能出现意想不到的问题
print(obj:Calc(10))
print(obj:Calc(10.2))


--解决重载函数含糊的问题
--xlua提供了解决方案 反射机制
--这种方法只做了解 尽量别用
--Type是反射的关键类
--得到指定函数的相关信息
local m1 = typeof(CS.Lesson6):GetMethod("Calc", {typeof(CS.System.Int32)})
local m2 = typeof(CS.Lesson6):GetMethod("Calc", {typeof(CS.System.Single)})

--通过xlua提供的一个方法 把它转成lua函数来使用
--一般我们转一次 然后重复使用
local f1 = xlua.tofunction(m1)
local f2 = xlua.tofunction(m2)
--成员方法 第一个参数传对象
--静态方法 不用传对象
print(f1(obj, 10))
print(f2(obj, 10.2))
https://i-blog.csdnimg.cn/direct/554eda3972d34969bde5625429ad42c6.png
local obj = CS.Lesson7()

--委托是用来装函数的
--使用C#中的委托 就是用来装lua函数的
local fun = function( )
        print("Lua函数Fun")
end

--Lua中没有复合运算符 不能+=
--如果第一次往委托中加函数 因为是nil 不能直接+
--所以第一次 要先等=
print("*********开始加函数***********")
obj.del = fun
--obj.del = obj.del + fun
obj.del = obj.del + fun
--不建议这样写 最好最好还是 先声明函数再加
obj.del = obj.del + function( )
        print("临时申明的函数")
end
--委托执行
obj.del()
print("*********开始减函数***********")
obj.del = obj.del - fun
obj.del = obj.del - fun
--委托执行
obj.del()
print("*********清空***********")
--清空所有存储的函数
obj.del = nil
--清空过后得先等
obj.del = fun
--调用
obj.del()

print("*********Lua调用C# 事件相关知识点***********")
local fun2 = function()
        print("事件加的函数")
end
print("*********事件加函数***********")
--事件加减函数和 委托非常不一样
--lua中使用C#事件 加函数
--有点类似使用成员方 冒号事件名("+", 函数变量)
obj:eventAction("+", fun2)
--最好最好不要这样写
obj:eventAction("+", function()
        print("事件加的匿名函数")
end)

obj:DoEvent()
print("*********事件减函数***********")
obj:eventAction("-", fun2)
obj:DoEvent()

print("*********事件清楚***********")
--清事件 不能直接设空
obj:ClaerEvent()
obj:DoEvent()
#region 委托和事件

public class Lesson7
{
    //申明委托和事件
    public UnityAction del;

    public event UnityAction eventAction;

    public void DoEvent()
    {
      if (eventAction != null)
            eventAction();
    }

    public void ClaerEvent()
    {
      eventAction = null;
    }
}

#endregion
https://i-blog.csdnimg.cn/direct/e938ececa43b4e7080b0f71141dff21c.png
local obj = CS.Lesson8()

--获取长度
print("行:" .. obj.array:GetLength(0))
print("列:" .. obj.array:GetLength(1))

--获取元素
--不能通过或者访问元素 会报错
print(obj.array:GetValue(0,0))
print(obj.array:GetValue(1,0))
print("********************")
for i=0,obj.array:GetLength(0)-1 do
        for j=0,obj.array:GetLength(1)-1 do
                print(obj.array:GetValue(i,j))
        end
end

obj:SetValue(obj.array, 99, 0, 0)
print(obj.array:GetValue(0,0))


local m = typeof(CS.System.Array):GetMethod("SetValue", {typeof(CS.System.Int32), typeof(CS.System.Int32), typeof(CS.System.Int32)})
print(m);
local ff = xlua.tofunction(m)
print(ff);
ff(obj.array, 1,0,0)
--print(obj.array:GetValue(0,0))
https://i-blog.csdnimg.cn/direct/c5922d6f404a426aa46102a19d189032.png
--往场景对象上添加一个脚本 如果存在就不加 如果不存在再加
GameObject = CS.UnityEngine.GameObject
Debug = CS.UnityEngine.Debug
Rigidbody = CS.UnityEngine.Rigidbody
Image = CS.UnityEngine.UI.Image

local obj = GameObject("测试加脚本")
--得到身上的刚体组件如果没有 就加 有就不管
local rig = obj:GetComponent(typeof(Rigidbody))
print(rig)
Debug.Log(rig)
if rig == nil then
        print(true)
end

local img = obj:GetComponent(typeof(Image))
print(img)
Debug.Log(img)
--判断空
--nil和null 没法进行==比较
--第一种方法
--if rig:Equals(nil) then
--if IsNull(rig) then
if rig:IsNull() then
        print("123")
        rig = obj:AddComponent(typeof(Rigidbody))
end
print(rig)
https://i-blog.csdnimg.cn/direct/6e45e1eb02494531bae0feb8d15a2bdb.png
https://i-blog.csdnimg.cn/direct/aa3ae8728cc94411a9b74405e3841cfe.png
https://i-blog.csdnimg.cn/direct/f23cfc3c65f24990b0a067d49ff6e129.png
https://i-blog.csdnimg.cn/direct/ba768588c4964f0a8ff6891a3335602c.png
https://i-blog.csdnimg.cn/direct/258cf13229bd40008c23b997e7892bbf.png
print("*********Lua调用C# 协程相关知识点***********")
--xlua提供的一个工具表
--一定是要通过require调用之后 才能用
util = require("xlua.util")
--C#中协程启动都是通过继承了Mono的类 通过里面的启动函数StartCoroutine

GameObject = CS.UnityEngine.GameObject
WaitForSeconds = CS.UnityEngine.WaitForSeconds
--在场景中新建一个空物体然后挂一个脚本上去 脚本继承mono使用它来开启协程
local obj = GameObject("Coroutine")
local mono = obj:AddComponent(typeof(CS.LuaCallCSharp))

--希望用来被开启的协程函数
fun = function()
        local a = 1
        while true do
                --lua中 不能直接使用 C#中的 yield return
                --就使用lua中的协程返回
                coroutine.yield(WaitForSeconds(1))
                print(a)
                a = a + 1
                if a > 10 then
                        --停止协程和C#当中一样
                        mono:StopCoroutine(b)
                end
        end
end
--我们不能直接将 lua函数传入到开启协程中!!!!!
--如果要把lua函数当做协程函数传入
--必须 先调用 xlua.util中的cs_generator(lua函数)
b = mono:StartCoroutine(util.cs_generator(fun))
https://i-blog.csdnimg.cn/direct/97dee1d0b26d4b3eb6bf47944bd1b1bc.png
https://i-blog.csdnimg.cn/direct/43968a1b97de46c79c1161ce36b9c31c.png
local obj = CS.Lesson12()

local child = CS.Lesson12.TestChild()
local father = CS.Lesson12.TestFather()

--支持有约束有参数的泛型函数
obj:TestFun1(child, father)
obj:TestFun1(father, child)

--lua中不支持 没有约束的泛型函数
--obj:TestFun2(child)

--lua中不支持 有约束 但是没有参数的泛型函数
--obj:TestFun3()

--lua中不支持 非class的约束
--obj:TestFun4(child)


--有一定的使用限制
--Mono打包 这种方式支持使用
--il2cpp打包如果泛型参数是引用类型才可以使用
--il2cpp打包如果泛型参数是值类型,除非C#那边已经调用过了 同类型的泛型参数 lua中才能够被使用

--补充知识 让上面 不支持使用的泛型函数 变得能用
--得到通用函数
--设置泛型类型再使用
--xlua.get_generic_method(类, "函数名")
local testFun2 = xlua.get_generic_method(CS.Lesson12, "TestFun2")
local testFun2_R = testFun2(CS.System.Int32)
--调用
--成员方法第一个参数 传调用函数的对象
--静态方法 不用传
testFun2_R(obj, 1)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Lua调用c#