lua调用C#

Posted 酱菜引擎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了lua调用C#相关的知识,希望对你有一定的参考价值。

一、lua调用类

在进行lua调用C#之前:Lua需要用Require(lua脚本名字)调用lua脚本 ,c#脚本里面也要调用这个lua脚本(Main脚本)

--固定套路写法
--CS.命名空间.类名
--Unity的类  比如  GameObject Transform等等   --- CS.UnityEngine.类名

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

--为了方便使用并且节约性能  定义全局变量存储一个类  相当于取了一个别名
GameObject = CS.UnityEngine.GameObject

--类中的静态对象可以直接使用.来调用
local obj = GameObject.Find("Main Camera")
print(obj)
--得到对象中的成员变量 直接.即可
print(obj.transform.position)

--得到对象中的成员方法 一定要加:
Vector3 = CS.UnityEngine.Vector3
obj.transform:Translate(Vector3.right)
print(obj.transform.position)

--调用自定义类
--没有命名空间的
local t = CS.Test()
t:Speak("yu")
--有命名空间的
local t1 = CS.yu.Test2()
t1:Speak("yu")

--给一个对象添加脚本
--继承了Mono的类  是不能直接new
local obj2 = GameObject("加脚本的对象")
obj2:AddComponent(typeof(CS.LuaCallCSharp))

--总结:
--Lua调用C#的类  CS.命名空间.类名 例如:CS.UnityEngine.类名
--没有命名空间的也就是自己写的类   CS.类名  例如:CS.Test

--实例化一个对象  CS.命名空间.类名()
--静态方法和变量  CS.命名空间.类名.方法或者变量

--成员变量和成员方法  实例化对象.变量名   实例化对象:方法名

--技巧知识点(重点)
--1、可以取别名  别名 = CS.命名空间.类名(方便使用、节约性能)
--2、xLua不支持无参泛型函数  所以我们要使用AddComponent(Type)  xLua提供了一个typeof方法  可以得到对象的Type
public class Test

    public void Speak(string str)
    
        Debug.Log("Test" + str);

    


namespace yu

    public class Test2
    
        public void Speak(string str)
        
            Debug.Log("Test2" + str);
        
    

二、lua调用枚举(Enum)

--枚举的调用规则和类的调用规则是一样的
--CS.命名空间.枚举名.枚举成员
--也支持取别名
PrimitiveType = CS.UnityEngine.PrimitiveType
GameObject = CS.UnityEngine.GameObject

local obj = GameObject.CreatePrimitive(PrimitiveType.Cube)

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

local idel = E_MyEnum.idel
print(idel)

--枚举的转换
--数值转枚举
local a = E_MyEnum.__CastFrom(1)
print(a)
--枚举转数值
local b = E_MyEnum.__CastFrom("Atk")
print(b)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Test

    public void Speak(string str)
    
        Debug.Log("Test" + str);

    


namespace yu

    public class Test2
    
        public void Speak(string str)
        
            Debug.Log("Test2" + str);
        
    


public enum E_MyEnum

    idel,
    move,
    Atk


三、lua调用数组、List、Dictionary

--数组
local obj = CS.Lesson3()
--Lua使用c#数组相关知识
--长度
local length = obj.array.Length
print(length)

--访问元素
print(obj.array[0])
--遍历要注意 虽然lua中索引从1开始
--但是数组是C#那边的规则  所以  还是按照C#的规则
for i = 0, obj.array.Length-1 do
    print(obj.array[i])
end

--通过lua创建一个C#数组 使用的是Array类中的静态方法即可
local Array1 = CS.System.Array.CreateInstance(typeof(CS.System.Int32),10)
print(Array1.Length)
print(Array1[0])

--列表
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[i])
end
print(obj.list)

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

--新版本
--相当于得到了一个 List<String> 的一个别名  需要再实例化
local List_String = CS.System.Collections.Generic.List(CS.System.String)

local list3 = List_String()
list3:Add("5555")
print(list3[0])

--字典
obj.dic:Add(1,"111")
obj.dic:Add(2,"222")
obj.dic:Add(3,"333")

--遍历字典
for key, value in pairs(obj.dic) do
    print("键"..key.."值"..value)
end

--在lua中创建一个字典对象
local Dic_String_Vector3 = CS.System.Collections.Generic.Dictionary(CS.System.String,CS.UnityEngine.Vector3)

local dic2 = Dic_String_Vector3()

dic2:Add("1",CS.UnityEngine.Vector3.right)
for key, value in pairs(dic2) do
    print(key,value)
end
--这里是一个坑  这样得不到
print(dic2["1"])
--通过键得到值  要通过固定的方法(有两种)
print(dic2:get_Item("1"))
print(dic2:TryGetValue("1"))   -- 这里有两个返回值
--改变字典中某个键的值
print(dic2:set_Item("1",nil))

#region 数组 List 字典
public class Lesson3

    public int[] array = new int[5]  1, 2, 3, 4, 5 ;
    public List<int> list = new List<int>();
    public Dictionary<int, string> dic = new Dictionary<int, string>();

#endregion

四、lua调用拓展方法

local Lesson4 = CS.Lesson4
--静态方法调用
Lesson4.walk()

--成员方法  实例化出来调用
local obj = Lesson4()
obj:Eat()
--使用拓展方法  和使用成员方法一致
obj:Move()

#region 拓展方法
/// <summary>
/// 想要在lua中使用拓展方法 一定要在工具类前面加上特性
/// 建议lua要使用的类  都加上该特性  可以提升性能
/// 如果不加上该特性  除了拓展方法对应的类 其它类加上也不会报错
/// 但是lua是通过反射的机制去调用C#类 效率较低
/// </summary>
[XLua.LuaCallCSharp]   //加完特性 记得在Unity里面去生成代码 下面有截图
public static class Tools

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

public class Lesson4

    public string name = "yu";

    public void Eat()
    
        Debug.Log("吃饭");
    

    public static void walk()
    
        Debug.Log("走路");
    

#endregion

五、Lua使用ref函数和out函数

print("*********Lua调用C# ref方法相关知识点***********")

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
#region ref和out

public class Lesson5

    public int RefFun(int a, ref int b, ref int c, int d)
    
        b = a + d;
        c = a - d;
        return 100;
    

    public int OutFun(int a, out int b, out int c, int d)
    
        b = a;
        c = d;
        return 200;
    

    public int RefOutFun(int a, out int b, ref int c)
    
        b = a * 10;
        c = a * 20;
        return 300;
    


#endregion

六、lua调用C#函数重载相关知识点

print("*********Lua调用C# 重载函数相关知识点***********")

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))
#region 函数重载

public class Lesson6

    public int Calc()
    
        return 100;
    

    public int Calc(int a, int b)
    
        return a + b;
    

    public int Calc(int a)
    
        return a;
    

    public float Calc(float a)
    
        return a;
    



#endregion

七、lua调用C#委托和事件

print("*********Lua调用C# 委托相关知识点***********")

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

八、lua调用C#二维数组相关知识点

print("*********Lua调用C# 二维数组相关知识点***********")

local obj = CS.Lesson8()

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

--获取元素
--不能通过[0,0]或者[0][0]访问元素 会报错
print(obj.array:GetValue(0,0))
print(obj.array:GetValue(1,0))
print("********************")
for i=0,obj.array:GetLength(0)-1 do
	for以上是关于lua调用C#的主要内容,如果未能解决你的问题,请参考以下文章

Unity中C#与Lua的交互

Unity热更新相关概念

lua调用C#

unity开发小贴士之三 UGUI-Lua Component回收

新人求助.unity3d能不能用lua来写代码

Unity热更新02-Lua基础-010-Lua多脚本执行