Generate Code干了什么
肉眼可見的,在Asset文件夾生成了XLua/Gen文件夾,里面有一些腳本。然后對加了[CSharpCallLua]的變量尋找引用,發現它被XLua/Gen/DelegatesGensBridge引用了。也可以在這里查哪些類型加了[CSharpCallLua]。
public override Delegate GetDelegateByType(Type type){if (type == typeof(NoParamNoReturn)){return new NoParamNoReturn(__Gen_Delegate_Imp0);}if (type == typeof(DelegateLua)){return new DelegateLua(__Gen_Delegate_Imp0);}if (type == typeof(MyActionIntInt)){return new MyActionIntInt(__Gen_Delegate_Imp1);}return null;}
沒加[CSharpCallLua]或沒生成代碼的變量被使用就報錯:
C#調用lua
1.新建LuaEnv類;
luaEnv=new LuaEnv();
2.執行luaEnv.AddLoader()。輸入是一個返回byte[]的函數,這個函數把一個lua腳本讀取出全部字節返回。當luaEnv.DoString()執行require一個lua腳本時,它調用這個函數,把需要的lua腳本名傳入,這個函數把腳本里的代碼讀出。
luaEnv.AddLoader(ProjectLoader);
byte[] ProjectLoader(ref string filePath){string path=string.Concat(luaPath,filePath,".lua");if(File.Exists(path)){return File.ReadAllBytes(path);}else{return null;}}
3.執行luaEnv.DoString(luaCode);執行單句lua代碼,一般是"require('xxx')"執行一個lua腳本。
4.要使用Lua里的任何變量,通過luaEnv.Global獲取;
public LuaTable Global{get{return luaEnv.Global;}}
?要獲取table,在C#里定義一個有table同名成員的結構體或類。要獲取函數,在C#里定義一個參數列表和返回類型相同的委托。在Global.Get<xxx>里填自定義的類型。
XLuaManager.Instance.Global.Get<xxx>("yyy");
Lua調用C#
靜態方法用.,實例的方法用:
local obj=CS.UnityEngine.GameObject.Find("xxx")
obj.transform:FindChild(0)
C#里一大堆方便語法不能用,需要用相應的函數。
沒有泛型<>,要用傳入type的重載;
創建數組不能用new,要用
CS.System.Array.CreateInstance(typeof(CS.System.Int32),長度);
創建列表用
local List_String=CS.System.Collections.Generic.List(CS.System.String)local list=List_String()
創建字典用
local Dic1=CS.System.Collections.Generic.Dictionary(CS.System.String,CS.xxx)
local dic1=Dic1()
讀取C#的字典元素可以用[],讀取Lua創建的字典元素用
dic:get_Item(xxx)
寫入字典元素用
dic:set_Item(xxx)
區別就是數組用CS.System一大串就直接創建了,List和Dictionary用CS.System一大串先得到類型xxx,再用xxx()創建實例。
二維數組讀取元素需要用GetValue(x,y);?
對象==null需要用.Equals(nil);
+=需要用xxx=xxx+yyy;
out和ref參數是多返回值;
委托第一次要用=賦值,后面加函數;
事件用myEvent("+",xxx)加函數;
總結:沒有new,部分類型(Lua創建的字典、二維數組)沒有[],沒有+=,沒有++,沒有<>。需要掌握相應的替代語法。
熱補丁
xLua熱補丁報錯在Lua里找不到xLua變量
原因:在lua腳本里把xlua打成了xLua。?
熱補丁協程報錯This type must add to CSharpCallLua: System.Collections.IEnumerator
問題
?'AppDomain' does not contain a definition for 'DefineDynamicAssembly':找不到AppDomain下的DefineDynamicAssembly方法
解決方法:把報錯扔給百度查,得到下面的文章。
C#反射中使用到Emit時,發現AppDomain.CurrentDomain.DefineDynamicAssembly()方法并不存在 - 名字已被使用N次 - 博客園 (cnblogs.com)
里面讓把AppDomain.CurrentDomain替換成AssemblyBuilder,照做,解決。原因應該是微軟把這個方法移動地方了,且改成了靜態方法。
百度查DefineDynamicAssembly,能看到官方文檔里有兩個類里出現這個方法。
AppDomain的適用版本:
AssemblyBuilder的適用版本:
創建運行環境報錯xlua assembly:<unknown assembly> type:<unknown type> member:(null)
原因:沒把Plugin文件夾拷過來
Lua里調用C#的委托報錯InvalidOperationException: not a generic method definition
C#代碼
Lua代碼
報錯:not a generic method definition
C#里添加并執行委托沒錯,Lua直接執行Func1()也沒錯。如果改成一個根本不存在的成員:
報錯會不一樣:
說明xLua是能找到這個成員的,但是不允許把函數賦給它。打印MyStaticDelegate,是nil,類型也是nil。給它賦一個整數,不報錯,打印,還是nil,執行,報錯說不能執行nil。
這是C#里定義的一個類:
在lua里遍歷它:
結果:
發現它含有NPC里的靜態成員,但是靜態字符串name和靜態委托MyStaticDelegate不見了,但是有一個UnderlyingSystemType,類型是NPC。
然后試圖把NPC實例化一個對象,對這個對象遍歷:
得到報錯:ob是NPC類型,不是table,不能遍歷:
遍歷了一下CS,以為會有很多東西:
結果:
連我定義的NPC類也沒有。
解決方法:在C#定義的無參無返回值委托、傳入自身的委托前面加[CSharpCallLua],不管是在Lua使用C#委托,還是C#委托接收Lua函數,都要加。有參且不為表自身的委托(如傳入字符串、整數)可以不加。
不要用print(CS.成員)驗證一個成員存不存在,就算不存在,也會添加這個成員,類型是table。下圖:print CS里一個根本不存在的成員,發現它有值,而且遍歷顯示這個成員已經被創建出來了:

Lua添加按鈕回調報錯:LuaException: c# exception:System.InvalidOperationException: not a generic method definition
原因:AddListener的輸入類型UnityAction沒加CSharpCallLua特性!
解決方法:加上下面一段代碼,xLua重新生成。
public static class CSLuaTypes{//記錄C#和Lua會調用對方的類型[CSharpCallLua]public static List<Type> cSharpCallLuaTypes=new List<Type>(){typeof(UnityAction),typeof(UnityAction<float>),typeof(UnityAction<bool>)};[LuaCallCSharp]public static List<Type> LuaCallCSharpTypes=new List<Type>(){};
}