XLua遇坑总结(不定期更)

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);
       }
    }
}

你可能感兴趣的:(Unity,xlua)