資源描述:
《另類unity熱更新大法:代碼注入式補(bǔ)丁熱更新》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在應(yīng)用文檔-天天文庫。
1、另類Unity熱更新大法:代碼注入式補(bǔ)丁熱更新眼看Unity引擎熱火朝天,無數(shù)程序猿加入到了Unity開發(fā)的大本營。一些老項(xiàng)目,當(dāng)時(shí)ulua/slua還不如今天那樣的成熟,因此他們選擇了全c#開發(fā);也有一些出于性能考慮,全c#開發(fā);也有一些沒有太豐富運(yùn)營經(jīng)驗(yàn)的開發(fā)團(tuán)隊(duì),沒有想太多,用全c#爽爽地開發(fā)。用C#開發(fā)爽爽的日子一天一天的過去了,直到突然有一天,策劃老大說:“我們得做個(gè)熱更新模塊!”;突然有一天,老板說:“別人游戲用Lua熱更新,為什么我們不行?”;突然有一天,運(yùn)營說:“線上游戲出了個(gè)bug,重新編譯出
2、包審核得幾天??!”——嗯,這時(shí)候,受傷的總是程序猿。有沒有亡羊補(bǔ)牢,臨危受命的折衷方法?可以不用把C#改成Lua,可以不用區(qū)分平臺(tái)(AndroidDLL重載IOS卻不行),可以對(duì)任何代碼做修復(fù)的方法?有的,并且用很笨的一句代碼來概括:classFucker{voidFucking(){if(PatchScript.HasPatchScript("Fucker.Fucking")){//dopatchfuckPatchScript.CallPatchScript("Fucker.Fucking");return;
3、}//dooriginfuckLog.Info("Iamaoriginalfuck");}}往所有的函數(shù)注入代碼,當(dāng)存在補(bǔ)丁腳本時(shí)執(zhí)行補(bǔ)丁腳本,不存在時(shí)執(zhí)行原代碼。因此,本文的熱更新等同于打補(bǔ)丁。什么是熱更新?吐槽一點(diǎn),雖然我們這個(gè)方法確實(shí)將熱更新做成模塊了,但這絕對(duì)是迫不得已的。熱更新絕對(duì)不是一個(gè)功能模塊能實(shí)現(xiàn),它是一個(gè)底層架構(gòu)所決定的。要說一個(gè)項(xiàng)目不好,無法實(shí)現(xiàn)熱更新,這歸根到底是架構(gòu)沒想好、策劃沒堅(jiān)持、程序沒執(zhí)著、運(yùn)營懶得管等等各種各樣復(fù)雜原因所導(dǎo)致的。我心目中理想熱更新是怎樣?要熱?。骸?duì)任意部位的代碼
4、進(jìn)行修改;·運(yùn)行時(shí),自動(dòng)下載更新代碼,爾后無需重啟;·運(yùn)行時(shí),立即重載代碼,并繼續(xù)運(yùn)行;·兼顧開發(fā)環(huán)境與生產(chǎn)環(huán)境的簡便性;熱更新在Web開發(fā)領(lǐng)域非常普遍,畢竟HTTP是無狀態(tài)的;而游戲這種高實(shí)時(shí)性的開發(fā)相比,要想做好熱更新就確實(shí)需要架構(gòu)層的更多考慮了。怎么做好熱更新,我們還是回到主題,接下來介紹方法,可以達(dá)到什么目的:·對(duì)任意部位的方法體代碼進(jìn)行修改;·運(yùn)行時(shí),立即重載代碼,并繼續(xù)運(yùn)行·語言無關(guān):同樣的思路可以應(yīng)用在Java、C#、Go、C++等等·使用起來不太方便·亡羊補(bǔ)牢專用代碼注入補(bǔ)丁熱更新大法流程上面說
5、了很多廢話。接下直奔主題,要怎樣做到:classFucker{voidFucking(){if(PatchScript.HasPatchScript("Fucker.Fucking")){//dopatchfuckPatchScript.CallPatchScript("Fucker.Fucking");return;}//dooriginfuckLog.Info("Iamaoriginalfuck");}}我們要針對(duì)Fucker類的Fucking方法進(jìn)行更新,則新建Lua腳本Fucker.Fucking.lu
6、a--文件名Fucker.Fucking.luafunctionFunc()print("Iamapatchfuck!")endreturnFunc一個(gè)補(bǔ)丁腳本就此完成,當(dāng)程序運(yùn)行到Fucking函數(shù)時(shí),實(shí)際上它執(zhí)行的是Lua腳本,變相的實(shí)現(xiàn)了熱更新的功能——改變代碼的執(zhí)行行為。STEP1:執(zhí)行環(huán)境本文針對(duì)Unity游戲開發(fā),那么原語言,當(dāng)然是C#了;而打補(bǔ)丁的語言,當(dāng)時(shí)Lua了;在這里我們使用SLua插件,它的高質(zhì)量代碼和強(qiáng)大的反射功能,非常適合代碼注入補(bǔ)丁熱更新。classPatchScript{publi
7、cboolHasPatchScript(stringpath){returnFile.Exists("Script/"+path+".lua");}publicvoidCallScript(stringpath){stringscriptCode=File.ReadAllString(path);varluaFunc=this.luaState.doScript(scriptCode)asLuaFunction;luaFunc.call();}}STEP2:代碼注入嗯,執(zhí)行環(huán)境,非常的簡單,不就是簡單的if判斷
8、嗎?估計(jì)最令人迷惑的部分就是,如何往所有的C#函數(shù)體前部分插入代碼了。我們要做的,遍歷所有的c#文件,取得class類名,然后再分析函數(shù)名,定位函數(shù)在代碼中的起始位置、獲取函數(shù)的參數(shù)列表、參數(shù)類型……等等??雌饋砗軓?fù)雜,是不是要對(duì)c#做語法分析、詞法分析了?感覺工作量很大啊。幸好,輪子已經(jīng)做好了。這里要用到一個(gè)重要的庫——NRefactory。包括IDEMonoDevelop中的語法智