(轉)Unity實現c#熱更新方案探究(一)

轉載請標明出處:http://www.cnblogs.com/zblade/

最近研究了一下如何在unity中實現c#的熱更新,對於整個DLL熱更新的過程和方案有一個初步的瞭解,這兒就寫下來,便於後續的深入調查和方案選擇。
一、C# DLL的動態加載和卸載
既然要熱更新,那麼就是動態的加載c#的DLL,所以第一步就是研究如何實現DLL的動態加載和卸載。
在CLR Via C#中,對於DLL的加載有詳細的講解,這兒就不再長篇幅的講解整個過程,簡單的來說,在C#的工程中,都會生成一個默認的程序域appDomain,就叫做DefaultAppDomain吧,在這個程序域的基礎上,我們可以加載多個不同的程序集。在.Net中,程序集不能卸載,但是可以隨着程序域的釋放而一起釋放,所以我們可以利用程序域來實現程序集(DLL)的加載和釋放。

上面的理論來自CLR Via C#, 具體的圖爲:

基於這個理論,我們可以在DefaultAppDomain之外,再多次創建多個AppDomain,基於AppDomain來實現DLL的加載和卸載。基於此,編寫相關的工程測試,參考網上的一個工程來進一步的測試,這兒是原文,文末有相關的代碼下載:
在原代碼的基礎上,進一步構建。首先,構建4個Class Library:

默認工程爲MainServer,將Module1和Module2的Build路徑設置到MainServer的bin中,這樣MainServer就可以加載最新的Module1.DLL/Module2.DLL(PS:這兒的設置很重要,忽略會使得不能加載最新的DLL)
Module1和Module2都在References中添加CommonLib的引用,實現ICalculater接口,各自的實現爲:
Module1:

Module2:

這樣,就是兩個不同的Class Library中,分別實現了ICalculater接口,分別爲相加和相乘。在MainServer的主程序入口Program中:

 

首先在默認appDomain的基礎上,進一步加載2個appDomain,然後分別在這2個程序域的基礎上加載DLL。得到的結果爲:

整個步驟都詳細的解釋了整個執行流程,先構建appDomain,在此基礎上,加載dll,然後執行裏面的方法。再一個新的appDomain中加載前面加載過的dll,再次執行,相互之間並不衝突。所以appDomain可以一對多個DLL,一個DLL可以被多個不同的AppDomain加載。

 

二、Unity中測試DLL的加載
在第一部分的基礎上,我們進一步的研究如何在Unity中實現Dll的加載,基本的操作步驟可以參考這篇文章:unity dll實現熱更新
當然,文章並不是完全的實現熱更新,實現的是windows和android平臺下,對於dll文件的熱更新。對於IOS爲什麼不能熱更新,我們後續會討論到,先看看安卓和windows下 dll的熱更新步驟。
1、新建一個ClassLibrary(類庫)的工程,在其中實現對應的類和方法;
2、將該工程導出爲DLL;
3、將DLL改爲bytes文件,存入Unity工程中的StreamingAssets文件夾下;
4、在工程運行的時候,讀取StreamingAssets下的Dll文件,用Assembly.Load(byte[] bytes )的方法,將DLL文件讀取出來,進而執行相關的操作。這一步的代碼爲:

 

對於DLL文件,是執行www.bytes,對於assetbundle文件,則是執行ab.mainAsset轉換爲TextAsset,進一步得到bytes。在windows和android平臺下,都會得到這樣的屏幕輸出:

這個方案的本質,和前面的本質相差不大,unity工程在執行的時候,會構建一個默認的appDomain,Assembly.Load,其實就是在這個程序域上加載Dll,所以相關的實質和前面一個部分相差不大,這就是c#熱更新在unity中的應用(IOS不包括)。

下文我們會講解IOS爲什麼不支持DLL的熱更新,以及如何利用ILRuntime來實現Android和IOS的熱更新。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章