Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇

这篇具有很好参考价值的文章主要介绍了Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

开始重头戏了,我们都知道wolong是用来热更代码部分,YooAsset是热更资源部分,所以二者结合起来可以就是热更完美的解决方案。

搭建项目

下载wolong示例项目
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
git clone或者直接下载。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
用unity打开此项目,发现这个项目菜单栏已经有HybridCLR选项了,点击该选项下方的installer…,安装。
然后我们再用上节课讲的方式将YooAsset加入到这个项目中。同时下载shoot示例项目。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
将一些我们常用资源文件夹建好并添加在AssetBundle Collector
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎

Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎

注意:热更新代码资源部分这里要设置成PackRawFile,我想大家应该都知道为什么,我就不在这里过多重复了。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎

代码修改

Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
找到场景里的LoadDll游戏物体,打开LoadDll脚本修改里面的内容。因为版本原因Host Play Mode、Web Play Mode部位代码和官网的有所差别,官网的可能是旧版的用了会报错,其他模式的大家自行修改大同小异。实在不会就看FsmInitialize脚本,在其中复制符合自己版本的代码。

using HybridCLR;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using YooAsset;

/// <summary>
/// 脚本工作流程:
/// 1.下载资源,用yooAsset资源框架进行下载
///    1.资源文件,ab包
///    2.热更新dll
///    3.AOT泛型补充元数据
/// 2.给AOT DLL补充元素据,通过RuntimeApi.LoadMetadataForAOTAssembly
/// 通过实例化prefab,运行热更代码
/// </summary>

public class LoadDll : MonoBehaviour
{
    /// <summary>
    /// 资源系统运行模式
    /// </summary>
    public EPlayMode PlayMode = EPlayMode.EditorSimulateMode;

    void Start()
    {
        //StartCoroutine(DownLoadAssets(this.StartGame));
        StartCoroutine(DownLoadAssetsByYooAssets(this.StartGame));
    }

    #region download assets

    private static Dictionary<string, byte[]> s_assetDatas = new Dictionary<string, byte[]>();

    public static byte[] ReadBytesFromStreamingAssets(string dllName)
    {
        return s_assetDatas[dllName];
    }

    private string GetWebRequestPath(string asset)
    {
        var path = $"{Application.streamingAssetsPath}/{asset}";
        if (!path.Contains("://"))
        {
            path = "file://" + path;
        }
        return path;
    }

    //补充元数据dll的列表
    //通过RuntimeApi.LoadMetadataForAOTAssembly()函数来补充AOT泛型的原始元数据
    private static List<string> AOTMetaAssemblyFiles { get; } = new List<string>()
    {
        "mscorlib.dll",
        "System.dll",
        "System.Core.dll",
    };

    IEnumerator DownLoadAssetsByYooAssets(Action onDownloadComplete)
    {
        // 1.初始化资源系统
        YooAssets.Initialize();

        string packageName = "DefaultPackage";
        var package = YooAssets.TryGetPackage(packageName);
        if (package == null)
        {
            package = YooAssets.CreatePackage(packageName);
            YooAssets.SetDefaultPackage(package);
        }
        if (PlayMode == EPlayMode.EditorSimulateMode)
        {
            //编辑器模拟模式
            var initParameters = new EditorSimulateModeParameters();
            initParameters.SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild("DefaultPackage");
            yield return package.InitializeAsync(initParameters);
        }
        else if (PlayMode == EPlayMode.HostPlayMode)
        {
            //联机运行模式
            string defaultHostServer = GetHostServerURL();
            string fallbackHostServer = GetHostServerURL();
            var initParameters = new HostPlayModeParameters();
            initParameters.BuildinQueryServices = new GameQueryServices(); //太空战机DEMO的脚本类,详细见StreamingAssetsHelper
            initParameters.DecryptionServices = new GameDecryptionServices();//这里的代码和官网上的代码有差别,官网的代码可能是旧版本的代码会报错已这里的代码为主
            initParameters.DeliveryQueryServices = new DefaultDeliveryQueryServices();
            initParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = package.InitializeAsync(initParameters);
            /*
             			var createParameters = new HostPlayModeParameters();
			createParameters.DecryptionServices = new GameDecryptionServices();
			createParameters.BuildinQueryServices = new GameQueryServices();
			createParameters.DeliveryQueryServices = new DefaultDeliveryQueryServices();
			createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
			initializationOperation = package.InitializeAsync(createParameters);
             */
            yield return initOperation;

            if (initOperation.Status == EOperationStatus.Succeed)
            {
                Debug.Log("资源包初始化成功!");
            }
            else
            {
                Debug.LogError($"资源包初始化失败:{initOperation.Error}");
            }
            //string defaultHostServer = GetHostServerURL();
            //string fallbackHostServer = GetHostServerURL();
            //var createParameters = new HostPlayModeParameters();
            //createParameters.DecryptionServices = new GameDecryptionServices();
            //createParameters.QueryServices = new GameQueryServices();
            //createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            //initializationOperation = package.InitializeAsync(createParameters);
        }
        else if (PlayMode == EPlayMode.OfflinePlayMode)
        {
            //单机模式
            var initParameters = new OfflinePlayModeParameters();
            yield return package.InitializeAsync(initParameters);
            //var createParameters = new OfflinePlayModeParameters();
            //createParameters.DecryptionServices = new GameDecryptionServices();
            //initializationOperation = package.InitializeAsync(createParameters);
        }
        else
        {
            WebGL运行模式
            string defaultHostServer = "http://127.0.0.1/CDN/WebGL/v1.0";
            string fallbackHostServer = "http://127.0.0.1/CDN/WebGL/v1.0";
            var initParameters = new WebPlayModeParameters();
            initParameters.BuildinQueryServices = new GameQueryServices(); //太空战机DEMO的脚本类,详细见StreamingAssetsHelper
            initParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            var initOperation = package.InitializeAsync(initParameters);
            yield return initOperation;

            if (initOperation.Status == EOperationStatus.Succeed)
            {
                Debug.Log("资源包初始化成功!");
            }
            else
            {
                Debug.LogError($"资源包初始化失败:{initOperation.Error}");
            }
            //string defaultHostServer = GetHostServerURL();
            //string fallbackHostServer = GetHostServerURL();
            //var createParameters = new WebPlayModeParameters();
            //createParameters.DecryptionServices = new GameDecryptionServices();
            //createParameters.QueryServices = new GameQueryServices();
            //createParameters.RemoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);
            //initializationOperation = package.InitializeAsync(createParameters);
        }
        //2.获取资源版本
        var operation = package.UpdatePackageVersionAsync();
        yield return operation;

        if (operation.Status != EOperationStatus.Succeed)
        {
            //更新失败
            Debug.LogError(operation.Error);
            yield break;
        }
        string packageVersion = operation.PackageVersion;
        Debug.Log($"Updated package Version : {packageVersion}");

        //3.更新补丁清单
        // 更新成功后自动保存版本号,作为下次初始化的版本。
        // 也可以通过operation.SavePackageVersion()方法保存。
        bool savePackageVersion = true;
        var operation2 = package.UpdatePackageManifestAsync(packageVersion, savePackageVersion);
        yield return operation2;

        if (operation2.Status != EOperationStatus.Succeed)
        {
            //更新失败
            Debug.LogError(operation2.Error);
            yield break;
        }

        //4.下载补丁包
        yield return Download();
        //判断是否下载成功
        var assets = new List<string>
        {
            "HotUpdate.dll"
        }.Concat(AOTMetaAssemblyFiles);
        foreach (var asset in assets)
        {
            //加载原生文件
            RawFileOperationHandle handle = package.LoadRawFileAsync(asset);
            yield return handle;
            byte[] fileData = handle.GetRawFileData();
            //string fileText = handle4.GetRawFileText();
            //string filePath = handle4.GetRawFilePath();
            s_assetDatas[asset] = fileData;
            Debug.Log($"dll:{asset} size:{fileData.Length}");
        }
        onDownloadComplete();
    }

    IEnumerator DownLoadAssets(Action onDownloadComplete)
    {
        var assets = new List<string>
        {
            "prefabs",
            "HotUpdate.dll.bytes",
        }.Concat(AOTMetaAssemblyFiles);

        foreach (var asset in assets)
        {
            string dllPath = GetWebRequestPath(asset);
            Debug.Log($"start download asset:{dllPath}");
            UnityWebRequest www = UnityWebRequest.Get(dllPath);
            yield return www.SendWebRequest();

#if UNITY_2020_1_OR_NEWER
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.Log(www.error);
            }
#else
            if (www.isHttpError || www.isNetworkError)
            {
                Debug.Log(www.error);
            }
#endif
            else
            {
                // Or retrieve results as binary data
                byte[] assetData = www.downloadHandler.data;
                Debug.Log($"dll:{asset}  size:{assetData.Length}");
                s_assetDatas[asset] = assetData;
            }
        }

        onDownloadComplete();
    }

    IEnumerator Download()
    {
        int downloadingMaxNum = 10;
        int failedTryAgain = 3;
        var package = YooAssets.GetPackage("DefaultPackage");
        var downloader = package.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);

        //没有需要下载的资源
        if (downloader.TotalDownloadCount == 0)
        {
            yield break;
        }

        //需要下载的文件总数和总大小
        int totalDownloadCount = downloader.TotalDownloadCount;
        long totalDownloadBytes = downloader.TotalDownloadBytes;

        //注册回调方法
        downloader.OnDownloadErrorCallback = OnDownloadErrorFunction;
        downloader.OnDownloadProgressCallback = OnDownloadProgressUpdateFunction;
        downloader.OnDownloadOverCallback = OnDownloadOverFunction;
        downloader.OnStartDownloadFileCallback = OnStartDownloadFileFunction;

        //开启下载
        downloader.BeginDownload();
        yield return downloader;

        //检测下载结果
        if (downloader.Status == EOperationStatus.Succeed)
        {
            //下载成功
            Debug.Log("更新完成");
        }
        else
        {
            //下载失败
            Debug.Log("更新失败");
        }
    }

    /// <summary>
    /// 开始下载
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="sizeBytes"></param>
    private void OnStartDownloadFileFunction(string fileName, long sizeBytes)
    {
        Debug.Log(string.Format("开始下载:文件名:{0},文件大小:{1}", fileName, sizeBytes));
    }

    /// <summary>
    /// 下载完成
    /// </summary>
    /// <param name="isSucceed"></param>
    private void OnDownloadOverFunction(bool isSucceed)
    {
        Debug.Log("下载" + (isSucceed ? "成功" : "失败"));
    }

    /// <summary>
    /// 更新中
    /// </summary>
    /// <param name="totalDownloadCount"></param>
    /// <param name="currentDownloadCount"></param>
    /// <param name="totalDownloadBytes"></param>
    /// <param name="currentDownloadBytes"></param>
    private void OnDownloadProgressUpdateFunction(int totalDownloadCount, int currentDownloadCount, long totalDownloadBytes, long currentDownloadBytes)
    {
        Debug.Log(string.Format("文件总数:{0},已下载文件数:{1},下载总大小:{2},已下载大小{3}", totalDownloadCount, currentDownloadCount, totalDownloadBytes, currentDownloadBytes));
    }

    /// <summary>
    /// 下载出错
    /// </summary>
    /// <param name="fileName"></param>
    /// <param name="error"></param>
    private void OnDownloadErrorFunction(string fileName, string error)
    {
        Debug.Log(string.Format("下载出错:文件名:{0},错误信息:{1}", fileName, error));
    }

    private string GetHostServerURL()
    {
        //string hostServerIP = "http://10.0.2.2"; //安卓模拟器地址
        string hostServerIP = "http://127.0.0.1";
        string appVersion = "v1.5";
//资源地址自行修改
#if UNITY_EDITOR
        if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.Android)
            return $"{hostServerIP}/CDN/Android/{appVersion}";
        else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.iOS)
            return $"{hostServerIP}/CDN/IPhone/{appVersion}";
        else if (UnityEditor.EditorUserBuildSettings.activeBuildTarget == UnityEditor.BuildTarget.WebGL)
            return $"{hostServerIP}/CDN/WebGL/{appVersion}";
        else
            return $"{hostServerIP}/CDN/PC/Package";
#else
		if (Application.platform == RuntimePlatform.Android)
			return $"{hostServerIP}/CDN/Android/{appVersion}";
		else if (Application.platform == RuntimePlatform.IPhonePlayer)
			return $"{hostServerIP}/CDN/IPhone/{appVersion}";
		else if (Application.platform == RuntimePlatform.WebGLPlayer)
			return $"{hostServerIP}/CDN/WebGL/{appVersion}";
		else
			return $"{hostServerIP}/CDN/PC/Package";
#endif
    }

    /// <summary>
    /// 远端资源地址查询服务类
    /// </summary>
    private class RemoteServices : IRemoteServices
    {
        private readonly string _defaultHostServer;
        private readonly string _fallbackHostServer;

        public RemoteServices(string defaultHostServer, string fallbackHostServer)
        {
            _defaultHostServer = defaultHostServer;
            _fallbackHostServer = fallbackHostServer;
        }
        string IRemoteServices.GetRemoteMainURL(string fileName)
        {
            return $"{_defaultHostServer}/{fileName}";
        }
        string IRemoteServices.GetRemoteFallbackURL(string fileName)
        {
            return $"{_fallbackHostServer}/{fileName}";
        }
    }


    #endregion

    private static Assembly _hotUpdateAss;

    /// <summary>
    /// 为aot assembly加载原始metadata, 这个代码放aot或者热更新都行。
    /// 一旦加载后,如果AOT泛型函数对应native实现不存在,则自动替换为解释模式执行
    /// </summary>
    private static void LoadMetadataForAOTAssemblies()
    {
        /// 注意,补充元数据是给AOT dll补充元数据,而不是给热更新dll补充元数据。
        /// 热更新dll不缺元数据,不需要补充,如果调用LoadMetadataForAOTAssembly会返回错误
        /// 
        HomologousImageMode mode = HomologousImageMode.SuperSet;
        foreach (var aotDllName in AOTMetaAssemblyFiles)
        {
            byte[] dllBytes = ReadBytesFromStreamingAssets(aotDllName);
            // 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode);
            Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. mode:{mode} ret:{err}");
        }
    }

    void StartGame()
    {
        LoadMetadataForAOTAssemblies();
#if !UNITY_EDITOR
        _hotUpdateAss = Assembly.Load(ReadBytesFromStreamingAssets("HotUpdate.dll"));
#else
        _hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
#endif
        //Type entryType = _hotUpdateAss.GetType("Entry");
        //entryType.GetMethod("Start").Invoke(null, null);

        Run_InstantiateComponentByAsset();
    }

    private void Run_InstantiateComponentByAsset()
    {
        // 通过实例化assetbundle中的资源,还原资源上的热更新脚本
        //AssetBundle ab = AssetBundle.LoadFromMemory(LoadDll.ReadBytesFromStreamingAssets("prefabs"));
        var package = YooAssets.GetPackage("DefaultPackage");
        //GameObject cube = ab.LoadAsset<GameObject>("Cube");
        AssetOperationHandle handle = package.LoadAssetAsync<GameObject>("Cube");
        handle.Completed += Handle_Completed;
        //GameObject.Instantiate(cube);
    }
    private void Handle_Completed(AssetOperationHandle obj)
    {
        GameObject go = obj.InstantiateSync();
        Debug.Log($"Prefab name is {go.name}");
    }
    /// <summary>
    /// 默认的分发资源查询服务类
    /// </summary>
    private class DefaultDeliveryQueryServices : IDeliveryQueryServices
    {
        public DeliveryFileInfo GetDeliveryFileInfo(string packageName, string fileName)
        {
            throw new NotImplementedException();
        }
        public bool QueryDeliveryFiles(string packageName, string fileName)
        {
            return false;
        }
    }
}
//代码自行整理
//PS:版本不同可能有一些类名发生变化,请参照现阶段版本自行修改,官网可能更新不及时。

然后再场景里添加Cube游戏物体并再Cube上添加InstantiateByAsset或者自己写一个啥脚本都行。里面有start方法作为程序运行入口。

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;

public class InstantiateByAsset : MonoBehaviour
{
    public string text;

    void Start()
    {
        Debug.Log($"[InstantiateByAsset] text:{text}, 首次");
    }
}

然后将Cube放入刚才新建的Assets/AssetPackage/Prefabs下删除掉Hierarchy场景里的Cube,然后将Cube上的脚本拖入到文件夹HotUpdate中,所有和热更有关的代码都要放在这个文件加下。ps:类似于大家熟悉的xLua中的[hotfix]热更标签,只不过脱离了代码了
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
然后选中程序集HotUpdate,在上面添加这两个程序集
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎

打包发布

然后返回unity界面,点击Build Settings先生成exe或者apk包程序。
之后返回unity界面。
第一步
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
第二步
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
然后会在StreamingAssets文件夹下生成一河滩之前LoadDll代码里的AOT相关的桥接文件。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
将着一河滩.dll文件移动到Assets/AssetPackage/Codes文件夹中。
之后的操作大家都很熟悉了。
第一步
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
点击构建后,又生成了一河滩更多的东西。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
将着一河滩东西,移动到之前的安装的资源服务器www文件夹下。打开刚才生成好的exe或apk程序。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
完事!

测试

回到unity界面,在Assets/AssetPackage/Scenes中新建场景。
进入新场景,在里面生成UI/Button
Assets/HotUpdate文件夹下创建Button_click代码。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Button_click : MonoBehaviour
{
    private void Start()
    {
        GetComponent<Button>().onClick.AddListener(() => Debug.Log("老于爱玩亚索"));
    }
}

将代码挂到Button上。
然后修改Assets/HotUpdate/InstantiateByAsset.cs

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using UnityEngine;
using YooAsset;

public class InstantiateByAsset : MonoBehaviour
{
    public string text;

    void Start()
    {
        Debug.Log($"[InstantiateByAsset] text:{text}, 第一次");
        var package = YooAssets.GetPackage("DefaultPackage");
        #region 异步加载场景
        string location = "22";//场景名字
        var sceneMode = UnityEngine.SceneManagement.LoadSceneMode.Single;
        bool suspendLoad = false;
        SceneOperationHandle handle = package.LoadSceneAsync(location, sceneMode, suspendLoad);
        handle.Completed += o =>
        {
            //回调逻辑
        };
        #endregion
    }
}

Console To Screen脚本挂到Main Camera上。
然后重新HybridCLR选项的两步和YooAsset构建。

  • HybridCLR生成一河滩文件后,先将原来的Assets/AssetPackage/Codes下的文件删除,再把新生成的移动到Assets/AssetPackage/Codes下。
  • 再用YooAssset构建,可以选择增量
    Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎

然后将原来的资源服务器上的热更文件删除,复制新的文件上去。
打开之前的exe程序或者apk程序。
Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇,unity,游戏引擎
场景跳转成功!
至此Unity热更教程结束,感觉确实比XLua、ULua更人性化有没有。文章来源地址https://www.toymoban.com/news/detail-736755.html

到了这里,关于Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 划时代!Eclipse AI编码新方式——Copilot4Eclipse即将发布

    在本月早些时候,MyEclipse官方宣布了将于本月晚些时候发布全新插件Copilot4Eclipse,它是同类型插件中的第一个,能帮助开发者直接在Eclipse IDE中无缝地使用GitHub Copilot AI编码辅助。 MyEclipse一次性提供了巨量的Eclipse插件库,无需学习任何新的开发语言和工具,便可在一体化的

    2024年02月03日
    浏览(36)
  • Unity + HybridCLR,近乎完美的新热更方案,从零开始(一)——Hello World

    最近又新接触了一种unity热更的解决方案——HybridCLR,自称是: 特性完整、零成本、高性能、低内存的近乎完美的Unity全平台原生c#热更方案 。 接下来我们就来一起学习下。 下面是官方文档的链接,一切以官方为主:HybridCLR HybridCLR扩充了il2cpp的代码,使它由纯AOT runtime变成

    2024年02月07日
    浏览(46)
  • Unity转微信小游戏 HybridCLR + YooAsset 实践

    参考链接:https://github.com/wechat-miniprogram/minigame-unity-webgl-transform?tab=readme-ov-file Unity 2021.3.15f1c1 Unity 2021.2.5f1c302 wxSDK HybridCLR 5.0.0 YooAsset 1.5.7 后台配置白名单 微信小游戏注意事项: 不支持同步加载。 不支持资源加密。 不支持多Package 关闭WebGL本地缓存 参考地址 因为微信小游戏

    2024年04月12日
    浏览(110)
  • 【Unity实战】HybridCLR热更快速集成

    本文假设你已经通过UPM导入了HybridCLR、Addressables、il2cpp支持并具有一定的C#基础和Unity编辑器操作能力。 由于本文主打快速集成,故将Assembly-CSharp划入到热更新DLL。 理论上成熟的项目应该用Assembly Definition进行精细划分以便于管理和缩短编译时间。但是若掌握不好,划分不明白

    2024年02月03日
    浏览(49)
  • Unity热更模块基于 HybridCLR + Addressable

    代码地址: GitHub - ManoKing/FFramework: 基于HybridCLR + Addressable的热更新框架,提供例子基于QFramework+URP开发 基于HybridCLR + Addressable的热更新框架,提供例子基于QFramework+URP开发 - GitHub - ManoKing/FFramework: 基于HybridCLR + Addressable的热更新框架,提供例子基于QFramework+URP开发 https://github.

    2023年04月14日
    浏览(48)
  • Unity 之 Addressable可寻址系统 -- HybridCLR(华佗)+Addressable实现资源脚本全热更 -- 实战(二)

    在Unity中,结合 Addressable Asset System (简称:AA)和 HybridCLR 来实现热更新资源和脚本的控制。 AA 是Unity的一个强大的资源管理系统,可以用于动态加载和更新资源。HybridCLR是一个用于在Unity中运行C#脚本的工具,可以实现热更新脚本的功能。 使用版本: Unity 2022.3.8 Addressables 1.21

    2024年01月24日
    浏览(64)
  • [Unity实战][C#实战]HybridCLR(wolong)卧龙C#热更框架v2.0.x-Unity2020.3.21f1

    官网介绍 HybridCLR(代号wolong)是一个特性完整、零成本、高性能、低内存的近乎完美的Unity全平台原生c#热更方案。 HybridCLR扩充了il2cpp的代码,使它由纯AOT (opens new window)runtime变成‘AOT+Interpreter’ 混合runtime,进而原生支持动态加载assembly,使得基于il2cpp backend打包的游戏不仅能在

    2024年02月15日
    浏览(43)
  • unity资源管理方案-YooAsset的使用

    我们在开发项目时,会发现资源管理模块往往在项目架构中扮演着重要的角色,而且一个游戏的流畅性和内存方面的性能优化,往往也能看到资源管理的影子,所以一个优秀强大的资源管理方案对一个项目开发者来说是一个强大的轮子。 YooAsset是一套用于Unity3D的资源管理系统

    2024年01月20日
    浏览(52)
  • HyBridCLR(华佗热更)踩坑记录

            官方说明:HybridCLR扩充了il2cpp的代码,使它由纯AOT runtime变成‘AOT+Interpreter’ 混合runtime,进而原生支持动态加载assembly,使得基于il2cpp backend打包的游戏不仅能在Android平台,也能在IOS、Consoles等限制了JIT的平台上高效地以 AOT+interpreter 混合模式执行,从底层彻底支持了

    2024年01月25日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包