1.NGUI通过lua层为按钮设置lua中点击回调方法时,需要把存储当前回调事件的脚本记录到list中,并在该LuaEnv Dispose()之前将所有onClick = null,否则会导致xlua抛出”try to dispose a LuaEnv with C# callback!” 异常
参考链接:http://www.cnblogs.com/ghl_carmack/p/7350530.html
参考代码:
private List ButtonEventListener = new List();
///
/// 添加单击事件
///
public void AddClick(GameObject go,UIEventListener.VoidDelegate luafunc)
{
if (go == null || luafunc == null) return;
UIEventListener uievent = UIEventListener.Get(go);
uievent.onClick = delegate(GameObject o) {
luafunc(go);
};
ButtonEventListener.Add(uievent);
}
///
/// 清除单击事件
///
public void ClearClick()
{
foreach (var listener in ButtonEventListener)
{
listener.onClick = null;
}
ButtonEventListener.Clear();
}
void OnDestroy()
{
ClearClick() ;
luaEnvironment.Dispose();
}
2.C# Call Lua 时的面向对象
(每个c#脚本对应一个lua文件,并且会重名)
lua中初始化代码如下:
Skill_10101 =
{
skillObj = 0
}
-- 这句是重定义元表的索引,就是说有了这句,这个才是一个类。
Skill_10101.__index = Skill_10101
-- 构造体,构造体的名字是随便起的,习惯性改为New()
function Skill_10101:New(sObj)
local self = { };
-- 初始化self,如果没有这句,那么类所建立的对象改变,其他对象都会改变
setmetatable(self, Skill_10101);
-- 将self的元表设定为Class
self.skillObj = sObj;
return self;
end
当c#脚本初始化时读取对应lua文件,代码如下:
public static string LuaStr = "Skill_";
public string LuaName { get { return LuaStr + this.SkillMode.dataBase.id; } }
// 对应该lua文件
private LuaTable _luaSkill = null;
// 对应该lua New出来的对象
private LuaTable _luaTableObject;
public LuaTable LuaTable
{
get
{
if (_luaSkill == null && _isExistLuaFile)
{
try
{
ManagerUtil.LuaManager.RequireFile("Skill/" + LuaName);
_luaSkill = ManagerUtil.LuaManager.GlobleLuaEnvTable.Get(LuaName);
//如果读取失败,说明不存在这个lua技能 择全部跳过
_isExistLuaFile = _luaSkill != null;
if (_isExistLuaFile)
{
// New一个luaTable对象 并在c# call lua 方法时将该对象传入第一个参数
var tab = _luaSkill.Get("New").Call(_luaSkill, this);
_luaTableObject = (LuaTable) tab[0];
}
}
catch
{
_isExistLuaFile = false;
}
}
return _luaSkill;
}
}
/// 回调lua中代码
/// 可以理解为从一个class中查找到该成员方法
/// 然后使用该class提前new出的对象调用该成员方法
public void CallLuaFunction(string FunName)
{
if (this.LuaTable != null)
{
var func = this.LuaTable.Get(funcName);
if (func != null)
{
func.Call(_luaTableObject);
}
}
}
3.C#调用lua传递参数问题
之前项目用ToLua时候,C#调用lua中的方法可以交给C#中的LuaManager读取lua方法,对应的lua参数是以params object[]形式传递进来的,但是换了xlua以后,必须直接将参数传递给LuaFunction调用,也就是说不允许在C#层将参数二次装箱处理,否则lua中只能读取出一个参数,并且为userdata类型.
// ToLua:
// 该方法写在lua管理类即可,其他C#脚本直接调用该方法
// 传递进的参数装箱为params object[]形式 再次传入LuaFunction
public void CallLuaFunction(string FunName,params object[] args)
{
if (this.LuaTable != null)
{
var func = this.LuaTable.Get(funcName);
if (func != null)
{
func.Call(_luaTableObject,args);
}
}
}
// XLua:
// 在每个调用lua方法的C#脚本中单独写出对应方法
// 由LuaFunction做装箱操作,直接传入params object[]型参数lua会读取错误
public void CallLuaFunction(string FunName,GameObject obj)
{
if (this.LuaTable != null)
{
var func = this.LuaTable.Get(funcName);
if (func != null)
{
func.Call(_luaTableObject,obj);
}
}
}