找回密码
 立即注册
查看: 253|回复: 0

Xlua Lua调用c#

[复制链接]
发表于 2021-8-13 15:26 | 显示全部楼层 |阅读模式
启动Lua脚本
using System.Collections;using System.Collections.Generic;using UnityEngine;using XLua;//本脚本启动Lua文件public class LuaCallCsharpBase : MonoBehaviour {    LuaEnv env = null;    private void Start()    {        env = new LuaEnv();        env.DoString("require 'LuaCallCSharp'"); //LuaCallCSharp.lua.txt    }    private void OnDestroy()    {        env.Dispose();    }}LuaCallCSharp.lua.txt
print("测试lua文件是否正确加载")--[[  一: 学习 lua  调用 Unity 系统 API   ]]---- 所有C#相关的都放到CS下,包括构造函数,静态成员属性、方法。--1: lua 中实例化一个 Unity 的对象local newGo=CS.UnityEngine.GameObject()newGo.name="New GameObject"--2: 查找游戏物体--   学习lua 访问Unity API 中静态属性与方法local TxtGo=CS.UnityEngine.GameObject.Find("Txt_Logo");TxtGo.name="Modify Name"--3: 得到游戏对象上的组件,学习使用冒号与句号(":",“.”)local txtLogo=TxtGo:GetComponent("UnityEngine.UI.Text")txtLogo.text="公告系统"--[[  二: 学习 lua  调用自定义C#脚本   ]]----lua中使用冒号,表示成员方法的调用。它自动完成把当前对象作为一个参数,传入方法。--lua中使用点,则表示静态属性与方法调用。它需要手工往方法中传递当前对象--类--如果有命名空间CS后面要加命名空间,比如CS.XluaPro.IsInvokedClass(XluaPro为命名空间)local IsInvoked=CS.IsInvokedClass--实例化local classObj=IsInvoked()   --自动调用父类与子类的构造函数--调用普通方法classObj:Mehtod1()                                        --ok--classObj.Mehtod1()                                --语法报错!classObj.Mehtod1(classObj)                    --语法OK--调用父类的字段与方法classObj:ShowFatherInfo();              --调用父类的方法print(classObj.FatherClassName)         --调用父类的公共字段print(classObj.ChildClassName)          --调用子类的公共字段--测试调用C#方法重载--有限重载,无法区分浮点和整型,精度,调用的C#函数是代码中排前面的那个classObj:Method2(10,20)classObj:Method2("abc","def")--测试C#中带有params 关键字的方法local intResult=classObj:Method3(20,70,"Hello ","World","EveryOne")print("调用parmas关键字的方法,返回数值= "..intResult)--测试lua调用C#中带有结构体参数的方法--lua 使用一个表,来映射C#的结构体。--定义一个表myStructTable={x="C#语言",y="lua语言"}classObj:Method4(myStructTable)--测试lua调用C#中带有接口参数的方法--lua 使用一个表,来映射C#的接口。--Unity里面要生成代码--定义一个表myInterfaceTable={        x=1000,        y=300,        Speak=function()                print("lua中 Speak 方法被调用!")        end}classObj:Method5(myInterfaceTable)--定义lua调用C#中带有委托参数的方法--Unity里面要生成代码--定义函数myDelegate=function(num)        print("lua 中对应委托方法。参数num="..num)endclassObj:Method6(myDelegate)--接收C#多返回数值--C#函数的返回值(如果有的话)算一个返回值,out算一个返回值,--   ref算一个返回值,然后从左往右对应lua的多返回值。local num1=10local num2=20local res1,res2,res3=classObj:Method7(num1,num2)--res1是返回值,res2和res3按参数顺序对应有out或者ref的参数print("res1="..res1)  --输出结果: 110print("res2="..res2)  --输出结果: 3000print("res3="..res3)  --输出结果: 999--lua中可以直接调用具有泛型为参数的方法myTable8={"lua语言","C#语言","C++语言"}classObj:Method8(myTable8);  --通过另外定义一个方法(Method_InvokeGenger)来调用泛型方法--让C#方法运行起来。classObj:Method_InvokeGenger()--lua中直接调用C#中定义的泛型方法 (错误)--local maxNum=CS.XluaPro.MyGengerric:GetMax<int>(20,30)  --报语法错误--print("maxNum="..maxNum)--lua调用C#中一个测试方法--c#定义一个方法,在方法内通过c#的扩展方法来调用泛型方法,classObj:Test8_InvokeExtensionMethod();--演示: 在lua中通过调用"扩展方法",来间接完成对C#“泛型方法”功能的实现。                                --  可以重载多个扩展方法来应用不同类型--c#带有泛型方法的类和扩展类都要加上 [XLua.LuaCallCSharp]--然后 重新生成代码--MyGengerric 注意后面要加括号--CS.XluaPro.MyGengerric():ExtGetMax(888,66)  XluaPro是自定义的命名空间local maxNum=CS.MyGengerric():ExtGetMax(888,66)  print("[在lua中扩展方法调用] maxNum="..maxNum)Lua要调用c#的内容
using System.Collections;using System.Collections.Generic;using UnityEngine;//定义结构体(建议结构体成员为小写)public struct MyStruct{    public string x;    public string y;}//定义接口//有标记的基本上都要生成代码,搭建c#和Lua沟通的桥梁[XLua.CSharpCallLua]public interface MyInterface{    int x { get; set; }    int y { get; set; }    void Speak();}//定义委托[XLua.CSharpCallLua]public delegate void MyDelegate(int num);public class IsInvokedClass : IsInvoked_FatherClass{    public string ChildClassName = "子类字段";    public IsInvokedClass()    {        Debug.Log("IsInvokedClass 子类构造函数");    }    public void Mehtod1()    {        Debug.Log("IsInvokedClass.cs/Mehtod1 方法");    }    /*  定义方法重载  */    public void Method2(int num1, int num2)    {        Debug.Log(GetType() + "/Method2()/ 重载方法/int浮点型/num1=" + num1 + " num2=" + num2);    }    public void Method2(float num1, float num2)    {        Debug.Log(GetType() + "/Method2()/ 重载方法/float浮点型/num1=" + num1 + " num2=" + num2);    }    public void Method2(string str1, string str2)    {        Debug.Log(GetType() + "/Method2()/ 重载方法/字符串类型/str1=" + str1 + " str2=" + str2);    }    //定义带有返回数值,有参数的方法,且有params 关键字    public int Method3(int num1, int num2, params string[] strArray)    {        Debug.Log(GetType() + "/Method3()/ 带有params关键字的方法/");        foreach (string item in strArray)        {            Debug.Log("输入的字符串内容:" + item);        }        return num1 + num2;    }    //带有结构体参数的方法    public void Method4(MyStruct p)    {        Debug.Log("测试lua调用结构体方法");        Debug.Log("p.x=" + p.x);        Debug.Log("p.y=" + p.y);    }    //方法具有接口为参数的    public void Method5(MyInterface p)    {        Debug.Log("测试lua调用具有接口为参数的方法");        Debug.Log("p.x=" + p.x);        Debug.Log("p.y=" + p.y);        p.Speak();    }    //方法具有委托为参数    public void Method6(MyDelegate p)    {        Debug.Log(GetType() + "/Method6()/委托参数:");        //调用        p.Invoke(88);    }    //定义一个具有多返回数值的方法    public int Method7(int num1, out int num2, ref int num3)    {        Debug.Log(GetType() + "/Method7()/测试lua接收C#的多返回数值");        num2 = 3000;        num3 = 999;        return num1 + 100;    }    //定义一个具有泛型方法为参数的。    public void Method8(List<string> strArray)    {        Debug.Log(GetType() + "/Method8()/这是一个具有泛型方法为参数的方法");        foreach (string item in strArray)        {            Debug.Log("泛型集合中的内容=" + item);        }    }    //C#方法中,调用我们自定义的泛型方法    public void Method_InvokeGenger()    {        int maxNum = 0;        int num1 = 100;        int num2 = 200;        MyGengerric obj = new MyGengerric();        maxNum = obj.GetMax<int>(num1, num2);        Debug.Log("C#中比较两个数字大小: "+maxNum);        //测试字符串的比较        //字符串的比较是比较第一个字符      //  string maxStr = string.Empty;       // string str1 = "xd";      // string str2 = "kb";      //  MyGengerric obj = new MyGengerric();      //  maxStr = obj.GetMax<string>(str1, str2);     //   Debug.Log("C#中比较两个字符串大小: " + maxStr);    }    //在C#中学习调用C#的扩展方法    public void Test8_InvokeExtensionMethod()    {        int maxNum = 0;        int num1 = 800;        int num2 = 200;        MyGengerric obj = new MyGengerric();        //通过扩展方法来调用泛型方法        maxNum = obj.ExtGetMax(num1, num2);        Debug.Log("[应用扩展方法] C#中得到最大数值=" + maxNum);    }}泛型方法的定义
/*** *          自定义泛型类 */using System.Collections;using System.Collections.Generic;using UnityEngine;using System;   [XLua.LuaCallCSharp]        public class MyGengerric        {        public T GetMax<T>(T num1, T num2) where T : IComparable        {            if (num1.CompareTo(num2)<0)            {                return num2;            }            else {                return num1;            }        }                        }拓展MyGengerric的方法
/*** * *          本类是一个“扩展方法”。 *           *          本类的功能是扩展原有“MyGengerric”类的功能。 * *   Description: *          注意: *             扩展方法有两大注意事项: *             A: 扩展方法类,必须是静态类。 *             B: 定义的扩展方法的参数,第一个参数必须是this ,然后跟需要扩展的类名称全称。 * * */using System.Collections;using System.Collections.Generic;using UnityEngine;    [XLua.LuaCallCSharp]    public static class Extension_MyGengerric        {    /// <summary>    /// 定义扩展方法,对类MyGengerric扩展一个方法    /// </summary>    /// <param name="gen"></param>    /// <param name="num1"></param>    /// <param name="num2"></param>    /// <returns></returns>     public static int ExtGetMax(this MyGengerric gen, int num1, int num2)     {            if (num1<num2)            {                return num2;            }            else {                return num1;            }       }                        }Lua对其他的调用1 枚举类型的调用枚举值就像枚举类型下的静态属性一样。testobj:EnumTestFunc(CS.Tutorial.TestEnum.E1)上面的EnumTestFunc函数参数是Tutorial.TestEnum类型的2   lua中可以使用“+/-”操作符,来增加与减少一个委托的调用。delegate 属性可以用一个luaFunction 来赋值。c#代码里, testobj里头有个事件定义是这样:public event Action TestEvent;在Lua内 增加事件回调testobj:TestEvent('+', lua_event_callback)移除事件回调testobj:TestEvent('-', lua_event_callback)--------event使用Eg:public event Action TestEvent;增加事件回调:testObj: TestEvent('+',lua_event_callback)移除事件回调:testObj: TestEvent('-',lua_event_callback)Lua调用C#经验总结一: lua 调用C#,需要在Xlua中生成“适配代码”,则在这个类打入一个[luaCallCSharp] 的标签二: 如果lua调用C#的系统API ,则无法拿到源代码,无法打入标签。则在配置文件(ExampleGenConfig.cs)使用“静态列表”方式解决。Eg:public static List<Type> mymodule_LuaCallCS_List=newList<Type>(){typeof(GameObject),typeof(Dictionary<string,int>),};然后把以上代码放入一个静态类中即可。三: 实际开发过程中,lua 调用C# 用的比较多。xlua 的优点体现的没有必要每次改的时候,都要生成代码。主要原理是依赖于编译器环境下,利用反射来动态生成代码接口。四: 在标有“[XLua.LuaCallCSharp]”的C#类中,添加新的方法后,如果是生成了代码类,则必须重新生成或者删除,否则Xlua 用以前生成的,进行注册查询,会出现lua 异常:“试图访问一个nil 的方法”
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 09:01 , Processed in 0.177834 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表