Unity3d ulua c#与lua交互+wrap文件理解

来源:互联网 发布:zeroc ice python 编辑:程序博客网 时间:2024/06/04 18:22

Unity3d ulua c#与lua交互+wrap文件理解


今天主要记录一下 c# 与 lua 的交互~~ 然后配以demo

C# 调用 lua 这个很简单,之前也有说过,这里不废话,直接贴

[csharp] view plain copy
  1. LuaScriptMgr mgr = new LuaScriptMgr ();  
  2. mgr.Start ();  
  3. mgr.DoFile ("LoginUI.lua");  


难点其实是Lua调用c#,以及效率问题

>> 最古老的是使用反射调用,不过由于反射的性能问题,目前基本上不怎么用了

>>wrap调用提升了反射在效率上的不足,但是必须自己去wrap,所以大版本更新是可以用到的,小版本更新目前还是得用到反射

ok~~ 肯定一头雾水,什么是wrap,怎么生成wrap,wrap工作原理是怎样的?(在今天之前我也是如此多的疑惑)


什么是wrap: wrap是对c#类的成员函数,成员变量,通过映射的方式。这里对比一下两个文件


这个是c#文件

[csharp] view plain copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class LoginData  {  
  5.     public string username;  
  6.     public string password;  
  7.     public int id;  
  8.   
  9.     public LoginData(){  
  10.     }  
  11.   
  12.     public LoginData(string username, string password, int id){  
  13.         this.username = username;  
  14.         this.password = password;  
  15.         this.id = id;  
  16.     }  
  17.   
  18.     public void Equip(string username, string password, int id){  
  19.         Debug.Log ("logindata equip log");  
  20.         if (this.username.Equals (username) && password.Equals (password) && this.id == id) {  
  21.             Debug.Log ("C# >>> LoginData = {username = " + this.username + ", password =" + this.password + ", id = " + this.id + " check ok!!!");  
  22.         } else {  
  23.             Debug.Log ("C# >>> LoginData = {username = " + this.username + ", password =" + this.password + ", id = " + this.id + " check error!!!");  
  24.         }  
  25.     }  
  26. }  
这个是wrap过后的文件

[csharp] view plain copy
  1. using System;  
  2. using LuaInterface;  
  3.   
  4. public class LoginDataWrap  
  5. {  
  6.     public static void Register(IntPtr L)  
  7.     {  
  8.         LuaMethod[] regs = new LuaMethod[]  
  9.         {  
  10.             new LuaMethod("Equip", Equip),  
  11.             new LuaMethod("New", _CreateLoginData),  
  12.             new LuaMethod("GetClassType", GetClassType),  
  13.         };  
  14.   
  15.         LuaField[] fields = new LuaField[]  
  16.         {  
  17.             new LuaField("username", get_username, set_username),  
  18.             new LuaField("password", get_password, set_password),  
  19.             new LuaField("id", get_id, set_id),  
  20.         };  
  21.   
  22.         LuaScriptMgr.RegisterLib(L, "LoginData"typeof(LoginData), regs, fields, typeof(object));  
  23.     }  
  24.   
  25.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  26.     static int _CreateLoginData(IntPtr L)  
  27.     {  
  28.         int count = LuaDLL.lua_gettop(L);  
  29.   
  30.         if (count == 0)  
  31.         {  
  32.             LoginData obj = new LoginData();  
  33.             LuaScriptMgr.PushObject(L, obj);  
  34.             return 1;  
  35.         }  
  36.         else if (count == 3)  
  37.         {  
  38.             string arg0 = LuaScriptMgr.GetString(L, 1);  
  39.             string arg1 = LuaScriptMgr.GetString(L, 2);  
  40.             int arg2 = (int)LuaScriptMgr.GetNumber(L, 3);  
  41.             LoginData obj = new LoginData(arg0,arg1,arg2);  
  42.             LuaScriptMgr.PushObject(L, obj);  
  43.             return 1;  
  44.         }  
  45.         else  
  46.         {  
  47.             LuaDLL.luaL_error(L, "invalid arguments to method: LoginData.New");  
  48.         }  
  49.   
  50.         return 0;  
  51.     }  
  52.   
  53.     static Type classType = typeof(LoginData);  
  54.   
  55.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  56.     static int GetClassType(IntPtr L)  
  57.     {  
  58.         LuaScriptMgr.Push(L, classType);  
  59.         return 1;  
  60.     }  
  61.   
  62.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  63.     static int get_username(IntPtr L)  
  64.     {  
  65.         object o = LuaScriptMgr.GetLuaObject(L, 1);  
  66.         LoginData obj = (LoginData)o;  
  67.   
  68.         if (obj == null)  
  69.         {  
  70.             LuaTypes types = LuaDLL.lua_type(L, 1);  
  71.   
  72.             if (types == LuaTypes.LUA_TTABLE)  
  73.             {  
  74.                 LuaDLL.luaL_error(L, "unknown member name username");  
  75.             }  
  76.             else  
  77.             {  
  78.                 LuaDLL.luaL_error(L, "attempt to index username on a nil value");  
  79.             }  
  80.         }  
  81.   
  82.         LuaScriptMgr.Push(L, obj.username);  
  83.         return 1;  
  84.     }  
  85.   
  86.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  87.     static int get_password(IntPtr L)  
  88.     {  
  89.         object o = LuaScriptMgr.GetLuaObject(L, 1);  
  90.         LoginData obj = (LoginData)o;  
  91.   
  92.         if (obj == null)  
  93.         {  
  94.             LuaTypes types = LuaDLL.lua_type(L, 1);  
  95.   
  96.             if (types == LuaTypes.LUA_TTABLE)  
  97.             {  
  98.                 LuaDLL.luaL_error(L, "unknown member name password");  
  99.             }  
  100.             else  
  101.             {  
  102.                 LuaDLL.luaL_error(L, "attempt to index password on a nil value");  
  103.             }  
  104.         }  
  105.   
  106.         LuaScriptMgr.Push(L, obj.password);  
  107.         return 1;  
  108.     }  
  109.   
  110.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  111.     static int get_id(IntPtr L)  
  112.     {  
  113.         object o = LuaScriptMgr.GetLuaObject(L, 1);  
  114.         LoginData obj = (LoginData)o;  
  115.   
  116.         if (obj == null)  
  117.         {  
  118.             LuaTypes types = LuaDLL.lua_type(L, 1);  
  119.   
  120.             if (types == LuaTypes.LUA_TTABLE)  
  121.             {  
  122.                 LuaDLL.luaL_error(L, "unknown member name id");  
  123.             }  
  124.             else  
  125.             {  
  126.                 LuaDLL.luaL_error(L, "attempt to index id on a nil value");  
  127.             }  
  128.         }  
  129.   
  130.         LuaScriptMgr.Push(L, obj.id);  
  131.         return 1;  
  132.     }  
  133.   
  134.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  135.     static int set_username(IntPtr L)  
  136.     {  
  137.         object o = LuaScriptMgr.GetLuaObject(L, 1);  
  138.         LoginData obj = (LoginData)o;  
  139.   
  140.         if (obj == null)  
  141.         {  
  142.             LuaTypes types = LuaDLL.lua_type(L, 1);  
  143.   
  144.             if (types == LuaTypes.LUA_TTABLE)  
  145.             {  
  146.                 LuaDLL.luaL_error(L, "unknown member name username");  
  147.             }  
  148.             else  
  149.             {  
  150.                 LuaDLL.luaL_error(L, "attempt to index username on a nil value");  
  151.             }  
  152.         }  
  153.   
  154.         obj.username = LuaScriptMgr.GetString(L, 3);  
  155.         return 0;  
  156.     }  
  157.   
  158.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  159.     static int set_password(IntPtr L)  
  160.     {  
  161.         object o = LuaScriptMgr.GetLuaObject(L, 1);  
  162.         LoginData obj = (LoginData)o;  
  163.   
  164.         if (obj == null)  
  165.         {  
  166.             LuaTypes types = LuaDLL.lua_type(L, 1);  
  167.   
  168.             if (types == LuaTypes.LUA_TTABLE)  
  169.             {  
  170.                 LuaDLL.luaL_error(L, "unknown member name password");  
  171.             }  
  172.             else  
  173.             {  
  174.                 LuaDLL.luaL_error(L, "attempt to index password on a nil value");  
  175.             }  
  176.         }  
  177.   
  178.         obj.password = LuaScriptMgr.GetString(L, 3);  
  179.         return 0;  
  180.     }  
  181.   
  182.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  183.     static int set_id(IntPtr L)  
  184.     {  
  185.         object o = LuaScriptMgr.GetLuaObject(L, 1);  
  186.         LoginData obj = (LoginData)o;  
  187.   
  188.         if (obj == null)  
  189.         {  
  190.             LuaTypes types = LuaDLL.lua_type(L, 1);  
  191.   
  192.             if (types == LuaTypes.LUA_TTABLE)  
  193.             {  
  194.                 LuaDLL.luaL_error(L, "unknown member name id");  
  195.             }  
  196.             else  
  197.             {  
  198.                 LuaDLL.luaL_error(L, "attempt to index id on a nil value");  
  199.             }  
  200.         }  
  201.   
  202.         obj.id = (int)LuaScriptMgr.GetNumber(L, 3);  
  203.         return 0;  
  204.     }  
  205.   
  206.     [MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]  
  207.     static int Equip(IntPtr L)  
  208.     {  
  209.         LuaScriptMgr.CheckArgsCount(L, 4);  
  210.         LoginData obj = (LoginData)LuaScriptMgr.GetNetObjectSelf(L, 1, "LoginData");  
  211.         string arg0 = LuaScriptMgr.GetLuaString(L, 2);  
  212.         string arg1 = LuaScriptMgr.GetLuaString(L, 3);  
  213.         int arg2 = (int)LuaScriptMgr.GetNumber(L, 4);  
  214.         obj.Equip(arg0,arg1,arg2);  
  215.         return 0;  
  216.     }  
  217. }  

当lua虚拟机启动的时候,会将此wrap文件加载进lua虚拟机,然后lua就可以识别此调用了,最后就形成了

Lua 调用 Wrap , Wrap调用C#的模式,实现了Lua调用C#


那么我们怎么来生成Wrap 呢 ? 

生成Wrap文件需要使用者自己手动的去WrapFile 文件填写需要Wrap的文件,大概像下面这个样子

_GT(typeof(LoginData)),

为啥需要添加这个呢? 其实很简单,这个要从Wrap文件是生成说起。

来到BindLua.cs 文件,你会发现里面有个叫Binding的函数,函数大概是这样的


生成的Wrap文件会放到Lua/Source/LuaWrap 这个目录下面, 具体可以参考生成过程。


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Lua文件如下,并没有什么特别的,只是一个简单的验证,并回调C#

[csharp] view plain copy
  1. local transform;  
  2. local gameObject;  
  3.   
  4. LoginUI = {};  
  5. local this = LoginUI;  
  6.   
  7. -- c# 向lua 传入参数, 然后lua创建c#对象,并调用c#方法(wrap方式调用)  
  8. function LoginUI.CheckUserName(username)  
  9.     if username=="pdw" then  
  10.         local loginData = LoginData.New();  
  11.         loginData:Equip(username, "123456", 1);  
  12.     else   
  13.     return "unknown username" end;  
  14. end  
  15.   
  16. -- c# 向 lua传入对象,然后lua 调用本对象  
  17. function LoginUI.CheckUserNameByData(data)  
  18.     data:Equip("pdw""123456", 1);  
  19. end  
UI 类如下,logindata上面已经贴了~这里不在贴了~
[csharp] view plain copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class LoginUIPanel : MonoBehaviour {  
  5.   
  6.     void OnGUI(){  
  7.         if (GUILayout.Button ("login")) {  
  8.             LoginData data = new LoginData ("pdw""123456", 1);  
  9.             LuaScriptMgr mgr = new LuaScriptMgr ();  
  10.             mgr.Start ();  
  11.             mgr.DoFile ("LoginUI.lua");  
  12.   
  13.             //mgr.CallLuaFunction ("LoginUI.CheckUserName", "pdw"); //传入lua字符串,并通过Wrap 创建对象返回  
  14.   
  15.             mgr.CallLuaFunction ("LoginUI.CheckUserNameByData", data); //传入lua对象  
  16.   
  17.         }  
  18.     }  
  19. }  
原创粉丝点击