iOS代码质量要求_Unity移动端代码热更新技术学习总结
為什么需要熱更新
游戲總是伴隨著不斷的開(kāi)發(fā)與維護(hù),我們不能要求玩家每次都將游戲客戶端卸載重裝,所以需要熱更新技術(shù)來(lái)在不需要重裝客戶端的情況下下載更新游戲里的代碼(其實(shí)資源也需要熱更新,但是因?yàn)椴僮飨到y(tǒng)沒(méi)有對(duì)資源文件熱更新做限制,所以這里按下不提)。
直接覆蓋DLL
這里只說(shuō)android平臺(tái),unity打包安裝包之后會(huì)生成一個(gè)apk文件,該文件事實(shí)上是一個(gè)zip文件,只是后綴名不同,解壓可以看到在 assetsbinDataManaged 目錄下有 predefined assemblies,也就是腳本編譯成的DLL(默認(rèn)名為Assembly-CSharp,在VS的 Solution Explorer 里可以看到),這就是游戲運(yùn)行時(shí)代碼所在,如果可以將新代碼的dll直接覆蓋替換,即可實(shí)現(xiàn)熱更的目的,自定義 assemblies 的情況也差不多,覆蓋需要的dll就完事了(要注意版本,宏之類的坑)。上面說(shuō)的是mono的情況,IL2CPP的話,則是另外的目錄(libarmeabi-v7a)這里有個(gè)小坑,so文件中存放的只是代碼段,數(shù)據(jù)段(比如字符串)是在assetsbinDataManagedMetadataglobal-metadata.dat 中。我測(cè)試的時(shí)候只改了覆蓋了so文件,結(jié)果修改沒(méi)有生效讓我困惑了老半天 。unity 用于快速迭代的pacth功能,也是類似的原理。不過(guò)因?yàn)閕os平臺(tái)上不支持JIT而且還禁止dll熱更,所以不支持這種方法,所以如果只開(kāi)發(fā)安卓平臺(tái)的話,就可以用這種方法,簡(jiǎn)單直觀。不過(guò)現(xiàn)實(shí)是稍微正經(jīng)的項(xiàng)目都是要支持ios的,畢竟市場(chǎng)占有率擺在那。。所以接下來(lái)回到現(xiàn)實(shí)。
基于Lua的熱更
單純使用Lua開(kāi)發(fā)
Lua 是一種腳本語(yǔ)言,可以運(yùn)行再對(duì)應(yīng)平臺(tái)的虛擬機(jī)上。Lua 在虛擬機(jī)上是被 解釋-執(zhí)行,而不是像 JIT 一樣先編譯成對(duì)應(yīng)機(jī)器碼,所以不會(huì)受到IOS的限制。我們所需要做的就是在程序里嵌入一個(gè)Lua解釋器然后在運(yùn)行時(shí)讀取腳本并解釋執(zhí)行(當(dāng)然,還要再C#與Lua代碼之間做一些數(shù)據(jù)通信,以及在Lua代碼支持對(duì)C#的調(diào)用 )。比如像下面這樣的代碼
void通過(guò)覆蓋腳本即可實(shí)現(xiàn)邏輯的更新。lua方案相比起C#通過(guò) JIT 或者 AOT 得到的 native code 一般而言性能上相對(duì)弱勢(shì),更不用說(shuō)還有 IL2CPP這種東西。把性能敏感模塊弄成非 lua 代碼還是相當(dāng)?shù)赜斜匾摹K赃€是需要提前確定好哪部分代碼是需要熱更的,需要項(xiàng)目把頻繁迭代的業(yè)務(wù)模塊以及穩(wěn)定的基本功能模塊劃分開(kāi)來(lái),(不過(guò)大部分項(xiàng)目早期開(kāi)發(fā)基本所有地方都是要頻繁地迭代修復(fù)的。。。)。
C#轉(zhuǎn)Lua
Lua 這種弱類型語(yǔ)言開(kāi)發(fā)效率與維護(hù)體驗(yàn)對(duì)很多人來(lái)說(shuō)都是不如C#的,于是就出現(xiàn)了一些能夠?qū)#代碼轉(zhuǎn)換為L(zhǎng)ua的工具。比如這個(gè)。但是顯然lua不可能把所有特性都支持了,實(shí)際項(xiàng)目也不是所有代碼都需要熱更新,實(shí)際搞進(jìn)工作流還是有很多的麻煩的,不過(guò)幸好已經(jīng)有了很多比較成熟的方案,比如 xlua 。總的來(lái)說(shuō)這類方案的核心熱更原理還是基于Lua解釋型腳本語(yǔ)言的特點(diǎn)。
ILRuntime
Unity 是通過(guò)Mono來(lái)將 C# 編譯為 CIL,然后通過(guò)將 CIL 運(yùn)行不同平臺(tái)的CLR上來(lái)實(shí)現(xiàn)跨平臺(tái)。前面提到了IOS禁止動(dòng)態(tài)加載dll與JIT。但是并沒(méi)有禁止腳本解釋。ILRuntime即是實(shí)現(xiàn)了一個(gè)IL的運(yùn)行時(shí),或者說(shuō)解釋器,把dll中的 IL 指令像腳本一樣解釋執(zhí)行,而不是通過(guò)JIT或者AOT編譯為機(jī)器碼。這實(shí)在是一個(gè)思路清奇的東西,整出了C#編譯成IL運(yùn)行一個(gè)能解釋IL的解釋器并用他來(lái)解釋執(zhí)行別的IL這樣給人套娃感覺(jué)的東西,作者是真的強(qiáng)。
因?yàn)镮OS還是禁止dll更新,所以要把編譯完包含 IL 的 dll(還有pdb,如果希望有調(diào)試信息的話) 打包成另外的文件加載,然后在運(yùn)行時(shí)動(dòng)態(tài)加載、解析、解釋、執(zhí)行。
ILRuntime的好處是,開(kāi)發(fā)語(yǔ)言可以繼續(xù)使用C#(或者別的能編譯成IL的語(yǔ)言)進(jìn)行開(kāi)發(fā)。同時(shí)還能實(shí)現(xiàn)熱更。開(kāi)發(fā)效率比純 Lua 的高,支持的C#特性比C#轉(zhuǎn)Lua的方案要多。缺點(diǎn)是性能較差(僅限不支持JIT的平臺(tái),有JIT的話ILRuntime會(huì)跑得更快,性能能被拉平),主要是體現(xiàn)在一些計(jì)算密集的地方,相比起Lua會(huì)有劣勢(shì)。
然后使用時(shí)還需要注意跨域繼承(注意不要繼承 Mono Behavior,坑太多。。),如果腳本代碼也需要熱更的話,就對(duì)幾個(gè)事件函數(shù)做一下重定向(當(dāng)然,這里得用ILRuntime調(diào)用熱更代碼的接口,我見(jiàn)過(guò)居然用反射來(lái)重定向到熱更代碼的人。。)、傳遞閉包時(shí)需要寫(xiě)適配,還有用 CLR綁定和值綁定優(yōu)化性能熱點(diǎn),不過(guò)官方提供了一些自動(dòng)生成代碼的工具,結(jié)合項(xiàng)目情況改改還是問(wèn)題不大的,至少不會(huì)比寫(xiě)Lua惡心。 如果使用IL2Cpp的話,還要注意對(duì)泛型方法做CLR綁定以及類型裁剪的坑。更多細(xì)節(jié)可以看官方文檔。
代碼文件的熱更
上文中沒(méi)有提及到的一個(gè)很重要的點(diǎn)就是沒(méi)有提及代碼文件(Lua腳本,或者DLL)如何下載覆蓋更新,事實(shí)上這個(gè)問(wèn)題與代碼熱更新關(guān)系不大,可以把這些代碼文件當(dāng)成普通的資源從服務(wù)器上下載、更新、加載,當(dāng)然這個(gè)過(guò)程還涉及到一些版本比較之類的東西,本文就不詳細(xì)展開(kāi)了。
參考鏈接
flashyiyi:一些新潮的Unity熱更方案?zhuanlan.zhihu.comhttps://ourpalm.github.io/ILRuntime/public/v1/guide/index.html?ourpalm.github.io總結(jié)
以上是生活随笔為你收集整理的iOS代码质量要求_Unity移动端代码热更新技术学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java在控制台打印余弦曲线,java打
- 下一篇: ef mysql db first_Ne