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

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

這篇具有很好參考價(jià)值的文章主要介紹了【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

HybridCLR的推廣已經(jīng)做得相當(dāng)好了,而且熱更領(lǐng)域突然殺出一匹黑馬,熱度很高,不再多做介紹,可以點(diǎn)擊進(jìn)入HybridCLR開源地址了解詳情。

在此之前用過tolua和xlua熱更框架, 因?yàn)镃#開發(fā)方式實(shí)在太爽,想支持熱更又不想使用弱類型語言,于是對ILRuntime和HybridCLR進(jìn)行了評估,了解后毫不猶豫選擇了HybridCLR方案,盡管它還比較新。選它的原因很簡單,它最接近于原生C#開發(fā)方式,雖然性能相比原生AOT還有一定差距,但是與其它熱更方案相比,絕對是熱更領(lǐng)域顛覆性的存在,尤其是近期解決了泛型元數(shù)據(jù)補(bǔ)充、橋接函數(shù)生成的痛點(diǎn),非常的好用!

感謝HybridCLR作者讓我趕上了一個(gè)好時(shí)代,遠(yuǎn)離lua屎山??

下面記錄一下Windows Unity2021.3.12f1環(huán)境下UGF + HybridCLR熱更接入過程。

GameFramework接入HybridCLR,維護(hù)五年以上的自用游戲框架,工作流完善,適合快速開發(fā),已無私共享:?GitHub - sunsvip/GF_HybridCLR

HybridCLR接入非常非常非常簡單! 而且把已完成的純C#開發(fā)游戲接入HybridCLR實(shí)現(xiàn)熱更也同樣簡單??偟脕碚f接入HybridCLR只需要以下步驟:
1,把代碼分離成非熱更程序集和熱更程序集;
2,把熱更程序集打成dll,作為資源以供下載更新.

3,下載更新熱更dll,加載熱更dll,調(diào)用HybridCLR函數(shù)為AOT補(bǔ)充泛型元數(shù)據(jù)。
4,通過反射進(jìn)入熱更邏輯,Over.

0. 環(huán)境準(zhǔn)備

① git環(huán)境,用于下載更新hybridclr

② C++編譯庫,在VisualStudio Install面板勾選C++開發(fā). 用于編譯il2cpp

[2022.11.1更新]: 最新正式版HybridCLR接入流程:

HybridCLR已經(jīng)正式發(fā)布了Unity Package Manager版本插件,進(jìn)一步規(guī)范化工作流。相比之前版本的接入方式有些改變,當(dāng)前最新版本0.9.0接入方式如下:

HybridCLR UPM版地址:https://github.com/focus-creative-games/hybridclr_unity.git

?①打開Package Manager通過 git URL添加插件,把https://github.com/focus-creative-games/hybridclr_unity.git粘貼進(jìn)去即可:

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?②點(diǎn)擊頂部菜單HybridCLR->Installer安裝HybridCLR

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?③點(diǎn)擊頂部菜單HybridCLR->Settings添加熱更程序集:

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?④配置熱更程序集:

首先要明白什么是熱更新程序集,HybridCLR會把熱更新程序集打成一個(gè)dll文件,在游戲運(yùn)行時(shí)注入這個(gè)熱更dll,然后就能執(zhí)行熱更dll中的邏輯了。

我們需要先把代碼分離開,分成兩個(gè)程序集,一個(gè)是內(nèi)置程序集(Builtin),一個(gè)是熱更程序集(Hotfix)。把內(nèi)置代碼和熱更代碼分別放到不同的文件夾,然后在內(nèi)置程序所在文件夾創(chuàng)建一個(gè)名為Builtin的Assembly Definition文件,在熱更程序文件夾創(chuàng)建一個(gè)名為Hotfix的Assembly Definition文件。注意,Hotfix程序集可以引用Builtin程序集,但是Builtin不能直接引用Hotfix程序集。

內(nèi)置程序集也就是邏輯比較靠前,無法熱更,必須打進(jìn)包體的代碼。內(nèi)置程序集邏輯主要包含下載更新資源(包括熱更dll資源)、調(diào)用System.Reflection.Assembly.Load(hotfixDll.bytes)載入熱更dll的二進(jìn)制數(shù)據(jù),然后通過反射調(diào)用Hotfix程序集中的函數(shù)進(jìn)入熱更新邏輯。

程序集拆分為內(nèi)置程序集(Builtin)和熱更程序集(Hotfix)后,將熱更新程序集拖入HybridCLR->Settings->Hot Update Assembly Definitions;

Hot Update Assemblies不需要配置,它默認(rèn)返回Hot Update Assembly Definitions中配置的程序集名字列表;

Output Link File是HybridCLR工具自動生成代碼裁剪配置文件link.xml;

Output AOT Generic Reference File是HybridCLR自動生成AOT泛型元數(shù)據(jù)補(bǔ)充;

?⑤AOT元數(shù)據(jù)補(bǔ)充:

由于編譯成熱更dll后會丟失值類型泛型的數(shù)據(jù)類型,所以需要把Hotfix中用到的值類型泛型數(shù)據(jù)提前補(bǔ)充到AOT里,在元數(shù)據(jù)共享機(jī)制下,Hotfix程序就能正確識別那些值類型泛型數(shù)據(jù)。

HybridCLR Settings里預(yù)留了Patch AOT Assemblies字段,用于配置AOT dll文件補(bǔ)充元數(shù)據(jù)。此字段HybridCLR沒有用到,只是預(yù)留給用戶使用的空白字段。

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

AOT 補(bǔ)充元數(shù)據(jù)需要用戶調(diào)用接口自行補(bǔ)充。補(bǔ)充AOT元數(shù)據(jù)沒有先后順序要求,因此可以寫一個(gè)小工具便于把AOT dll名字添加到Patch AOT Assemblies列表:

勾選AOT Dll點(diǎn)擊Save會自動添加到Patch AOT Assemblies列表,并將對應(yīng)dll文件移動到Resources/AotDlls下,然后運(yùn)行時(shí)通過Resources.LoadAll<TextAsset>("AotDlls")加載全部AOT DLL然后調(diào)用RuntimeApi.LoadMetadataForAOTAssembly進(jìn)行AOT元數(shù)據(jù)補(bǔ)充;

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?工具代碼:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
internal enum ConfigEditorMode
{
    StripLinkConfig,
    AotDllConfig
}
public class StripLinkConfigWindow : EditorWindow
{
    private class ItemData
    {
        public bool isOn;
        public string dllName;
        public ItemData(bool isOn, string dllName)
        {
            this.isOn = isOn;
            this.dllName = dllName;
        }
    }
    private Vector2 scrollPosition;
    private string[] selectedDllList;
    private List<ItemData> dataList;
    private GUIStyle normalStyle;
    private GUIStyle selectedStyle;

    ConfigEditorMode mode;
    private void OnEnable()
    {
        normalStyle = new GUIStyle();
        normalStyle.normal.textColor = Color.white;

        selectedStyle = new GUIStyle();
        selectedStyle.normal.textColor = Color.green;
        dataList = new List<ItemData>();
        RefreshListData();
    }
    internal void SetEditorMode(ConfigEditorMode mode)
    {
        this.mode = mode;
        RefreshListData();
    }
    private void OnGUI()
    {
        EditorGUILayout.BeginVertical();
        if (dataList.Count <= 0)
        {
            EditorGUILayout.HelpBox("未找到程序集,請先Build項(xiàng)目以生成程序集.", MessageType.Warning);
        }
        else
        {
            switch (mode)
            {
                case ConfigEditorMode.StripLinkConfig:
                    EditorGUILayout.HelpBox("勾選需要添加到Link.xml的程序集,然后點(diǎn)擊保存生效.", MessageType.Info);
                    break;
                case ConfigEditorMode.AotDllConfig:
                    EditorGUILayout.HelpBox("勾選需要添加到AOT元數(shù)據(jù)補(bǔ)充的dll,然后點(diǎn)擊保存生效.", MessageType.Info);
                    break;
            }
        }
        scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, false, true);
        for (int i = 0; i < dataList.Count; i++)
        {
            EditorGUILayout.BeginHorizontal();
            var item = dataList[i];
            item.isOn = EditorGUILayout.ToggleLeft(item.dllName, item.isOn, item.isOn ? selectedStyle : normalStyle);
            EditorGUILayout.EndHorizontal();
        }
        EditorGUILayout.EndScrollView();
        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Select All", GUILayout.Width(100)))
        {
            SelectAll(true);
        }
        if (GUILayout.Button("Cancel All", GUILayout.Width(100)))
        {
            SelectAll(false);
        }
        GUILayout.FlexibleSpace();

        if (GUILayout.Button("Reload", GUILayout.Width(120)))
        {
            RefreshListData();
        }
        if (GUILayout.Button("Save", GUILayout.Width(120)))
        {
            switch (mode)
            {
                case ConfigEditorMode.StripLinkConfig:
                    if (MyGameTools.Save2LinkFile(GetCurrentSelectedList()))
                    {
                        EditorUtility.DisplayDialog("Strip LinkConfig Editor", "Update link.xml success!", "OK");
                    }
                    break;
                case ConfigEditorMode.AotDllConfig:
                    if (MyGameTools.Save2AotDllList(GetCurrentSelectedList()))
                    {
                        EditorUtility.DisplayDialog("AOT dlls Editor", "Update AOT dll List success!", "OK");
                    }
                    break;
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.EndVertical();
    }
    private void SelectAll(bool isOn)
    {
        foreach (var item in dataList)
        {
            item.isOn = isOn;
        }
    }
    private string[] GetCurrentSelectedList()
    {
        List<string> result = new List<string>();
        foreach (var item in dataList)
        {
            if (item.isOn)
            {
                result.Add(item.dllName);
            }
        }
        return result.ToArray();
    }
    private void RefreshListData()
    {
        dataList.Clear();

        switch (mode)
        {
            case ConfigEditorMode.StripLinkConfig:
                selectedDllList = MyGameTools.GetSelectedAssemblyDlls();
                break;
            case ConfigEditorMode.AotDllConfig:
                selectedDllList = MyGameTools.GetSelectedAotDlls();
                break;
        }
        foreach (var item in MyGameTools.GetProjectAssemblyDlls())
        {
            dataList.Add(new ItemData(IsInSelectedList(item), item));
        }
    }
    private bool IsInSelectedList(string dllName)
    {
        return ArrayUtility.Contains(selectedDllList, dllName);
    }
}

?自定義一個(gè)菜單用于一鍵編譯dll并把熱更dll和AOT泛型補(bǔ)充dll復(fù)制到Assets指定目錄以便打包dll到AssetBundle做熱更:

/// <summary>
    /// 把熱更新dll拷貝到指定目錄
    /// </summary>
    /// <param name="target">平臺</param>
    /// <param name="desDir">拷貝到目標(biāo)目錄</param>
    /// <param name="copyAotMeta">是否同時(shí)拷貝AOT元數(shù)據(jù)補(bǔ)充dll</param>
    /// <returns></returns>
    public static string[] CopyHotfixDllTo(BuildTarget target, string desDir, bool copyAotMeta = true)
    {
        List<string> failList = new List<string>();
        string hotfixDllSrcDir = HybridCLR.Editor.SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);

        foreach (var dll in HybridCLR.Editor.SettingsUtil.PatchingHotUpdateAssemblyFiles)
        {
            string dllPath = UtilityBuiltin.ResPath.GetCombinePath(hotfixDllSrcDir, dll);
            if (File.Exists(dllPath))
            {
                string dllBytesPath = UtilityBuiltin.ResPath.GetCombinePath(desDir, Utility.Text.Format("{0}.bytes", dll));
                File.Copy(dllPath, dllBytesPath, true);
            }
            else
            {
                failList.Add(dllPath);
            }
        }

        var aotDlls = HybridCLRSettings.Instance.patchAOTAssemblies.Select(dll => dll + ".dll").ToArray();
        if (copyAotMeta)
        {
            var failNames = CopyAotDllsToProject(target);
            failList.AddRange(failNames);
        }
        var hotfixListFile = UtilityBuiltin.ResPath.GetCombinePath(Application.dataPath, ConstBuiltin.HOT_FIX_DLL_DIR, "HotfixFileList.txt");
        File.WriteAllText(hotfixListFile, UtilityBuiltin.Json.ToJson(HybridCLR.Editor.SettingsUtil.HotUpdateAssemblyFiles.ToArray()), System.Text.Encoding.UTF8);
        AssetDatabase.Refresh();
        return failList.ToArray();
    }
    public static string[] CopyAotDllsToProject(BuildTarget target)
    {
        List<string> failList = new List<string>();
        var aotDlls = HybridCLRSettings.Instance.patchAOTAssemblies.Select(dll => dll + ".dll").ToArray();
        string aotDllDir = HybridCLR.Editor.SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
        string aotSaveDir = UtilityBuiltin.ResPath.GetCombinePath(Application.dataPath, "Resources", ConstBuiltin.AOT_DLL_DIR);
        if (Directory.Exists(aotSaveDir))
        {
            Directory.Delete(aotSaveDir,true);
        }
        Directory.CreateDirectory(aotSaveDir);
        foreach (var dll in aotDlls)
        {
            string dllPath = UtilityBuiltin.ResPath.GetCombinePath(aotDllDir, dll);
            if (!File.Exists(dllPath))
            {
                Debug.LogWarning($"ab中添加AOT補(bǔ)充元數(shù)據(jù)dll:{dllPath} 時(shí)發(fā)生錯(cuò)誤,文件不存在。裁剪后的AOT dll在BuildPlayer時(shí)才能生成,因此需要你先構(gòu)建一次游戲App后再打包。");
                failList.Add(dllPath);
                continue;
            }
            string dllBytesPath = UtilityBuiltin.ResPath.GetCombinePath(aotSaveDir, Utility.Text.Format("{0}.bytes", dll));
            File.Copy(dllPath, dllBytesPath, true);
        }

        return failList.ToArray();
    }

⑥ 加載并補(bǔ)充AOT元數(shù)據(jù):

var aotMetaDlls = Resources.LoadAll<TextAsset>("AotDlls");
foreach (var dll in aotMetaDlls)
{
    var success = RuntimeApi.LoadMetadataForAOTAssembly(dll.bytes, HomologousImageMode.SuperSet) == LoadImageErrorCode.OK;
}

?什么情況下需要把dll添加到Patch AOT Assemblies進(jìn)行AOT元數(shù)據(jù)補(bǔ)充?

AOT元數(shù)據(jù)補(bǔ)充,顧名思義是為AOT補(bǔ)充元數(shù)據(jù),元數(shù)據(jù)補(bǔ)充dll一定是AOT dll而不是熱更dll。

例如,項(xiàng)目用到了LitJson插件,插件放到了非熱更部分(AOT),LitJson有很多方法用到了值類型泛型T,當(dāng)熱更dll中的邏輯調(diào)用了AOT里帶有值類型泛型的函數(shù)就會報(bào)錯(cuò),因此需要將LitJson.dll添加到補(bǔ)充Patch AOT Assemblies列表里,游戲啟動后先進(jìn)行AOT元數(shù)據(jù)補(bǔ)充,熱更dll再調(diào)用值類型泛型函數(shù)就不會報(bào)錯(cuò)了。

AOT元數(shù)據(jù)補(bǔ)充dll只需要出包時(shí)打進(jìn)包里就行,不要作為熱更資源。

GF接入HybridCLR:

1. 下載hybridclr_trial示例工程并導(dǎo)入U(xiǎn)GF框架

HybridCLR目前還不是以Unity插件的形式提供,需要下載hybridclr_trial示例工程提取提供的Dll生成工具和橋接函數(shù)生成工具, 以及HybridCLR Runtime接口。

2. 安裝配置HybridCLR環(huán)境

首先找到hybridclr_trial\HybridCLRData\init_local_il2cpp_data.bat, 以文本方式打開,并做如下配置。

@echo off

set IL2CPP_BRANCH=2021.3.1    //這里Unity2020.3.x填2020.3.33; Unity2021.3.x填2021.3.1
...
...
set IL2CPP_PATH=C:\Program Files\Unity\Hub\Editor\2021.3.1f1\Editor\Data\il2cpp  //填自己Unity安裝目錄下的il2cpp文件夾所在路徑

......

目前HybridCLR支持的Unity版本為Unity2020.3系列和2021.3系列,即Unity2020.3.x使用il2cpp 2020.3.33分支,Unity2021.3.x使用il2cpp 2021.3.1分支。然后把IL2CPP_PATH配置為自己Unity安裝目錄下il2cpp所在路徑。

對應(yīng)關(guān)系:

Unity 2020.x => 使用HybridCLR il2cpp 2020.3.33分支;IL2CPP_PATH配置為Unity2020.3.33安裝目錄下的il2cpp

Unity 2021.x => 使用HybridCLR il2cpp 2021.3.1分支;L2CPP_PATH配置為Unity2021.3.1安裝目錄下的il2cpp

建議:

HybridCLR魔改了Unity 2020.3.33和Unity 2021.3.1兩個(gè)版本的il2cpp,分別兼容Unity 2020.x和Unity 2021.x.?

建議il2cpp和HybridCLR魔改版il2cpp的Unity版本保持一致,即如果你是用Unity2020.x開發(fā),就把IL2CPP_PATH設(shè)置為Unity2020.3.33安裝目錄下的il2cpp,使用Unity2021.x開發(fā)就把IL2CPP_PATH設(shè)置為Unity2021.3.1安裝目錄下的il2cpp. il2cpp版本不一致否則很有可能遇到奇怪的bug.

為了方便可以把Unity2020.3.33和Unity2021.3.1的il2cpp文件夾提取出來放到項(xiàng)目里。

修改完成后右鍵以管理員方式運(yùn)行init_local_il2cpp_data.bat,win11下先右鍵打開Windows PowerShell終端,然后在終端中運(yùn)行。.bat會自動從git下載hybridclr和魔改后支持dll動態(tài)加載的il2cpp庫,并將IL2CPP_PATH配置的Unity原生il2cpp庫與魔改后的il2cpp文件合并。Unity使用魔改過的il2cpp編譯也就從底層支持了C#熱更新。

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?3. 程序集分離,劃分為Builtin.Runtime(內(nèi)置)程序集和Hotfix(熱更)程序集。

為什么要分離程序集?

正如你不能自己把自己舉起來,所以需要一個(gè)起到橋梁作用的內(nèi)置程序負(fù)責(zé)初始化一些比較靠前的邏輯,比如啟動游戲后需要先把熱更新邏輯Hotfix.dll從資源服務(wù)器下載下來,并加載程序集。加載完成后通過反射調(diào)用Hotfix.dll中的入口函數(shù)切換到熱更新邏輯。

程序集拆分為Builtin.Runtime和Hitfix,即內(nèi)置程序集和熱更新程序集兩個(gè)即可,把內(nèi)置程序和熱更新程序分離到不同的文件夾,在兩個(gè)文件夾下創(chuàng)建分別創(chuàng)建Assembly Definition. 然后將熱更新程序集引用內(nèi)置程序集。

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?4. 熱更邏輯入口HotfixEntry

由于Hotfix程序集是以熱更資源的形式存在,不會被編譯成.so進(jìn)入安裝包,所以Builtin程序集不能直接調(diào)用Hotfix程序集,否則編譯時(shí)會報(bào)錯(cuò)。這就需要一個(gè)HotfixEntry作為進(jìn)入熱更邏輯的入口,使用反射的方式進(jìn)入Hotfix程序集。

為了盡可能把邏輯放到熱更新以達(dá)到更大可控性,Builtin程序集只處理比較靠前的邏輯,比如更新資源和熱更dll,初始化熱更dll. 熱更dll初始化完成后就進(jìn)入熱更程序集把所有邏輯交由熱更新程序集完成。由于GF不支持動態(tài)追加Procedure,所以進(jìn)入熱更程序集流程時(shí)需要重新為熱更新Procedure創(chuàng)建有限狀態(tài)機(jī),并切換到熱更新流程。在Builtin程序集初始化完熱更dll后通過反射調(diào)用HotfixEntry.StartHotfixLogic()進(jìn)入熱更新邏輯。

        //加載熱更新Dll完成,進(jìn)入熱更邏輯
        if (loadedProgress >= totalProgress)
        {
            Log.Info("熱更dll加載完成, 開始進(jìn)入HotfixEntry");
            loadedProgress = -1;
#if !DISABLE_HYBRIDCLR
            var hotfixDll = GFBuiltin.Hotfix.GetHotfixClass("HotfixEntry");
            if (hotfixDll == null)
            {
                Log.Error("獲取熱更入口類HotfixEntry失敗!");
                return;
            }
            hotfixDll.GetMethod("StartHotfixLogic").Invoke(null, new object[] { true });
#else
            HotfixEntry.StartHotfixLogic(false);
#endif
using GameFramework;
using GameFramework.Fsm;
using GameFramework.Procedure;
using UnityGameFramework.Runtime;
/// <summary>
/// 熱更邏輯入口
/// </summary>
public class HotfixEntry
{
    public static void StartHotfixLogic(bool enableHotfix)
    {
        Log.Info("Hotfix Enable:{0}", enableHotfix);
        GFBuiltin.Fsm.DestroyFsm<IProcedureManager>();
        var fsmManager = GameFrameworkEntry.GetModule<IFsmManager>();
        var procManager = GameFrameworkEntry.GetModule<IProcedureManager>();
        //手動把熱更新程序集的流程添加進(jìn)來
        ProcedureBase[] procedures = new ProcedureBase[]
        {
            new PreloadProcedure(),
            new ChangeSceneProcedure(),
            new MenuProcedure(),
            new GameProcedure(),
            new GameOverProcedure()
        };
        procManager.Initialize(fsmManager, procedures);
        procManager.StartProcedure<PreloadProcedure>();//默認(rèn)啟動熱更新程序集的預(yù)加載流程
    }
}

5. 打包流程及注意事項(xiàng)

0.通過HybridCLR內(nèi)置工具生成橋接函數(shù)(MethodBridge)、生成dll(CompileDll):

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

1. HybridCLR必須要先Build工程,目的是Build時(shí)生成代碼裁剪后的dll以供HybridCLR進(jìn)行AOT元數(shù)據(jù)補(bǔ)充。

由于il2cpp編譯后泛型函數(shù)的原始函數(shù)體元數(shù)據(jù)會丟失,無法創(chuàng)建出AOT泛型函數(shù)的實(shí)例就會導(dǎo)致報(bào)錯(cuò)。AOT有泛型共享機(jī)制,利用這一特性,我們只需要在內(nèi)置程序集中實(shí)例化的類中添加泛型函數(shù)的調(diào)用,該泛型函數(shù)的元數(shù)據(jù)就會建立并共享。

HybridCLR已經(jīng)默認(rèn)在RefTypes.cs中補(bǔ)充了常用的泛型元數(shù)據(jù):

(最新版HybridCLR做了優(yōu)化,已經(jīng)沒了)

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

?泛型函數(shù)在開發(fā)中使用非常頻繁,自己寫的泛型值類型函數(shù)必須提前注冊到AOT以泛型共享, 如下示例,只需在會實(shí)例化的類中添加這些泛型函數(shù)調(diào)用,RefBuiltinAOT()和RefLitJson()無需有任何地方調(diào)用。泛型元數(shù)據(jù)問題也是目前HybridCLR最大的痛點(diǎn),HybridCLR官方RoadMap不久后就會出一個(gè)自動掃描添加泛型函數(shù)的工具以解決這一痛點(diǎn)。(官方已經(jīng)解決了這個(gè)痛點(diǎn))

HybridCLR還支持通過dll自動補(bǔ)充元數(shù)據(jù), 例如, 我項(xiàng)目里內(nèi)置了LitJson插件,可以通過HybridCLR.RuntimeApi.LoadMetadataForAOTAssembly() 從LitJson.dll自動補(bǔ)充AOT元數(shù)據(jù)

#region 提前把熱更新使用到的值類型泛型注冊到AOT,否則報(bào)錯(cuò)
    /// <summary>
    /// 注冊元數(shù)據(jù)到AOT
    /// </summary>
    void RefBuiltinAOT()
    {
        var param = RefParams.Acquire();
        param.GetValue<bool>(default, default);
        param.GetValue<int>(default, default);
        param.GetValue<float>(default, default);
        param.GetValue<double>(default, default);
        param.GetValue<Vector2>(default, default);
        param.GetValue<Vector3>(default, default);
        param.GetValue<Vector4>(default, default);
        param.GetValue<Vector2Int>(default, default);
        param.GetValue<Vector3Int>(default, default);
        param.GetValue<Quaternion>(default, default);
        param.GetValue<Rect>(default, default);
        param.GetValue<Bounds>(default, default);
        param.GetValue<Color>(default, default);
        param.GetValue<Color32>(default, default);


        param.TryGetValue<bool>(default, out bool _);
        param.TryGetValue<int>(default, out int _);
        param.TryGetValue<float>(default, out float _);
        param.TryGetValue<double>(default, out double _);
        param.TryGetValue<Vector2>(default, out Vector2 _);
        param.TryGetValue<Vector3>(default, out Vector3 _);
        param.TryGetValue<Vector4>(default, out Vector4 _);
        param.TryGetValue<Vector2Int>(default, out Vector2Int _);
        param.TryGetValue<Vector3Int>(default, out Vector3Int _);
        param.TryGetValue<Quaternion>(default, out Quaternion _);
        param.TryGetValue<Rect>(default, out Rect _);
        param.TryGetValue<Bounds>(default, out Bounds _);
        param.TryGetValue<Color>(default, out Color _);
        param.TryGetValue<Color32>(default, out Color32 _);
    }
    void RefLitJson()
    {
        LitJson.JsonMapper.RegisterExporter<Vector2>(default);
        LitJson.JsonMapper.RegisterExporter<Vector3>(default);
        LitJson.JsonMapper.RegisterExporter<Vector2Int>(default);
        LitJson.JsonMapper.RegisterExporter<Vector3Int>(default);
        LitJson.JsonMapper.RegisterExporter<Vector4>(default);
        LitJson.JsonMapper.RegisterExporter<Quaternion>(default);
        LitJson.JsonMapper.RegisterExporter<Color>(default);
        LitJson.JsonMapper.RegisterExporter<Color32>(default);
        LitJson.JsonMapper.RegisterExporter<Bounds>(default);
        LitJson.JsonMapper.RegisterExporter<Rect>(default);
    }
    #endregion

2. 橋接函數(shù)丟失

如果運(yùn)行時(shí)遇到報(bào)錯(cuò)ExecutionEngineException: GetManaged2NativeMethodPointer not support. signature:xxx(簽名),需要把手動補(bǔ)充到HybridCLR\Editor\HybridCLR\Generators\GeneratorConfig.cs中,這也是HybridCLR最大的痛點(diǎn)之一,好在官方剛剛完善了橋接函數(shù)的問題,后續(xù)還會完善橋接函數(shù)生成工具以徹底消除此問題。

/// <summary>
        /// 如果提示缺失橋接函數(shù),將提示缺失的簽名加入到下列列表是簡單的做法。
        /// 這里添加64位App缺失的橋接函數(shù)簽名
        /// </summary>
        /// <returns></returns>
        public static List<string> PrepareCustomMethodSignatures64()
        {
            return new List<string>
            {
                "vi8i8",
                "i4i8i8i4i4i8i8",
                "i8i8S12",
                "S12i8S12",
                "S12i8S12S12",
                "i16i8i16i16",
            };
        }

        /// <summary>
        /// 如果提示缺失橋接函數(shù),將提示缺失的簽名加入到下列列表是簡單的做法。
        /// 這里添加32位App缺失的橋接函數(shù)簽名
        /// </summary>
        /// <returns></returns>
        public static List<string> PrepareCustomMethodSignatures32()
        {
            return new List<string>
            {
                "vi4i4",
                "S12i4S12S12",
            };
        }

3. 把Build后生成的Strip(裁剪)過的dll打包成AssetBundle

Build后HybridCLR會將Strip后的dll復(fù)制到項(xiàng)目根目錄的HybridCLRData\AssembliesPostIl2CppStrip下。

可以寫個(gè)工具監(jiān)聽Build進(jìn)程,Build完成后自動把Strip后的dll復(fù)制到Assets指定目錄,并修改為Unity支持的資源擴(kuò)展名以供打包AB:

#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using HybridCLR;
using System.IO;
using GameFramework;

public class BuildAppListener : IPostprocessBuildWithReport, IPreprocessBuildWithReport, IPostBuildPlayerScriptDLLs
{
    public int callbackOrder => 100;

    public void OnPostBuildPlayerScriptDLLs(BuildReport report)
    {
        //Debug.LogFormat("OnPostBuildPlayerScriptDLLs:{0}", report.name);

    }

    public void OnPostprocessBuild(BuildReport report)
    {
        Debug.Log("OnPostprocessBuild:");
        BuildTarget target = report.summary.platform;
        //CompileDllHelper.CompileDll(target);
        var hotfixDllDir = UtilityExt.Path.GetCombinePath(Application.dataPath, ConstBuiltin.HOT_FIX_DLL_DIR);
        try
        {
            if (!Directory.Exists(hotfixDllDir))
            {
                Directory.CreateDirectory(hotfixDllDir);
            }
            else
            {
                var dllFils = Directory.GetFiles(hotfixDllDir);
                for (int i = dllFils.Length - 1; i >= 0; i--)
                {
                    File.Delete(dllFils[i]);
                }
            }
            CopyHotfixDllTo(target, hotfixDllDir);
        }
        catch (System.Exception e)
        {
            Debug.LogErrorFormat("生成熱更新dll文件失敗:{0}", e.Message);
            throw;
        }

    }

    public void OnPreprocessBuild(BuildReport report)
    {

        Debug.Log("OnPreprocessBuild:");
    }
    public static void CopyHotfixDllTo(BuildTarget target, string desDir, bool copyAotMeta = true)
    {
        string hotfixDllSrcDir = BuildConfig.GetHotFixDllsOutputDirByTarget(target);
        foreach (var dll in BuildConfig.AllHotUpdateDllNames)
        {
            string dllPath = UtilityExt.Path.GetCombinePath(hotfixDllSrcDir, dll);
            if (File.Exists(dllPath))
            {
                string dllBytesPath = UtilityExt.Path.GetCombinePath(desDir, Utility.Text.Format("{0}.bytes", dll));
                File.Copy(dllPath, dllBytesPath, true);
            }
        }
        if (copyAotMeta)
        {
            string aotDllDir = BuildConfig.GetAssembliesPostIl2CppStripDir(target);
            foreach (var dll in BuildConfig.AOTMetaDlls)
            {
                string dllPath = UtilityExt.Path.GetCombinePath(aotDllDir, dll);
                if (!File.Exists(dllPath))
                {
                    Debug.LogError($"ab中添加AOT補(bǔ)充元數(shù)據(jù)dll:{dllPath} 時(shí)發(fā)生錯(cuò)誤,文件不存在。裁剪后的AOT dll在BuildPlayer時(shí)才能生成,因此需要你先構(gòu)建一次游戲App后再打包。");
                    continue;
                }
                string dllBytesPath = UtilityExt.Path.GetCombinePath(desDir, Utility.Text.Format("{0}.bytes", dll));
                File.Copy(dllPath, dllBytesPath, true);
            }
        }
        AssetDatabase.Refresh();
    }
}
#endif

3. 把熱更dll添加到GF的AB打包工具并打包AB

4. Build項(xiàng)目并測試。

GF_HybridCLR

https://github.com/sunsvip/GF_HybridCLR

GF_HybridCLR是已經(jīng)集成好的GameFramework + HybridCLR開發(fā)框架,有著一整套完善的工作流。包含對GameFramework的擴(kuò)展,數(shù)據(jù)表生成工具、代碼生成工具、熱更新工作流,AssetBundle加密解密。并且針對HybridCLR增加了傻瓜式的安裝、更新工具,支持一鍵開關(guān)HybridCLR熱更新。

使用方法:

1. 首先要確保安裝了git環(huán)境: Git下載

2. 下載GF_HybridCLR工程,點(diǎn)擊Unity菜單欄HybridCLR->Setup 自動配置HybridCLR環(huán)境;

3. 點(diǎn)擊HybridCLR->Update一鍵更新HybridCLR到最新版本

?2022.8.21更新:

官方也新增了一鍵安裝HybridCLR功能,我直接移植過來了。另外為了使用方便,提取了Unity 2021.3.1版本的il2cpp放在項(xiàng)目里,增加了一鍵從il2cpp壓縮文件安裝HybridCLR的功能。

使用方法如圖:

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架

工具默認(rèn)會根據(jù)當(dāng)前Unity版本去查找匹配的HybridCLR il2cpp版本(2020.3.3或2021.3.1),如果你沒有安裝這兩個(gè)版本就會使用當(dāng)前Unity安裝目錄下的il2cpp, 但是il2cpp版本不匹配很有可能出現(xiàn)兼容問題。

所以我以壓縮包的形式內(nèi)置了Unity 2021.3.1版本的il2cpp,點(diǎn)擊Use Buitin il2cpp程序會自動解壓并使用,然后點(diǎn)擊install安裝即可。(注,如果用的是Unity 2020.x,需要自行提取Unity 2020.3.33版本的il2cpp,壓縮為il2cpp_Unity2020_3_33.zip放到項(xiàng)目的HybridCLRData目錄下)

手機(jī)端熱更實(shí)測:

【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架文章來源地址http://www.zghlxwxcb.cn/news/detail-410809.html

到了這里,關(guān)于【UGF】GameFramework接入HybridCLR(wolong)臥龍C#熱更框架的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • Unity劃時(shí)代熱更方案 YooAsset+HybridCLR(wolong)(原h(huán)uatuo)(四)

    Unity劃時(shí)代熱更方案 YooAsset+HybridCLR(wolong)(原h(huán)uatuo)(四)

    上一篇簡介了YooAsset的安裝,本篇我們來詳細(xì)了解一下Asset的功能和使用。 之前的安裝的示例項(xiàng)目 Space Shooter 在 Assets/Samples/Space Shooter 下。 通過右鍵創(chuàng)建配置文件(Project窗體內(nèi)右鍵 - Create - YooAsset - Create YooAsset Setting) 注意:請將配置文件放在Resources文件夾下 配置說明:Ma

    2024年02月05日
    瀏覽(26)
  • Unity劃時(shí)代熱更方案 YooAsset+HybridCLR(wolong)(原h(huán)uatuo)(二)

    Unity劃時(shí)代熱更方案 YooAsset+HybridCLR(wolong)(原h(huán)uatuo)(二)

    在上一篇中對unity各大熱門的熱更方案進(jìn)行了對比,HybridCLR完勝。本篇來說一說HybridCLR在unity中的安裝和使用。 注意: 安裝 2020.3.26+、 2021.3.0+、2022.3.0+ 中任一版本。如果你不是經(jīng)驗(yàn)豐富的Unity開發(fā)者,推薦使用2021.3.1版本。 根據(jù)你所用的操作系統(tǒng),安裝過程中選擇模塊時(shí),必

    2024年02月06日
    瀏覽(16)
  • Unity劃時(shí)代熱更方案 YooAsset+HybridCLR(wolong)(原h(huán)uatuo)(六)完結(jié)篇

    Unity劃時(shí)代熱更方案 YooAsset+HybridCLR(wolong)(原h(huán)uatuo)(六)完結(jié)篇

    開始重頭戲了,我們都知道wolong是用來熱更代碼部分,YooAsset是熱更資源部分,所以二者結(jié)合起來可以就是熱更完美的解決方案。 下載wolong示例項(xiàng)目 用 git clone或者直接下載。 用unity打開此項(xiàng)目,發(fā)現(xiàn)這個(gè)項(xiàng)目菜單欄已經(jīng)有HybridCLR選項(xiàng)了,點(diǎn)擊該選項(xiàng)下方的installer…,安裝。

    2024年02月06日
    瀏覽(20)
  • HybridCLR(代號wolong)/huatuo新一代熱更新方案

    HybridCLR(代號wolong)/huatuo新一代熱更新方案

    ? huatuo 現(xiàn)已改名 HybridCLR, 而原來的huatuo倉庫由途游接著維護(hù) 本文章主要以HybridCLR倉庫為例說明:focus creative games(代碼哲學(xué)) · GitHub ?hybridclr? 倉庫為核心倉庫 ?il2cpp_plus?倉庫為改造過的il2cpp倉庫添加解釋核心倉庫的代碼指令 ?hybridclr_trial?倉庫為示例倉庫 在此之前,我們先了解

    2024年02月03日
    瀏覽(22)
  • HyBridCLR(華佗熱更)踩坑記錄

    ? ? ? ? 官方說明:HybridCLR擴(kuò)充了il2cpp的代碼,使它由純AOT runtime變成‘AOT+Interpreter’ 混合runtime,進(jìn)而原生支持動態(tài)加載assembly,使得基于il2cpp backend打包的游戲不僅能在Android平臺,也能在IOS、Consoles等限制了JIT的平臺上高效地以 AOT+interpreter 混合模式執(zhí)行,從底層徹底支持了

    2024年01月25日
    瀏覽(108)
  • 【Unity實(shí)戰(zhàn)】HybridCLR熱更快速集成

    【Unity實(shí)戰(zhàn)】HybridCLR熱更快速集成

    本文假設(shè)你已經(jīng)通過UPM導(dǎo)入了HybridCLR、Addressables、il2cpp支持并具有一定的C#基礎(chǔ)和Unity編輯器操作能力。 由于本文主打快速集成,故將Assembly-CSharp劃入到熱更新DLL。 理論上成熟的項(xiàng)目應(yīng)該用Assembly Definition進(jìn)行精細(xì)劃分以便于管理和縮短編譯時(shí)間。但是若掌握不好,劃分不明白

    2024年02月03日
    瀏覽(28)
  • Unity熱更模塊基于 HybridCLR + Addressable

    Unity熱更模塊基于 HybridCLR + Addressable

    代碼地址: GitHub - ManoKing/FFramework: 基于HybridCLR + Addressable的熱更新框架,提供例子基于QFramework+URP開發(fā) 基于HybridCLR + Addressable的熱更新框架,提供例子基于QFramework+URP開發(fā) - GitHub - ManoKing/FFramework: 基于HybridCLR + Addressable的熱更新框架,提供例子基于QFramework+URP開發(fā) https://github.

    2023年04月14日
    瀏覽(22)
  • Unity + HybridCLR,近乎完美的新熱更方案,從零開始(一)——Hello World

    Unity + HybridCLR,近乎完美的新熱更方案,從零開始(一)——Hello World

    最近又新接觸了一種unity熱更的解決方案——HybridCLR,自稱是: 特性完整、零成本、高性能、低內(nèi)存的近乎完美的Unity全平臺原生c#熱更方案 。 接下來我們就來一起學(xué)習(xí)下。 下面是官方文檔的鏈接,一切以官方為主:HybridCLR HybridCLR擴(kuò)充了il2cpp的代碼,使它由純AOT runtime變成

    2024年02月07日
    瀏覽(18)
  • # 熱更新方案 HybridCLR 學(xué)習(xí)教程 |(二)官方示例項(xiàng)目搭建 及 新增熱更代碼示例
  • Unity 之 Addressable可尋址系統(tǒng) -- HybridCLR(華佗)+Addressable實(shí)現(xiàn)資源腳本全熱更 -- 實(shí)戰(zhàn)(二)

    Unity 之 Addressable可尋址系統(tǒng) -- HybridCLR(華佗)+Addressable實(shí)現(xiàn)資源腳本全熱更 -- 實(shí)戰(zhàn)(二)

    在Unity中,結(jié)合 Addressable Asset System (簡稱:AA)和 HybridCLR 來實(shí)現(xiàn)熱更新資源和腳本的控制。 AA 是Unity的一個(gè)強(qiáng)大的資源管理系統(tǒng),可以用于動態(tài)加載和更新資源。HybridCLR是一個(gè)用于在Unity中運(yùn)行C#腳本的工具,可以實(shí)現(xiàn)熱更新腳本的功能。 使用版本: Unity 2022.3.8 Addressables 1.21

    2024年01月24日
    瀏覽(54)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包