国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Unity 熱更新方案之——ILRuntime

這篇具有很好參考價值的文章主要介紹了Unity 熱更新方案之——ILRuntime。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

做游戲離不開熱更新,目前市面上熱更新方案用的比較多的是Lua(XLua,ToLua),最近又出現(xiàn)了基于C#的熱更新 huatuo(已改名HybridCLR又叫wolong)。來不及學習了,以后用到了再去了解吧。
筆者入行做的第一個項目是利用ILRuntime進行熱更新的,當時也是用的稀里糊涂的,一些坑點都是項目主程去解決的。這里做一個簡單的回顧。


一、ILRuntime是什么?

1.官方簡介
ILRuntime項目為基于C#的平臺(例如Unity)提供了一個純C#實現(xiàn),快速、方便且可靠的IL運行時,使得能夠在不支持JIT的硬件環(huán)境(如iOS)能夠?qū)崿F(xiàn)代碼的熱更新。

2.實現(xiàn)原理
ILRuntime借助Mono.Cecil庫來讀取DLL的PE信息,以及當中類型的所有信息,最終得到方法的IL匯編碼,然后通過內(nèi)置的IL解譯執(zhí)行虛擬機來執(zhí)行DLL中的代碼來實現(xiàn)熱更新功能。
查看ILRuntime源碼你會發(fā)現(xiàn),內(nèi)部有一個很大的switch/case結(jié)構(gòu),就是針對基本上每一條IL指令碼進行解釋,同時維護一個Stackframe用于模擬cpu的函數(shù)調(diào)用的基本操作進行輔助解釋。
ILRuntime中解釋熱更dll中的自定義類實例,在框架層這邊都是對應(yīng)的同一個warper,即ILTypeInstance。
ILTypeInstance會知道最終被調(diào)用方法的il指令內(nèi)容,如果調(diào)用,則就是switch逐句去解析這個方法的IL代碼。
這樣一來就沒有什么執(zhí)行權(quán)限的問題,簡單理解為讀取一個普通文件,然后解析文件內(nèi)容。
如果是反射處理這種情形,那就是真實的構(gòu)建出一個新的類型,然后調(diào)用新類型的方法,這倒是會涉及到內(nèi)存權(quán)限問題。

二、ILRuntime使用

當時使用的時候只記得有以下限制:
1.不能手動掛載熱更Mono腳本,只能通過代碼AddComponent
2.不能使用非System.Action/Fun類型的委托,需要手動注冊委托類型轉(zhuǎn)換
3.需要將類的成員初始化賦值刪除,改為在方法內(nèi)初始化
4.不允許使用ref和out
5.將熱更腳本放在特定文件夾。通過定義宏,在日常開發(fā)中在Assembly-CSharp編譯調(diào)用,打包時將熱更腳本單獨打DLL。

當時每天都在趕UI,沒有去細究為什么這么做。
由于項目已經(jīng)掛掉了,這里就不去糾結(jié)了。下面記錄一下自己學習ILRuntime的歷程。

1.跨域委托

只在熱更新的DLL項目中使用的委托,是不需要任何額外操作的,就跟在通常的C#里那樣使用即可。
如果你需要將委托實例傳給ILRuntime外部使用,那則根據(jù)情況,你需要額外添加適配器或者轉(zhuǎn)換器。

示例:同一個參數(shù)組合的委托,只需要注冊一次即可

Action,以及Func委托需要在主工程注冊適配器
// 無返回值委托
appDomain.DelegateManager.RegisterMethodDelegate<int, float>();
// 帶返回值委托
appDomain.DelegateManager.RegisterFunctionDelegate<int, float, bool>();

自定義委托需要額外添加轉(zhuǎn)換器DelegateConvertor
// 自定義委托
delegate bool SomeFunction(int a, float b);
app.DelegateManager.RegisterDelegateConvertor<SomeFunction>((action) =>
{
    return new SomeFunction((a, b) =>
    {
       return ((Func<int, float, bool>)action)(a, b);
    });
});

官方建議:
盡量避免不必要的跨域委托調(diào)用。
盡量使用Action以及Func這兩個系統(tǒng)內(nèi)置萬用委托類型。

2.跨域繼承

如果你想在熱更DLL項目當中繼承一個Unity主工程里的類,或者實現(xiàn)一個主工程里的接口,你需要在Unity主工程中實現(xiàn)一個繼承適配器。
為什么需要適配器?
1)防止熱更層用到的框架層代碼被裁減。
為什么會被裁減呢?因為Unity打包的時候真的不把這個熱更dll看做dll,因為這個熱更dll是脫離unity框架層的。自然在unity打包的時候,為了包體大小會把認為沒有使用的代碼全部過濾掉。這種情況下ILRuntime解釋執(zhí)行的時候,去反射調(diào)用框架層代碼就會被視為錯誤,因為框架層不存在這些被調(diào)用的代碼。

因為脫離了關(guān)系,那么如何在框架層中驅(qū)動的時候,可以同步驅(qū)動到熱更層,這就成了一個問題。這就需要框架層引用熱更層的相關(guān)instance去驅(qū)動 ,那么如何引用?這就是適配器的作用。適配器工作在框架層,其顯式強調(diào)了需要引用驅(qū)動的類型實例,然后重寫相關(guān)函數(shù)體內(nèi)容,去實質(zhì)調(diào)用 熱更類型實例 的方法。具體參考MonoBehaviourAdapter即可理解。

ILRuntime提供了一個代碼生成工具來自動生成跨域繼承的適配器代碼。

示例:

    void OnHotFixLoaded()
    {
        Debug.Log("首先我們來創(chuàng)建熱更里的類實例");
        TestClassBase obj;
        Debug.Log("現(xiàn)在我們來注冊適配器, 該適配器由ILRuntime/Generate Cross Binding Adapter菜單命令自動生成");
        appdomain.RegisterCrossBindingAdaptor(new TestClassBaseAdapter());
        Debug.Log("現(xiàn)在再來嘗試創(chuàng)建一個實例");
        obj = appdomain.Instantiate<TestClassBase>("HotFix_Project.TestInheritance");
        Debug.Log("現(xiàn)在來調(diào)用成員方法");
        obj.TestAbstract(123);
        obj.TestVirtual("Hello");
        obj.Value = 233;
        Debug.LogFormat("obj.Value={0}", obj.Value);


        Debug.Log("現(xiàn)在換個方式創(chuàng)建實例");
        obj = appdomain.Invoke("HotFix_Project.TestInheritance", "NewObject", null, null) as TestClassBase;
        obj.TestAbstract(456);
        obj.TestVirtual("Foobar");
        obj.Value = 2333333;
        Debug.LogFormat("obj.Value={0}", obj.Value);
    }

3.CLR綁定與重定向

為什么需要綁定與重定向機制?
1)防止熱更層用到的框架層代碼被裁減。
2)加速熱更代碼的執(zhí)行。
加速熱更代碼執(zhí)行其實是ILRuntime解釋每條il指令的時候,都會去現(xiàn)有緩存中查找當前指令是否為重定向函數(shù),如果為重定向函數(shù),則直接調(diào)用,如果不是重定向函數(shù),則會反射調(diào)用。通過反射來調(diào)用接口調(diào)用效率會比直接調(diào)用低很多,反射傳遞函數(shù)參數(shù)時需要使用object[]數(shù)組,這樣不可避免的每次調(diào)用都會產(chǎn)生不少GC Alloc。眾所周知GC Alloc高意味著在Unity中執(zhí)行會存在較大的性能問題。

ILRuntime提供了一個代碼生成工具來自動生成CLR綁定代碼。

生成代碼示例:

namespace ILRuntime.Runtime.Generated
{
    unsafe class HelloWorld_Binding
    {
        public static void Register(ILRuntime.Runtime.Enviorment.AppDomain app)
        {
            BindingFlags flag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
            MethodBase method;
            Type[] args;
            Type type = typeof(global::HelloWorld);
            args = new Type[]{};
            method = type.GetMethod("TestHotfixInvokeMain", flag, null, args, null);
            app.RegisterCLRMethodRedirection(method, TestHotfixInvokeMain_0);

            args = new Type[]{};
            method = type.GetConstructor(flag, null, args, null);
            app.RegisterCLRMethodRedirection(method, Ctor_0);

        }

        static StackObject* TestHotfixInvokeMain_0(ILIntepreter __intp, StackObject* __esp, IList<object> __mStack, CLRMethod __method, bool isNewObj)
        {
            ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;
            StackObject* ptr_of_this_method;
            StackObject* __ret = ILIntepreter.Minus(__esp, 1);

            ptr_of_this_method = ILIntepreter.Minus(__esp, 1);
            global::HelloWorld instance_of_this_method = (global::HelloWorld)typeof(global::HelloWorld).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, __mStack), (CLR.Utils.Extensions.TypeFlags)0);
            __intp.Free(ptr_of_this_method);

            instance_of_this_method.TestHotfixInvokeMain();

            return __ret;
        }

        static StackObject* Ctor_0(ILIntepreter __intp, StackObject* __esp, IList<object> __mStack, CLRMethod __method, bool isNewObj)
        {
            ILRuntime.Runtime.Enviorment.AppDomain __domain = __intp.AppDomain;
            StackObject* __ret = ILIntepreter.Minus(__esp, 0);

            var result_of_this_method = new global::HelloWorld();

            return ILIntepreter.PushObject(__ret, __mStack, result_of_this_method);
        }

    }
}


先學到這,持續(xù)更新中。。。

參考鏈接:
github倉庫地址:https://github.com/Ourpalm/ILRuntime
中文文檔:https://ourpalm.github.io/ILRuntime/public/v1/guide/index.html
使用ILRuntime遇到的一些問題
王王王渣渣ILRuntime系列文章來源地址http://www.zghlxwxcb.cn/news/detail-404295.html

到了這里,關(guān)于Unity 熱更新方案之——ILRuntime的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • ILRuntime是如何與Unity互相調(diào)用的

    一、ILRuntime的基本介紹 ILRuntime是一個跨平臺CLR實現(xiàn),它可以在多個平臺上運行C#代碼,包括Android、iOS、Windows、Linux等等。ILRuntime的實現(xiàn)方式是將C#代碼編譯成IL代碼,然后在運行時通過JIT或AOT的方式將IL代碼轉(zhuǎn)換為機器代碼,從而實現(xiàn)跨平臺的效果。ILRuntime的主要功能包括熱更

    2024年02月16日
    瀏覽(20)
  • Unity游戲開發(fā)客戶端面經(jīng)——熱更新(初級)

    前言:記錄了總6w字的面經(jīng)知識點,文章中的知識點若想深入了解,可以點擊鏈接學習。由于文本太多,按類型分開。這一篇是 熱更新?常問問題總結(jié),有幫助的可以收藏。 1.1 為什么使用Lua作為熱更新語言,不用C# ????????熱更新本身對于資源熱更新是非常容易的,Unit

    2023年04月20日
    瀏覽(27)
  • Unity 熱更新方案和流程

    Unity 熱更新方案和流程

    在開發(fā)商業(yè)游戲時,熱更新是一個很重要的模塊,這里講的熱更新不是指僅僅修復Bug,而是進行游戲功能的更新。簡單來講,就是啟動游戲后,跑個條,下載資源和代碼,然后再進入游戲。本篇博客所寫的內(nèi)容并不是最優(yōu)的解,只是完成了熱更新這個事情而已,具體使用還需

    2024年02月09日
    瀏覽(19)
  • Unity聯(lián)網(wǎng)多人游戲技術(shù)方案調(diào)研

    Unity聯(lián)網(wǎng)多人游戲技術(shù)方案調(diào)研

    Listen Server (Host) 和 Relay轉(zhuǎn)發(fā)服務(wù)器游戲包同時包含客戶端和服務(wù)端邏輯,聯(lián)網(wǎng)時一個客戶端開主,稱為Host,其他客戶端連入。局域網(wǎng)和互聯(lián)網(wǎng)都支持?;ヂ?lián)網(wǎng)需要有一個匹配服務(wù)器幫助找到不同人建立的主機。如果不使用Relay服務(wù)器,那對于互聯(lián)網(wǎng)連接就要使用NAT穿透下的

    2023年04月09日
    瀏覽(40)
  • Unity3D 游戲服務(wù)器怎么實現(xiàn)熱更新詳解

    Unity3D是一款強大的游戲開發(fā)引擎,它不僅可以用于游戲客戶端的開發(fā),還可以用于游戲服務(wù)器的搭建。在游戲開發(fā)過程中,熱更新是一項非常重要的功能,它可以使游戲在不重新啟動的情況下,更新游戲內(nèi)容,修復bug,提高游戲體驗。本文將詳細介紹Unity3D游戲服務(wù)器如何實

    2024年01月16日
    瀏覽(22)
  • 優(yōu)化Unity日志系統(tǒng)的消耗及在ILRuntime模式下雙擊能跳轉(zhuǎn)到對應(yīng)的文件行號

    Unity的日志控制: 日志系統(tǒng)打開,但是只打印錯誤日志。這樣其他級別的日志就不會有打印消耗。 但是還是有字符串拼接的消耗。 Conditional屬性是一個C#特性,它允許你根據(jù)預處理器指令的定義來有條件地執(zhí)行方法。例如下面的代碼: 如果沒有OPEN_MAIN_LOG_LOGWARNING宏,編譯的時

    2024年02月11日
    瀏覽(18)
  • Unity 熱更新技術(shù) | (一) 熱更新的基本概念原理及主流熱更新方案介紹

    Unity 熱更新技術(shù) | (一) 熱更新的基本概念原理及主流熱更新方案介紹

    ?? 博客主頁:https://xiaoy.blog.csdn.net ?? 本文由 呆呆敲代碼的小Y 原創(chuàng),首發(fā)于 CSDN ?? ?? 學習專欄推薦:Unity系統(tǒng)學習專欄 ?? 游戲制作專欄推薦:游戲制作 ??Unity實戰(zhàn)100例專欄推薦:Unity 實戰(zhàn)100例 教程 ?? 歡迎點贊 ?? 收藏 ?留言 ?? 如有錯誤敬請指正! ?? 未來很長

    2024年02月01日
    瀏覽(21)
  • [游戲開發(fā)]Unity顏色矯正無障礙方案

    [游戲開發(fā)]Unity顏色矯正無障礙方案

    之前有在關(guān)注色盲視覺糾正問題,最近在調(diào)整游戲的時候就打算把這個用上。 色弱色盲,這其實算是一種誤稱吧,只是人類中的少數(shù)派,只不過看到的顏色和大部分人不一樣。下文用,視覺少數(shù)者,來稱呼吧。 本質(zhì)上是因為感知顏色的細胞發(fā)生突變,感知與大部分人有差異

    2024年02月15日
    瀏覽(24)
  • 【Unity 框架】QFramework v1.0 使用指南 工具篇:05. ResKit 資源管理&開發(fā)解決方案 | Unity 游戲框架 | Unity 游戲開發(fā) | Unity 獨立游戲

    【Unity 框架】QFramework v1.0 使用指南 工具篇:05. ResKit 資源管理&開發(fā)解決方案 | Unity 游戲框架 | Unity 游戲開發(fā) | Unity 獨立游戲

    Res Kit,是資源管理快速開發(fā)解決方案 特性如下: 可以使用一個 API 從 dataPath、Resources、StreammingAssetPath、PersistentDataPath、網(wǎng)絡(luò)等地方加載資源。 基于引用計數(shù),簡化資源加載和卸載。 擁抱游戲開發(fā)流程中的不同階段 開發(fā)階段不用打 AB 直接從 dataPath 加載。 測試階段支持只需打

    2024年02月01日
    瀏覽(58)
  • Photon Unity Networking 實時多人在線游戲開發(fā)解決方案

    作者:禪與計算機程序設(shè)計藝術(shù) 2019年,由英特爾、Facebook等公司聯(lián)合舉辦的GDC大會上宣布了Unity Technologies將推出一個新品牌——Unity Game Development Platform(UGDP)。這個平臺將包括對虛幻引擎4、Unreal Engine 4和原生Unity引擎的支持。在這個平臺基礎(chǔ)上,Unity Technologies推出了實時的多

    2024年02月09日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包