對C#熱更新方案ILRuntime的探究


轉載請標明出處:http://www.cnblogs.com/zblade/
對於游戲中的熱更,目前主流的解決方案,分為Lua(ulua/slua/xlua/tolua)系和ILRuntime代表的c#系。今天就來探究一下ILRuntime是如何實現熱更的流程的,新手入門,個中有錯誤理解,歡迎指正。
ILRuntime的原理
首先說一下lua的熱更新基本過程,unity提供了AssetBundle的資源打包方式,這樣可以通過資源的對比來更新最新的資源。而lua文件不需要編譯,可以被打包進游戲的資源中,在游戲啟動的過程中加載對應的腳本資源,今兒解釋執行轉換為字節碼,在lua的虛擬機中執行,這種天然的設計,可以規避靜態語言需要編譯的環節。
C#代碼在編寫后,是需要執行編譯的,才能起效,這樣如果在手機端,沒有對應的編譯環境,那么對應的c#代碼就無法實現熱更。ILRuntime實現的基礎,也是基於AssetBundle的資源熱更新方式,將需要熱更新的c#代碼打包成DLL,放在工程的StreamingAssets下,在每次完成資源打包后,對應的DLL會被作為資源熱更新出去。這樣就規避了編譯相關的環節,實現了熱更。
文字講述較為枯燥,看看示例代碼是如何執行這個流程的:
1、ILRuntime的相關資料鏈接
可以在github上查找: ILRuntime
對應的unity3d的工程的例子:ILRuntime U3D例子
 
2、探究ILRuntime的例子
整個例子分為兩個部分:
分別是熱更新的工程和U3D主工程,那么先看看U3D工程:
較為重要的是兩個部分,一個是ILRuntime需要用到的幾個環境,重點是Mono.Ceil.20, Mono.Ceil.Pdb,ILRuntime三個文件夾,ILRuntime后續的版本將LitJson也加入進來了。
另一個關鍵點就是講HotFix_Project.dll作為資源加入到StreamingAssets文件夾下,這樣就可以被ab打包作為資源熱更新出去。
接下來我們打開HotFix_Project:
 
得到的工程為:
 

重點分析一下引用,可以看到,該工程是引用了UnityEngine/UnityEngine.UI/Assembly-CSharp等幾個U3D游戲主工程中的dll的,這樣,可以在工程中直接調用對應的u3d相關的dll下的類和方法,示例代碼:

 

只要using UnityEngine申明后,下面的代碼就可以繼承MonoBehaviour類,自然可以調用其中的相關類和方法。那么到這一步,就可以理解,在HotFix_Project中,我們是可以調用U3D游戲主工程的類和方法的,只要添加其相關的dll到工程的引用中。這樣我們就完成了HotFix對U3D游戲主工程的調用的一條線路。

3、U3D游戲主工程調用HotFix_Project中的類型和相關方法
現在的調用都是交互式的,在完成了hotfix對u3d的調用后,我們接下來看看u3d是如何調用hotfix中的類和方法的。
取我們最常見和關注的反射作為一個示例,這樣可以了解整個調用過程。
首先,需要加載hotfix的dll,來看看相關的代碼:
 
整個豎屏截出來的圖比較大,跟隨箭頭來看看流程:
1) 首先MonoBehaviour下的Start執行一個協程;
2) 實例化唯一的appdomain;
3) 加載hotfix的dll和pdb,可以看到,如果我們熱更新相關的dll和pdb,是需要在這一步之前執行的,其實可以放在Awake中執行,當然這兒沒有熱更,我們就直接執行dll和pdb的加載;
4) 在完成dll和pdb的加載后,執行assembly的加載,這樣我們可以獲取到hotfix中的相關類和方法,屬性等相關信息,相關可以查看源碼即可了解。
5) 測試如何調用反射:
        Debug.Log("熱更DLL中的類型我們均需要通過AppDomain取得"); var it = appdomain.LoadedTypes["HotFix_Project.InstanceClass"]; Debug.Log("LoadedTypes返回的是IType類型,但是我們需要獲得對應的System.Type才能繼續使用反射接口"); var type = it.ReflectionType; Debug.Log("取得Type之后就可以按照我們熟悉的方式來反射調用了"); var ctor = type.GetConstructor(new System.Type[0]); var obj = ctor.Invoke(null); Debug.Log("打印一下結果"); Debug.Log(obj); Debug.Log("我們試一下用反射給字段賦值"); var fi = type.GetField("id", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); fi.SetValue(obj, 111111); Debug.Log("我們用反射調用屬性檢查剛剛的賦值"); var pi = type.GetProperty("ID"); Debug.Log("ID = " + pi.GetValue(obj, null));
讓我們看看整個流程:
基於appdomain來獲取類,然后獲取type,對應的invoke, 也可以利用反射來修改對應的field的值。
 
總結:到這兒,我們就基本理清楚了基於ILRuntime如何實現hotfix和u3d主工程之間的相互調用,可以講這樣一套熱更新方式嵌套到游戲的框架中,實現不用lua來實現熱更。當然ILRuntime要轉換到IL2CPP,還是有很多地方需要注意的,詳情可以參考github上的相關手冊。
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM