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

U3D 专栏收录该内容
5 篇文章 0 订阅

上次已经搭建好了框架,这里开始使用框架,本文会比较长~~因为我搞了一天,也遇到了好多坑

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

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

	LuaScriptMgr mgr = new LuaScriptMgr ();
	mgr.Start ();
	mgr.DoFile ("LoginUI.lua");


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

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

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

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


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


这个是c#文件

using UnityEngine;
using System.Collections;

public class LoginData  {
	public string username;
	public string password;
	public int id;

	public LoginData(){
	}

	public LoginData(string username, string password, int id){
		this.username = username;
		this.password = password;
		this.id = id;
	}

	public void Equip(string username, string password, int id){
		Debug.Log ("logindata equip log");
		if (this.username.Equals (username) && password.Equals (password) && this.id == id) {
			Debug.Log ("C# >>> LoginData = {username = " + this.username + ", password =" + this.password + ", id = " + this.id + " check ok!!!");
		} else {
			Debug.Log ("C# >>> LoginData = {username = " + this.username + ", password =" + this.password + ", id = " + this.id + " check error!!!");
		}
	}
}
这个是wrap过后的文件

using System;
using LuaInterface;

public class LoginDataWrap
{
	public static void Register(IntPtr L)
	{
		LuaMethod[] regs = new LuaMethod[]
		{
			new LuaMethod("Equip", Equip),
			new LuaMethod("New", _CreateLoginData),
			new LuaMethod("GetClassType", GetClassType),
		};

		LuaField[] fields = new LuaField[]
		{
			new LuaField("username", get_username, set_username),
			new LuaField("password", get_password, set_password),
			new LuaField("id", get_id, set_id),
		};

		LuaScriptMgr.RegisterLib(L, "LoginData", typeof(LoginData), regs, fields, typeof(object));
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int _CreateLoginData(IntPtr L)
	{
		int count = LuaDLL.lua_gettop(L);

		if (count == 0)
		{
			LoginData obj = new LoginData();
			LuaScriptMgr.PushObject(L, obj);
			return 1;
		}
		else if (count == 3)
		{
			string arg0 = LuaScriptMgr.GetString(L, 1);
			string arg1 = LuaScriptMgr.GetString(L, 2);
			int arg2 = (int)LuaScriptMgr.GetNumber(L, 3);
			LoginData obj = new LoginData(arg0,arg1,arg2);
			LuaScriptMgr.PushObject(L, obj);
			return 1;
		}
		else
		{
			LuaDLL.luaL_error(L, "invalid arguments to method: LoginData.New");
		}

		return 0;
	}

	static Type classType = typeof(LoginData);

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int GetClassType(IntPtr L)
	{
		LuaScriptMgr.Push(L, classType);
		return 1;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int get_username(IntPtr L)
	{
		object o = LuaScriptMgr.GetLuaObject(L, 1);
		LoginData obj = (LoginData)o;

		if (obj == null)
		{
			LuaTypes types = LuaDLL.lua_type(L, 1);

			if (types == LuaTypes.LUA_TTABLE)
			{
				LuaDLL.luaL_error(L, "unknown member name username");
			}
			else
			{
				LuaDLL.luaL_error(L, "attempt to index username on a nil value");
			}
		}

		LuaScriptMgr.Push(L, obj.username);
		return 1;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int get_password(IntPtr L)
	{
		object o = LuaScriptMgr.GetLuaObject(L, 1);
		LoginData obj = (LoginData)o;

		if (obj == null)
		{
			LuaTypes types = LuaDLL.lua_type(L, 1);

			if (types == LuaTypes.LUA_TTABLE)
			{
				LuaDLL.luaL_error(L, "unknown member name password");
			}
			else
			{
				LuaDLL.luaL_error(L, "attempt to index password on a nil value");
			}
		}

		LuaScriptMgr.Push(L, obj.password);
		return 1;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int get_id(IntPtr L)
	{
		object o = LuaScriptMgr.GetLuaObject(L, 1);
		LoginData obj = (LoginData)o;

		if (obj == null)
		{
			LuaTypes types = LuaDLL.lua_type(L, 1);

			if (types == LuaTypes.LUA_TTABLE)
			{
				LuaDLL.luaL_error(L, "unknown member name id");
			}
			else
			{
				LuaDLL.luaL_error(L, "attempt to index id on a nil value");
			}
		}

		LuaScriptMgr.Push(L, obj.id);
		return 1;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int set_username(IntPtr L)
	{
		object o = LuaScriptMgr.GetLuaObject(L, 1);
		LoginData obj = (LoginData)o;

		if (obj == null)
		{
			LuaTypes types = LuaDLL.lua_type(L, 1);

			if (types == LuaTypes.LUA_TTABLE)
			{
				LuaDLL.luaL_error(L, "unknown member name username");
			}
			else
			{
				LuaDLL.luaL_error(L, "attempt to index username on a nil value");
			}
		}

		obj.username = LuaScriptMgr.GetString(L, 3);
		return 0;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int set_password(IntPtr L)
	{
		object o = LuaScriptMgr.GetLuaObject(L, 1);
		LoginData obj = (LoginData)o;

		if (obj == null)
		{
			LuaTypes types = LuaDLL.lua_type(L, 1);

			if (types == LuaTypes.LUA_TTABLE)
			{
				LuaDLL.luaL_error(L, "unknown member name password");
			}
			else
			{
				LuaDLL.luaL_error(L, "attempt to index password on a nil value");
			}
		}

		obj.password = LuaScriptMgr.GetString(L, 3);
		return 0;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int set_id(IntPtr L)
	{
		object o = LuaScriptMgr.GetLuaObject(L, 1);
		LoginData obj = (LoginData)o;

		if (obj == null)
		{
			LuaTypes types = LuaDLL.lua_type(L, 1);

			if (types == LuaTypes.LUA_TTABLE)
			{
				LuaDLL.luaL_error(L, "unknown member name id");
			}
			else
			{
				LuaDLL.luaL_error(L, "attempt to index id on a nil value");
			}
		}

		obj.id = (int)LuaScriptMgr.GetNumber(L, 3);
		return 0;
	}

	[MonoPInvokeCallbackAttribute(typeof(LuaCSFunction))]
	static int Equip(IntPtr L)
	{
		LuaScriptMgr.CheckArgsCount(L, 4);
		LoginData obj = (LoginData)LuaScriptMgr.GetNetObjectSelf(L, 1, "LoginData");
		string arg0 = LuaScriptMgr.GetLuaString(L, 2);
		string arg1 = LuaScriptMgr.GetLuaString(L, 3);
		int arg2 = (int)LuaScriptMgr.GetNumber(L, 4);
		obj.Equip(arg0,arg1,arg2);
		return 0;
	}
}

当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#

local transform;
local gameObject;

LoginUI = {};
local this = LoginUI;

-- c# 向lua 传入参数, 然后lua创建c#对象,并调用c#方法(wrap方式调用)
function LoginUI.CheckUserName(username)
	if username=="pdw" then
		local loginData = LoginData.New();
		loginData:Equip(username, "123456", 1);
	else 
	return "unknown username" end;
end

-- c# 向 lua传入对象,然后lua 调用本对象
function LoginUI.CheckUserNameByData(data)
	data:Equip("pdw", "123456", 1);
end

UI 类如下,logindata上面已经贴了~这里不在贴了~
using UnityEngine;
using System.Collections;

public class LoginUIPanel : MonoBehaviour {

	void OnGUI(){
		if (GUILayout.Button ("login")) {
			LoginData data = new LoginData ("pdw", "123456", 1);
			LuaScriptMgr mgr = new LuaScriptMgr ();
			mgr.Start ();
			mgr.DoFile ("LoginUI.lua");

			//mgr.CallLuaFunction ("LoginUI.CheckUserName", "pdw"); //传入lua字符串,并通过Wrap 创建对象返回

			mgr.CallLuaFunction ("LoginUI.CheckUserNameByData", data); //传入lua对象

		}
	}
}






©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值