您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)在ToLua框架中如何使用C#與Lua,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
Lua是目前國(guó)內(nèi)使用最多的熱更語(yǔ)言,基于Lua的熱更框架也非常多,最近學(xué)習(xí)了一下ToLua的熱更框架,主要使用的問(wèn)題在于C#和Lua之間的互調(diào),因此做一下學(xué)習(xí)記錄以備后查。
所謂“互調(diào)”,當(dāng)然要包括兩個(gè)方面,一是通過(guò)C#調(diào)用Lua代碼,二是通過(guò)Lua代碼調(diào)用C#腳本,第二點(diǎn)還包括注冊(cè)在C#腳本里的Unity物體。
ToLua框架主要是通過(guò)靜態(tài)綁定來(lái)實(shí)現(xiàn)C#與Lua之間的交互的,基本原理是通過(guò)建立一個(gè)Lua虛擬機(jī)來(lái)映射C#腳本,然后再通過(guò)這個(gè)虛擬機(jī)來(lái)運(yùn)行Lua腳本,Lua腳本在運(yùn)行時(shí)可以通過(guò)虛擬機(jī)反過(guò)來(lái)調(diào)用C#腳本里注冊(cè)過(guò)的物體,這種方式的優(yōu)勢(shì)在于比起使用反射的uLua來(lái)說(shuō)效率更高。
ToLua框架下可以將實(shí)現(xiàn)分成三大部分:普通的Unity+C#部分、ToLua虛擬機(jī)部分和Lua腳本部分,結(jié)構(gòu)見(jiàn)下圖:
ToLua結(jié)構(gòu)
目前國(guó)內(nèi)需要熱更的手游一般都將主要的邏輯框架和組件功能用C#實(shí)現(xiàn),而具體功能和調(diào)用放在Lua中,因?yàn)镃#是不能被打包進(jìn)AssetBundle中的,所以無(wú)法通過(guò)AssetBundle對(duì)代碼進(jìn)行改動(dòng),但是Lua是即時(shí)編譯型語(yǔ)言,并且可以被打包進(jìn)入AssetBundle中,在需要修改簡(jiǎn)單功能時(shí),將Lua代碼通過(guò)AssetBundle進(jìn)行更新即可。
首先是下載地址:
ToLua
這是作者的github地址,進(jìn)入以后點(diǎn)擊下載Zip,完成后解壓到自己需要的目錄,再用Unity打開(kāi)即可。
點(diǎn)擊下載zip即可
第一次打開(kāi)工程時(shí)會(huì)提示是否需要自動(dòng)生成注冊(cè)文件,新手可以選擇直接生成,若選擇了取消,也可以在編輯器菜單中手動(dòng)注冊(cè)?!@是一個(gè)非常重要的操作,后文也會(huì)提到。
下面開(kāi)始關(guān)于使用的正文。
前面有提到過(guò)ToLua的基本實(shí)現(xiàn)方式,這里可以再細(xì)化一點(diǎn):創(chuàng)建虛擬機(jī)——綁定數(shù)據(jù)——調(diào)用Lua代碼,這套步驟在框架自帶的Example里也非常清晰。
首先脫離Example實(shí)現(xiàn)一下這三個(gè)步驟。
ToLua虛擬機(jī)的創(chuàng)建非常簡(jiǎn)單,只需要new一個(gè)LuaState即可,我們建立一個(gè)C#腳本作為入口,引用LuaInterface命名空間,輸入以下代碼,將文件掛載到場(chǎng)景中的一個(gè)空物體上即可。
using LuaInterface; using UnityEngine; public class LuaScene : MonoBehaviour { string luaString = @" print('這是一個(gè)使用DoString的Lua程序') "; string luaFile = "LuaStudy"; LuaState state; void Start() { state = new LuaState();//建立Lua虛擬機(jī) state.Start();//啟動(dòng)虛擬機(jī) //使用string調(diào)用Lua state.DoString(luaString); //使用文件調(diào)用Lua //手動(dòng)添加一個(gè)lua文件搜索地址 string sceneFile = Application.dataPath + "/LuaStudy"; state.AddSearchPath(sceneFile); state.DoFile(luaFile); state.Require(luaFile); state.Dispose();//使用完畢回收虛擬機(jī) Debug.LogFormat("當(dāng)前虛擬機(jī)狀態(tài):{0}", null == state);//驗(yàn)證虛擬機(jī)狀態(tài) } }
這里使用的Lua腳本也非常簡(jiǎn)單
print('這是一個(gè)使用DoFile的Lua程序')
Lua掛載
ToLua直接調(diào)用Lua代碼的方式有兩種,一種是DoString,另一種是DoFile;此外還有一個(gè)Require方法,這個(gè)方法和前兩個(gè)方法不同的是,ToLua會(huì)將調(diào)用的Lua文件載入Lua棧中,而前兩者只是運(yùn)行一次,運(yùn)行之后保存在緩存中,雖然也可以后續(xù)調(diào)用,但是會(huì)。
在上述代碼中要注意,使用DoFile和Require方法時(shí),要手動(dòng)給目標(biāo)文件添加一個(gè)文件搜索位置。
運(yùn)行結(jié)果如下:
Lua運(yùn)行結(jié)果
最后,使用完畢記得清理虛擬機(jī),我使用null==state來(lái)進(jìn)行判斷,最后輸出“true”,說(shuō)明調(diào)用LuaState.Dispose()后,虛擬機(jī)已經(jīng)被清理。
我們上面實(shí)現(xiàn)了C#調(diào)用Lua文件和string,其實(shí)對(duì)于ToLua而且,直接調(diào)用string和文件并沒(méi)有本質(zhì)區(qū)別,最后都會(huì)轉(zhuǎn)換成byte[]進(jìn)行載入。
接下來(lái)實(shí)現(xiàn)一下ToLua調(diào)用指定Lua變量和函數(shù),這里通過(guò)文件導(dǎo)入Lua代碼。
首先是我們的Lua代碼,這一段Lua代碼一共有一個(gè)普通變量、一個(gè)帶有函數(shù)的表,一個(gè)無(wú)參函數(shù),一個(gè)有參函數(shù),功能非常簡(jiǎn)單,并且在這一段代碼中沒(méi)有調(diào)用。
num = 0 mytable={1,2,3,4} mytable.tableFunc=function() print('調(diào)用TableFunc'); end function Count() num=num+1 print('計(jì)數(shù)器+1,當(dāng)前計(jì)數(shù)器為'..num) return num; end function InputValue( param) print('[lua中調(diào)用:]InputValue方法傳入?yún)?shù):'..tostring( param)) end
然后是C#代碼,還是一樣的套路,先創(chuàng)建虛擬機(jī),讀入Lua文件。下面依次說(shuō)明普通變量、無(wú)參函數(shù)、有參函數(shù)和table的調(diào)用。
注意:如果帶有l(wèi)ocal標(biāo)識(shí),那么C#中無(wú)法直接獲取
普通變量
普通變量的調(diào)用非常簡(jiǎn)單,在載入文件后,通過(guò)LuaState[string]的形式就可以直接獲取到,也可以通過(guò)這個(gè)表達(dá)式來(lái)直接賦值。
無(wú)參函數(shù)
函數(shù)的調(diào)用有兩種方式,一是先緩存為L(zhǎng)uaFunction類(lèi)型后調(diào)用,二是直接能過(guò)Call方法調(diào)用。
有參函數(shù)
有參函數(shù)和無(wú)參函數(shù)調(diào)用的區(qū)別在于參數(shù)的傳入,在ToLua中重載了非常多的傳參函數(shù),與無(wú)參函數(shù)的調(diào)用方法相同,有參函數(shù)也有兩種調(diào)用方式,這里具體說(shuō)明一下傳入?yún)?shù)的不同方式。
傳入?yún)⒑驼{(diào)用分離。
這種方式一般需要先將函數(shù)緩存為L(zhǎng)uaFunction,然后使用BeginPcall方法標(biāo)記函數(shù),再使用Push或者PushArgs方法將參數(shù)傳入函數(shù),最后調(diào)用PCall,還可以調(diào)用EndPcall標(biāo)記結(jié)束。
//對(duì)方法傳入?yún)?shù) LuaFunction valueFunc = state.GetFunction("InputValue"); valueFunc.BeginPCall(); valueFunc.Push("--push方法從C#中傳入?yún)?shù)--"); valueFunc.PCall();
調(diào)用時(shí)直接傳入?yún)?shù)。
這是最符合一般操作邏輯的方式,但是查看實(shí)現(xiàn)代碼會(huì)發(fā)現(xiàn),事實(shí)上只是LuaFunction中封裝的一套實(shí)現(xiàn),其本質(zhì)和上一種是一樣的。
table是lua中的一個(gè)百寶箱,一切東西都可以往里裝,table里可以有普通的變量,還可以有table,也可以有方法。
在ToLua里對(duì)table的數(shù)據(jù)結(jié)構(gòu)進(jìn)行了解析,實(shí)現(xiàn)了非常多的方法,這里完全可以將table看一個(gè)LuaState來(lái)進(jìn)行操作,兩者沒(méi)有什么區(qū)別。
以下是完整的C#代碼,運(yùn)行結(jié)果后附。
using LuaInterface; using UnityEngine; public class LuaAccess : MonoBehaviour { string luaFile = "LuaAccess"; LuaState state; void Start() { state = new LuaState(); state.Start(); //使用文件調(diào)用Lua //手動(dòng)添加一個(gè)lua文件搜索地址 string sceneFile = Application.dataPath + "/LuaStudy"; state.AddSearchPath(sceneFile); state.Require(luaFile);//載入文件 //獲取Lua變量 Debug.Log("獲取文件中變量:" + state["num"]); state["num"] = 10; Debug.Log("設(shè)置文件中變量為:" + state["num"]); //調(diào)用Lua方法 LuaFunction luaFunc = state.GetFunction("Count"); luaFunc.Call(); Debug.Log("C#調(diào)用LuaFunc,函數(shù)返回值:" + state["num"]); Debug.Log("C#直接調(diào)用Count方法。"); state.Call("Count", false); //對(duì)方法傳入?yún)?shù) LuaFunction valueFunc = state.GetFunction("InputValue"); valueFunc.BeginPCall(); valueFunc.Push("--push方法從C#中傳入?yún)?shù)--"); valueFunc.PCall(); valueFunc.EndPCall(); valueFunc.Call("--直接Call方法從C#傳入?yún)?shù)--"); //獲取LuaTable LuaTable table = state.GetTable("mytable"); table.Call("tableFunc"); LuaFunction tableFunc = table.GetLuaFunction("tableFunc"); Debug.Log("C#調(diào)用table中的func"); tableFunc.Call(); Debug.Log("獲取table中的num值:"+table["num"]); //通過(guò)下標(biāo)直接獲取 for (int i = 0; i < table.Length; i++) { Debug.Log("獲取table的值:" + table[i]); } //轉(zhuǎn)換成LuaDictTable LuaDictTable dicTable = table.ToDictTable(); foreach (var item in dicTable) { Debug.LogFormat("遍歷table:{0}--{1}", item.Key, item.Value); } state.Dispose(); } }
Lua訪(fǎng)問(wèn)變量
之前在 @羅夏L的文章里看過(guò)一篇他關(guān)于lua調(diào)用C#的筆記,但總覺(jué)得少了點(diǎn)什么,所以在我自己記筆記的時(shí)候特別注意了一下具體的實(shí)現(xiàn)。
在@羅夏L的文章中,將一個(gè)C#對(duì)象作為參數(shù)傳入列表中,然后直接在Lua代碼里運(yùn)行對(duì)應(yīng)的方法名,其中少了幾個(gè)關(guān)鍵的步驟,如果只是進(jìn)行了這幾步,是實(shí)現(xiàn)不了在Lua里引用的。
首先還是從實(shí)現(xiàn)原理說(shuō)起,在文章開(kāi)始的第一節(jié)我提過(guò)ToLua的基本實(shí)現(xiàn)思路,并且將這套系統(tǒng)分成了三部分,在這三部分之中,ToLua作為一個(gè)橋梁實(shí)現(xiàn)了溝通Lua腳本和C#的功能,我們知道Lua的實(shí)質(zhì)是通過(guò)字節(jié)碼對(duì)C進(jìn)行了一套封裝,具有即時(shí)編譯的特點(diǎn),從C#或者其他語(yǔ)言中來(lái)調(diào)用Lua都不算太困難,只需要提前約定特定方法名然后載入腳本即可,但C#是需要提前編譯的,怎么通過(guò)一段解釋器來(lái)調(diào)用C#中的對(duì)象就是主要的難點(diǎn)了,ToLua實(shí)現(xiàn)的就是這兩方面的功能。
從這方面來(lái)分析,我覺(jué)得大多數(shù)人會(huì)想到的最直接的實(shí)現(xiàn)思路大概都是通過(guò)反射來(lái)實(shí)現(xiàn),uLua也是通過(guò)反射來(lái)實(shí)現(xiàn)的,但是反射的效率非常低,雖然確實(shí)可以實(shí)現(xiàn),但問(wèn)題還是非常明顯。
ToLua是通過(guò)方法名綁定的方式來(lái)實(shí)現(xiàn)這個(gè)映射的,首先構(gòu)造一個(gè)Lua虛擬機(jī),在虛擬機(jī)啟動(dòng)后對(duì)所需的方法進(jìn)行綁定,在虛擬機(jī)運(yùn)行時(shí)可以在Lua中調(diào)用特定方法,虛擬機(jī)變相地實(shí)現(xiàn)了一個(gè)解釋器的功能,在Lua調(diào)用特定方法和對(duì)象時(shí),虛擬機(jī)會(huì)在已綁定的方法中找到對(duì)應(yīng)的C#方法和對(duì)象進(jìn)行操作,并且ToLua已經(jīng)自動(dòng)實(shí)現(xiàn)了一些綁定的方法 。
基本原理大概了解以后,我們就可以來(lái)看看它的具體實(shí)現(xiàn)了。
第一步還是建立虛擬機(jī)并且啟動(dòng),為了實(shí)現(xiàn)Lua對(duì)C#的調(diào)用,首先我們要調(diào)用一下綁定方法,于是我們的代碼變成了下面這樣??梢钥吹?,這里和之前的唯一區(qū)別是增加了LuaBinder.Bind(state)方法,這一個(gè)方法內(nèi)部其實(shí)是對(duì)許多定義好的方法的綁定,也就是上面說(shuō)的綁定方法。
using LuaInterface; using UnityEngine; public class CSharpAccess : MonoBehaviour { private string luaFile = "LuaCall"; LuaState state; void Start() { state = new LuaState(); state.Start(); string sceneFile = Application.dataPath + "/LuaStudy"; state.AddSearchPath(sceneFile); // 注冊(cè)方法調(diào)用 LuaBinder.Bind(state); state.Require(luaFile);//載入文件 } }
然后我們加入一個(gè)變量和一個(gè)方法,我們要實(shí)現(xiàn)的是完成在Lua中對(duì)這個(gè)方法和變量的調(diào)用。
public string AccessVar = "++這是初始值++"; public void PrintArg(string arg) { Debug.Log("C#輸出變量值:" + arg); }
在有了目標(biāo)方法之后,我們要將這個(gè)變量和方法綁定進(jìn)入虛擬機(jī)中。
查看LuaState的實(shí)現(xiàn)代碼,可以發(fā)現(xiàn)綁定主要有RegFunction、RegVar和RegConstant三個(gè)方法,分別用于綁定函數(shù)/委托、變量和常量。在這里ToLua是通過(guò)一個(gè)委托來(lái)實(shí)現(xiàn)方法的映射,這個(gè)委托需要傳入一個(gè)luaState變量,類(lèi)型是IntPtr,這個(gè)變量的實(shí)質(zhì)是一個(gè)句柄,在實(shí)際操作中,會(huì)將虛擬機(jī)作為變量傳入。
public delegate int LuaCSFunction(IntPtr luaState); public void RegFunction(string name, LuaCSFunction func); public void RegVar(string name, LuaCSFunction get, LuaCSFunction set); public void RegConstant(string name, double d); public void RegConstant(string name, bool flag);
總結(jié)一下幾個(gè)方法的特點(diǎn):
這幾個(gè)方法都需要傳入一個(gè)string name,這個(gè)name就是之后在Lua中調(diào)用的變量或方法名。
RegConstant方法比較簡(jiǎn)單,傳入一個(gè)name再傳入一個(gè)常量即可;
RegFunction和RegVar都是通過(guò)LuaCSFunction類(lèi)型的委托實(shí)現(xiàn);
RegFunction需要一個(gè)LuaCSFunction委托,這個(gè)委托需要對(duì)原方法重新進(jìn)行一次實(shí)現(xiàn);
RegVar除了name之外,還需要兩個(gè)LuaCSFunction委托,可以理解為一個(gè)變量的get/set方法,如果只有g(shù)et或set,另一個(gè)留null即可。
接下來(lái)我們對(duì)AccessVar和PrintArg方法進(jìn)行一下LuaCSFunction形式的實(shí)現(xiàn)。
private int PrintCall(System.IntPtr L) { try { ToLua.CheckArgsCount(L, 2); //對(duì)參數(shù)進(jìn)行校驗(yàn) CSharpAccess obj = (CSharpAccess)ToLua.CheckObject(L, 1, typeof(CSharpAccess));//獲取目標(biāo)對(duì)象并轉(zhuǎn)換格式 string arg0 = ToLua.CheckString(L, 2);//獲取特定值 obj.PrintArg(arg0);//調(diào)用對(duì)象方法 return 1; } catch (System.Exception e) { return LuaDLL.toluaL_exception(L, e); } } private int GetAccesVar(System.IntPtr L) { object o = null; try { o = ToLua.ToObject(L, 1); //獲得變量實(shí)例 CSharpAccess obj = (CSharpAccess)o; //轉(zhuǎn)換目標(biāo)格式 string ret = obj.AccessVar; //獲取目標(biāo)值 ToLua.Push(L, ret);//將目標(biāo)對(duì)象傳入虛擬機(jī) return 1; } catch (System.Exception e) { return LuaDLL.toluaL_exception(L, e, o, "attempt to index AccessVar on a nil value"); } } private int SetAccesVar(System.IntPtr L) { object o = null; try { o = ToLua.ToObject(L, 1);//獲得變量實(shí)例 CSharpAccess obj = (CSharpAccess)o;//轉(zhuǎn)換目標(biāo)格式 obj.AccessVar = ToLua.ToString(L, 2);//將要修改的值進(jìn)行設(shè)定,注意這里如果是值類(lèi)型可能會(huì)出現(xiàn)拆裝箱 return 1; } catch (System.Exception e) { return LuaDLL.toluaL_exception(L, e, o, "attempt to index AccessVar on a nil value"); } }
可以看到這三個(gè)方法的格式都是一致的,通用的步驟如下:
使用ToLua中的方法對(duì)L句柄進(jìn)行校驗(yàn),出現(xiàn)異常則拋出,本例中使用ToLua.CheckArgsCount方法;
獲得目標(biāo)類(lèi)的實(shí)例,并轉(zhuǎn)換格式,具體轉(zhuǎn)換方法較多,可以根據(jù)需要在ToLua類(lèi)中選擇,本例中使用了ToLua.CheckObject和ToLua.ToObject等方法;
調(diào)用對(duì)應(yīng)方法,不同的方法調(diào)用略有區(qū)別。
值得注意的是,在ToLua的ToObjectQuat、ToObjectVec2等獲取值類(lèi)型的方法中,會(huì)出現(xiàn)拆裝箱的情況。
下一步將幾個(gè)方法注冊(cè)進(jìn)lua虛擬機(jī)。
注意這里有兩對(duì)方法,分別是BeginModule\EndModule和BeginClass\EndClass,BeginModule\EndModule用于綁定命名空間,可以逐層嵌套;而B(niǎo)eginClass\EndClass用于開(kāi)啟具體的類(lèi)型空間,具體的方法和變量綁定必須在這成對(duì)的方法之中,否則會(huì)導(dǎo)致ToLua崩潰(百試百靈,別問(wèn)我怎么知道的)。
private void Bind(LuaState L) { L.BeginModule(null); L.BeginClass(typeof(CSharpAccess), typeof(UnityEngine.MonoBehaviour)); state.RegFunction("Debug", PrintCall); state.RegVar("AccessVar", GetAccesVar, SetAccesVar); L.EndClass(); L.EndModule(); }
最后是我們的Lua代碼,非常簡(jiǎn)單,注意Debug和AccessVar調(diào)用的區(qū)別。
print('--進(jìn)入Lua調(diào)用--') local go = UnityEngine.GameObject.Find("LuaScene") local access=go:GetComponent("CSharpAccess") access:Debug("Lua調(diào)用C#方法") access.AccessVar="--這是修改值--" print('--Lua調(diào)用結(jié)束--')
完整C#代碼
using LuaInterface; using UnityEngine; public class CSharpAccess : MonoBehaviour { private string luaFile = "LuaCall"; LuaState state; void Start() { state = new LuaState(); state.Start(); string sceneFile = Application.dataPath + "/LuaStudy"; state.AddSearchPath(sceneFile); // 注冊(cè)方法調(diào)用 LuaBinder.Bind(state); Bind(state); Debug.Log("AccessVar初始值:" + AccessVar); state.Require(luaFile);//載入文件 Debug.Log("C#查看:" + AccessVar); state.Dispose(); } private void Bind(LuaState L) { L.BeginModule(null); L.BeginClass(typeof(CSharpAccess), typeof(UnityEngine.MonoBehaviour)); state.RegFunction("Debug", PrintCall); state.RegVar("AccessVar", GetAccesVar, SetAccesVar); L.EndClass(); L.EndModule(); } private int PrintCall(System.IntPtr L) { try { ToLua.CheckArgsCount(L, 2); //對(duì)參數(shù)進(jìn)行校驗(yàn) CSharpAccess obj = (CSharpAccess)ToLua.CheckObject(L, 1, typeof(CSharpAccess));//獲取目標(biāo)對(duì)象并轉(zhuǎn)換格式 string arg0 = ToLua.CheckString(L, 2);//獲取特定值 obj.PrintArg(arg0);//調(diào)用對(duì)象方法 return 1; } catch (System.Exception e) { return LuaDLL.toluaL_exception(L, e); } } public void PrintArg(string arg) { Debug.Log("C#輸出變量值:" + arg); } [System.NonSerialized] public string AccessVar = "++這是初始值++"; private int GetAccesVar(System.IntPtr L) { object o = null; try { o = ToLua.ToObject(L, 1); //獲得變量實(shí)例 CSharpAccess obj = (CSharpAccess)o; //轉(zhuǎn)換目標(biāo)格式 string ret = obj.AccessVar; //獲取目標(biāo)值 ToLua.Push(L, ret);//將目標(biāo)對(duì)象傳入虛擬機(jī) return 1; } catch (System.Exception e) { return LuaDLL.toluaL_exception(L, e, o, "attempt to index AccessVar on a nil value"); } } private int SetAccesVar(System.IntPtr L) { object o = null; try { o = ToLua.ToObject(L, 1);//獲得變量實(shí)例 CSharpAccess obj = (CSharpAccess)o;//轉(zhuǎn)換目標(biāo)格式 obj.AccessVar = ToLua.ToString(L, 2);//將要修改的值進(jìn)行設(shè)定 return 1; } catch (System.Exception e) { return LuaDLL.toluaL_exception(L, e, o, "attempt to index AccessVar on a nil value"); } } }
運(yùn)行結(jié)果
Lua調(diào)用C#
那么最后,我們回到本節(jié)開(kāi)始, @羅夏L的文章里是哪里出現(xiàn)了問(wèn)題?
我在lua中加入了一行access:PrintArg("PrintArg")調(diào)用方法,發(fā)現(xiàn)Unity報(bào)了這樣的錯(cuò)誤:
直接調(diào)用方法名報(bào)錯(cuò).png
說(shuō)明單純這樣是做不到直接調(diào)用方法的,仔細(xì)看文章,我發(fā)現(xiàn)他有提到這樣的內(nèi)容:
首先將自己寫(xiě)的類(lèi) 放到 CustomSettings 里 就是CallLuafunction
BindType[] customTypeList
放到這個(gè)數(shù)組里 注冊(cè)進(jìn)去供lua使用
這里是不是他說(shuō)得不夠詳細(xì)?我找到這個(gè)類(lèi),發(fā)現(xiàn)這個(gè)類(lèi)里記錄了非常多的Unity自帶類(lèi),這讓我想起了第一次啟動(dòng)Lua時(shí)的提示,心里生出了一個(gè)疑問(wèn):這些數(shù)據(jù)是不是用于自動(dòng)注冊(cè)生成類(lèi)的呢?
//在這里添加你要導(dǎo)出注冊(cè)到lua的類(lèi)型列表 public static BindType[] customTypeList = { _GT(typeof(LuaInjectionStation)), _GT(typeof(InjectType)), _GT(typeof(Debugger)).SetNameSpace(null),
...以下部分省略
沿著調(diào)用鏈,我找到了這個(gè)變量的引用,果然,最這個(gè)數(shù)據(jù)是用于類(lèi)型注冊(cè)的。
我將這個(gè)類(lèi)放到了數(shù)組的最后,點(diǎn)擊Clear wrap files,完成后立即彈出了數(shù)據(jù)自動(dòng)生成的對(duì)話(huà)框,點(diǎn)擊確認(rèn),
重新生成注冊(cè)
自動(dòng)生成
接下來(lái)我重新運(yùn)行了lua腳本:
print('--進(jìn)入Lua調(diào)用--') local go = UnityEngine.GameObject.Find("LuaScene") local access=go:GetComponent("CSharpAccess") access:Debug("Lua調(diào)用C#方法") access.AccessVar="--這是修改值--" print('--Lua調(diào)用結(jié)束--') access:PrintArg("PrintArg")
成功運(yùn)行
成功運(yùn)行,說(shuō)明ToLua實(shí)現(xiàn)了一整套綁定方案,只需要將所需要的內(nèi)容配置完成即可。
關(guān)于在ToLua框架中如何使用C#與Lua就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。