XLua遇坑總結(不定期更)
阿新 • • 發佈:2019-02-06
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<UIEventListener> ButtonEventListener = new List<UIEventListener>();
/// <summary>
/// 新增單擊事件
/// </summary>
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);
}
/// <summary>
/// 清除單擊事件
/// </summary>
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<LuaTable>(LuaName);
//如果讀取失敗,說明不存在這個lua技能 擇全部跳過
_isExistLuaFile = _luaSkill != null;
if (_isExistLuaFile)
{
// New一個luaTable物件 並在c# call lua 方法時將該物件傳入第一個引數
var tab = _luaSkill.Get<LuaFunction>("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<LuaFunction>(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<LuaFunction>(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<LuaFunction>(funcName);
if (func != null)
{
func.Call(_luaTableObject,obj);
}
}
}