宁波 外贸b2c网站建设/十大营销策略有哪些

宁波 外贸b2c网站建设,十大营销策略有哪些,查询网站怎么做的,各大网站的404文章目录: 一、前言二、创建空工程三、接入HybridCLR四、接入YooAsset五、搭建本地资源服务器Nginx六、实战七、最后八、后记 一、前言 unity热更有很多方案,各种lua热更,ILRuntime等,这里介绍的是YooAssetHybridCLR的热更方案&a…

文章目录:

  • 一、前言
  • 二、创建空工程
  • 三、接入HybridCLR
  • 四、接入YooAsset
  • 五、搭建本地资源服务器Nginx
  • 六、实战
  • 七、最后
  • 八、后记

一、前言

unity热更有很多方案,各种lua热更,ILRuntime等,这里介绍的是YooAsset+HybridCLR的热更方案,HybridCLR负责更新c#代码,YooAsset负责更新资源。

简单来说,流程就是将c#代码打成dll,然后把dll当做一个资源,用YooAsset热更dll资源之后,动态加载dll程序集,然后执行新逻辑

HybridCLR相比其他代码热更方案而言,纯c#方便开发,更加符合开发者习惯,更新的代码执行效率也更好。

YooAsset热更资源,主要是省去了自己亲自管理ab包,ab包的管理挺繁琐,AssetBundle坑也很多,而且YooAsset有下载器,不用自己手写网络下载,也不用自己记录资源,比对资源列表来判定需要热更什么资源。

这里将从零开始,用一个空工程,展示YooAsset+HybridCLR热更的使用过程。

二、创建空工程

这里使用的版本是unity2022.3.17.f1c1
在这里插入图片描述

三、接入HybridCLR

unity必须添加了Windows Build Support(IL2CPP)或Mac Build Support(IL2CPP)模块
在这里插入图片描述
在这里插入图片描述

安装IDE及相关编译环境
Win
需要安装visual studio 2019或更高版本。安装时至少要包含使用Unity的游戏开发和使用c++的游戏开发组件。
安装git

Mac
要求MacOS版本 >= 12,xcode版本 >= 13,例如xcode 13.4.1, macos 12.4。
安装 git

添加ConsoleToScreen.cs脚本
和热更无关,主要在屏幕上显示log,代码如下:

using System.Collections.Generic;
using UnityEngine;public class ConsoleToScreen : MonoBehaviour
{const int maxLines = 50;const int maxLineLength = 120;private string _logStr = "";private readonly List<string> _lines = new();public int fontSize = 15;void OnEnable() { Application.logMessageReceived += Log; }void OnDisable() { Application.logMessageReceived -= Log; }public void Log(string logString, string stackTrace, LogType type){foreach (var line in logString.Split('\n')){if (line.Length <= maxLineLength){_lines.Add(line);continue;}var lineCount = line.Length / maxLineLength + 1;for (int i = 0; i < lineCount; i++){if ((i + 1) * maxLineLength <= line.Length){_lines.Add(line.Substring(i * maxLineLength, maxLineLength));}else{_lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));}}}if (_lines.Count > maxLines){_lines.RemoveRange(0, _lines.Count - maxLines);}// _lines.Add(stackTrace);_logStr = string.Join("\n", _lines);}void OnGUI(){GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle { fontSize = 10 });}
}

工程初始设置
创建Main场景
将ConsoleToScreen挂载一个创建的空物体上
菜单栏 File/BuildSettings添加Main场景
创建Assets/HotUpdate目录
在这里插入图片描述

创建热更程序集
在HotUpdate目录下 右键 Create/Assembly Definition,创建一个名为HotUpdate的程序集模块
在这里插入图片描述

安装HybridCLR
主菜单中点击Windows/Package Manager
Add package from git URL…
填入:https://gitee.com/focus-creative-games/hybridclr_unity.git
如下:
在这里插入图片描述
在这里插入图片描述

初始化HybridCLR
打开菜单HybridCLR/Installer…, 点击Install按钮进行安装。 耐心等待30s左右,安装完成后会在最后打印 安装成功日志。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

配置HybridCLR
打开菜单 HybridCLR/Settings, 在热更新Assembly Definitions配置项中添加HotUpdate程序集。
在这里插入图片描述
在这里插入图片描述

设置PlayerSettings
打开菜单Edit/Project Setting,在Player选项中,设置如下几个配置:
Scripting Backend 切换为 IL2CPP。
Api Compatability Level 切换为 .Net 4.x(Unity 2019-2020) 或.Net Framework(Unity 2021+)
在这里插入图片描述
在这里插入图片描述

HybridCLR方面的操作告一段落,接下来接入YooAsset

四、接入YooAsset

安装YooAsset
打开菜单Edit/Project Settings/Package Manager
在Package Manager选项找那个,输入如下内容,点击save:

(国际版)
Name: package.openupm.com
URL: https://package.openupm.com
Scope(s): com.tuyoogame.yooasset

(中国版)
Name: package.openupm.cn
URL: https://package.openupm.cn
Scope(s): com.tuyoogame.yooasset
(这个配置好像报错了,我用的上面国际版的地址)
在这里插入图片描述
在这里插入图片描述

打开菜单Windows/Package Manager
Packages选择My Registries,出现了YooAsset,点击Install安装。
在这里插入图片描述
在这里插入图片描述

五、搭建本地资源服务器Nginx

为了模拟热更流程,需要一个服务器作为热更资源的下载,我们可以在本机搭建一个资源服务器。我这里用的是Nginx。
下载地址:https://nginx.org/en/download.html
在这里插入图片描述

随便下一个,下载之后是个zip包,解压之后如下:
在这里插入图片描述

注意:端口冲突时,更改端口:打开文件:conf-nginx.conf,修改第36行的listen,我改的是8084,自己随意
然后运行nginx.exe即可
在这里插入图片描述

现在打开网址http://127.0.0.1:8084如下:
在这里插入图片描述

html文件夹下,就可以放需要热更的资源,比如我准备打包测试的是pc平台,我就在html文件夹下建了个TestProject文件夹,在里面再建个PC文件夹,TestProject是项目名,PC是平台名,用以放接下来要热更的资源
在这里插入图片描述

六、实战

创建热更目录
之前的HotUpdate文件夹是为了放c#代码,用以生成程序集的,接下来创建的目录,是为了热更资源的(包括c#代码的dll资源,dll也是一种资源),创建如下目录:
在这里插入图片描述

准备工作
HotUpdate文件夹下创建InstantiateByAsset.cs,这是会被热更的代码:

using UnityEngine;public class InstantiateByAsset : MonoBehaviour
{void Start(){Debug.Log("原始代码");}
}

在这里插入图片描述

创建一个cube预制体,挂载InstantiateByAsset组件,放入MyAsset/Prefabs中
在这里插入图片描述

收集热更资源

创建Resources文件夹,在Resources文件夹内通过右键创建配置文件(Project窗体内右键 -> Create -> YooAsset -> Create Setting),将配置文件放在Resources文件夹下
在这里插入图片描述

打开菜单YooAsset/AssetBundle Collector,点击ShowPackages,再点击+号,创建packages,再点击ShowPackages,只显示Groups就行,方便操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

打开Enable Addressable
添加code和prefab分组,具体设置如下:
在这里插入图片描述
在这里插入图片描述

选项含义如下,其他含义,请看官网
在这里插入图片描述

编写LoadDll.cs
编写代码初始化YooAsset,从资源服加载热更资源,加载热更程序集,将LoadDll.cs挂在Main场景的Main Camera上。

整个代码流程就是先初始化,然后下载热更资源,然后补充元数据,然后开始执行热更代码。
关于补充元数据,通俗的理解,举个例子:

由于Unity IL2CPP打包的代码裁剪,假设在打包时的代码,从来没有用过List泛型,打包时,List的元数据会被裁掉了。到玩家手机的APP上,根本不存在List的程序定义等关键信息。当玩家运行app时,在运行前预编译这个app的代码时,是不存在List的相关定义的,编译完成后,在运行时,热更逻辑中,使用了List,虽然这个热更的dll中有List的程序定义,但是已经过了编译阶段,现在是执行阶段,执行阶段是直接找预编译时的程序定义去进行实例化。所以在动态执行包含有List的代码时,由于编译阶段缺失了List的程序定义相关的元数据,无法对其进行实例化。所以在运行包含了List的热更代码时,先补齐编译阶段缺失的List元数据,之后才能正常运行和实例化热更中的包含了List的代码。

常见的需要补充的元数据如:mscorlib.dll, System.dll, System.Core.dll

详细信息原理请浏览官网

注意!注意!注意!
如果你用较新版的YooAsset插件,导致这个脚本中的各种类找不到,请翻到本文第八小节:后记,里面有适应最新版(到2024.12.21日,YooAsset2.2.7版)的LoadDll.cs,可以用那个代码,并更改上文中YooAssetSettings资源的位置,新位置在后记中也已标注。

代码如下:

using HybridCLR;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using YooAsset;/// <summary>
/// 脚本工作流程:
/// 1.下载资源,用yooAsset资源框架进行下载
///    1.资源文件,ab包
///    2.热更新dll
/// 2.给AOT DLL补充元素据,通过RuntimeApi.LoadMetadataForAOTAssembly
/// 3.通过实例化prefab,运行热更代码
/// </summary>
public class LoadDll : MonoBehaviour
{/// <summary>/// 资源系统运行模式/// </summary>public EPlayMode PlayMode = EPlayMode.HostPlayMode;private ResourcePackage _defaultPackage;void Start(){StartCoroutine(InitYooAssets(StartGame));}#region YooAsset初始化IEnumerator InitYooAssets(Action onDownloadComplete){// 1.初始化资源系统YooAssets.Initialize();string packageName = "DefaultPackage";var package = YooAssets.TryGetPackage(packageName) ?? YooAssets.CreatePackage(packageName);YooAssets.SetDefaultPackage(package);if (PlayMode == EPlayMode.EditorSimulateMode){//编辑器模拟模式var initParameters = new EditorSimulateModeParameters { SimulateManifestFilePath = EditorSimulateModeHelper.SimulateBuild(EDefaultBuildPipeline.BuiltinBuildPipeline, "DefaultPackage") };yield return package.InitializeAsync(initParameters);}else if (PlayMode == EPlayMode.HostPlayMode){//联机运行模式string defaultHostServer = GetHostServerURL();string fallbackHostServer = GetHostServerURL();Debug.Log(defaultHostServer);var initParameters = new HostPlayModeParameters();initParameters.BuildinQueryServices = new GameQueryServices();// initParameters.DecryptionServices = new GameDecryptionServices();// initParameters.DeliveryQueryServices = new DefaultDeliveryQueryServices();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}");}}//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()方法保存。var operation2 = package.UpdatePackageManifestAsync(packageVersion);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){var handle = package.LoadAssetAsync<TextAsset>(asset);yield return handle;var assetObj = handle.AssetObject as TextAsset;s_assetDatas[asset] = assetObj;Debug.Log($"dll:{asset}   {assetObj == null}");}_defaultPackage = package;onDownloadComplete();}private string GetHostServerURL(){//模拟下载地址,8084为Nginx里面设置的端口号,项目名,平台名return "http://127.0.0.1:8084/TestProject/PC";}/// <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}";}}/// <summary>/// 资源文件查询服务类/// </summary>internal class GameQueryServices : IBuildinQueryServices{public bool Query(string packageName, string fileName, string fileCRC){
#if UNITY_IPHONEthrow new Exception("Ios平台需要内置资源");return false;
#elsereturn false;
#endif}}#endregion#region 下载热更资源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));}#endregion#region 补充元数据//补充元数据dll的列表//通过RuntimeApi.LoadMetadataForAOTAssembly()函数来补充AOT泛型的原始元数据private static List<string> AOTMetaAssemblyFiles { get; } = new() { "mscorlib.dll", "System.dll", "System.Core.dll", };private static Dictionary<string, TextAsset> s_assetDatas = new Dictionary<string, TextAsset>();private static Assembly _hotUpdateAss;public static byte[] ReadBytesFromStreamingAssets(string dllName){if (s_assetDatas.ContainsKey(dllName)){return s_assetDatas[dllName].bytes;}return Array.Empty<byte>();}/// <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}");}}#endregion#region 运行测试void StartGame(){// 加载AOT dll的元数据LoadMetadataForAOTAssemblies();// 加载热更dll
#if !UNITY_EDITOR_hotUpdateAss = Assembly.Load(ReadBytesFromStreamingAssets("HotUpdate.dll"));
#else_hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
#endifDebug.Log("运行热更代码");StartCoroutine(Run_InstantiateComponentByAsset());}IEnumerator Run_InstantiateComponentByAsset(){// 通过实例化assetbundle中的资源,还原资源上的热更新脚本var package = YooAssets.GetPackage("DefaultPackage");var handle = package.LoadAssetAsync<GameObject>("Cube");yield return handle;handle.Completed += Handle_Completed;}private void Handle_Completed(AssetHandle obj){Debug.Log("准备实例化");GameObject go = obj.InstantiateSync();Debug.Log($"Prefab name is {go.name}");}#endregion
}
//PS:版本不同可能有一些类名发生变化,请参照现阶段版本自行修改,官网可能更新不及时。

打包阶段
(这里演示的是pc平台)
打开菜单 HybridCLR/Generate/All,耐心等待之后,
回到Assets同级目录,将HybridCLRData/HotUpdateDlls/StandaloneWindows64/HotUpdate.dll复制到Assets/MyAssset/Codes内,并且加上后缀.bytes,这是包含热更逻辑代码的dll
在这里插入图片描述

再将HybridCLRData/AssembliesPostIl2CppStrip/StandaloneWindows64目录下的mscorlib.dll, System.dll, System.Core.dll这三个dll复制到Assets/MyAssset/Codes内,并且加上后缀.bytes,这是包含补充元数据的dll
在这里插入图片描述
在这里插入图片描述

打开菜单YooAsset/AssetBundle Builder,BuildModel选ForceRebuild,全量构建。一般第一次选这个,后面IncrementalBuild热更选增量构建,点击ClickBuild
在这里插入图片描述

构建完之后会自动打开构建后的资源目录,在Asset同级目录下的Bundles/StandaloneWindows64/DefaultPackage/2024-06-27-1194(构建时的版本号)
在这里插入图片描述

把里面的所有东西,放在本地资源服务器Nginx的目录下,之前代码里访问的地址:http://127.0.0.1:8084/TestProject/PC就是这里了,到时候热更就是从这里下载最新的资源
在这里插入图片描述

操作完上述之后,打开菜单 File/Build Settings/Build先把.exe打出来,双击运行,能看到先从http://127.0.0.1:8084/TestProject/PC路径下下载资源包,然后补充元数据,然后实例化了Cube预制体,执行了预制体上的代码,打印了“原始代码”。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

开始热更
终于到了激动人心的热更环节,前面搞了那么多就是为了热更代码和资源。接下来我们把cube预制体尺寸x改为10,将InstantiateByAsset脚本的输出从“原始代码”改为“热更后的代码”。
在这里插入图片描述
在这里插入图片描述

点击菜单 HybridCLR/CompileDll/ActiveBuildTarget,把新的HotUpdate.dll复制替换掉MyAsset里面原来的HotUpdate.dll,记得加后缀.bytes,另外三个mscorlib.dll, System.dll, System.Core.dll也复制替换过去记得加后缀.bytes
在这里插入图片描述
在这里插入图片描述

打开菜单YooAsset/AssetBundle Builder,BuildModel选IncrementalBuild,增量构建,点击ClickBuild,然后自动打开了生成的资源所在的文件夹,把这一堆生成的东西,复制到本地资源服务器Nginx的TestProject/PC目录下,之前的旧资源删掉。
在这里插入图片描述
在这里插入图片描述

然后重新打开之前的exe程序,看到代码和资源都热更了,大功告成!!!
在这里插入图片描述

七、最后

至于其他的更多细节,比如加密解密,资源收集设置等待,可以多多浏览官网以及官网的示例项目。
HybridCLR
YooAsset

github工程:https://github.com/zhanghan2007/HotDemo

八、后记

2024.12.31日

文章发出后,很多小伙伴表示里面各种类找不到,那是由于新版本的YooAsset插件里面有一些改动,我用当天最新版2.2.7版本的YooAsset插件,修改了报错部分并重试了一下,demo可以跑通。

修改部分如下:

1.修改LoadDll.cs脚本,修复报错,代码如下:

using HybridCLR;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEngine;
using YooAsset;/// <summary>
/// 脚本工作流程:
/// 1.下载资源,用yooAsset资源框架进行下载
///    1.资源文件,ab包
///    2.热更新dll
/// 2.给AOT DLL补充元素据,通过RuntimeApi.LoadMetadataForAOTAssembly
/// 3.通过实例化prefab,运行热更代码
/// </summary>
public class LoadDll : MonoBehaviour
{/// <summary>/// 资源系统运行模式/// </summary>public EPlayMode PlayMode = EPlayMode.HostPlayMode;private ResourcePackage _defaultPackage;void Start(){StartCoroutine(InitYooAssets(StartGame));}#region YooAsset初始化IEnumerator InitYooAssets(Action onDownloadComplete){// 1.初始化资源系统YooAssets.Initialize();string packageName = "DefaultPackage";var package = YooAssets.TryGetPackage(packageName) ?? YooAssets.CreatePackage(packageName);YooAssets.SetDefaultPackage(package);InitializationOperation initializationOperation = null; //===================================适应新版本YooAsset插件的修改===================================if (PlayMode == EPlayMode.EditorSimulateMode){// //编辑器模拟模式var simulateBuildParam = new EditorSimulateBuildParam { PackageName = packageName };var simulateBuildResult = EditorSimulateModeHelper.SimulateBuild(simulateBuildParam);var createParameters = new EditorSimulateModeParameters { EditorFileSystemParameters = FileSystemParameters.CreateDefaultEditorFileSystemParameters(simulateBuildResult) };initializationOperation = package.InitializeAsync(createParameters);}else if (PlayMode == EPlayMode.HostPlayMode){//联机运行模式string defaultHostServer = GetHostServerURL();string fallbackHostServer = GetHostServerURL();IRemoteServices remoteServices = new RemoteServices(defaultHostServer, fallbackHostServer);var createParameters = new HostPlayModeParameters { BuildinFileSystemParameters = FileSystemParameters.CreateDefaultBuildinFileSystemParameters(), CacheFileSystemParameters = FileSystemParameters.CreateDefaultCacheFileSystemParameters(remoteServices) };initializationOperation = package.InitializeAsync(createParameters);}yield return initializationOperation;//===================================适应新版本YooAsset插件的修改===================================if (initializationOperation.Status == EOperationStatus.Succeed){Debug.Log("资源包初始化成功!");}else{Debug.LogError($"资源包初始化失败:{initializationOperation.Error}");}//2.获取资源版本var operation = package.RequestPackageVersionAsync();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()方法保存。var operation2 = package.UpdatePackageManifestAsync(packageVersion);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){var handle = package.LoadAssetAsync<TextAsset>(asset);yield return handle;var assetObj = handle.AssetObject as TextAsset;s_assetDatas[asset] = assetObj;Debug.Log($"dll:{asset}   {assetObj == null}");}_defaultPackage = package;onDownloadComplete();}private string GetHostServerURL(){//模拟下载地址,8084为Nginx里面设置的端口号,项目名,平台名return "http://127.0.0.1:8084/TestProject/PC";}/// <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}";}}//===================================适应新版本YooAsset插件的修改===================================
//     /// <summary>
//     /// 资源文件查询服务类
//     /// </summary>
//     internal class GameQueryServices : IBuildinQueryServices
//     {
//         public bool Query(string packageName, string fileName, string fileCRC)
//         {
// #if UNITY_IPHONE
//             throw new Exception("Ios平台需要内置资源");
//             return false;
// #else
//             return false;
// #endif
//         }
//     }
//===================================适应新版本YooAsset插件的修改===================================#endregion#region 下载热更资源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;//===================================适应新版本YooAsset插件的修改===================================//注册回调方法downloader.DownloadErrorCallback = OnDownloadErrorFunction;downloader.DownloadUpdateCallback = OnDownloadProgressUpdateFunction;downloader.DownloadFinishCallback = OnDownloadOverFunction;downloader.DownloadFileBeginCallback = OnStartDownloadFileFunction;//===================================适应新版本YooAsset插件的修改===================================//开启下载downloader.BeginDownload();yield return downloader;//检测下载结果if (downloader.Status == EOperationStatus.Succeed){//下载成功Debug.Log("更新完成");}else{//下载失败Debug.Log("更新失败");}}//===================================适应新版本YooAsset插件的修改===================================/// <summary>/// 开始下载/// </summary>private void OnStartDownloadFileFunction(DownloadFileData downloadFileData){Debug.Log($"开始下载:文件名:{downloadFileData.FileName},文件大小:{downloadFileData.FileSize}");}/// <summary>/// 下载完成/// </summary>private void OnDownloadOverFunction(DownloaderFinishData downloaderFinishData){Debug.Log("下载" + (downloaderFinishData.Succeed ? "成功" : "失败"));}/// <summary>/// 更新中/// </summary>private void OnDownloadProgressUpdateFunction(DownloadUpdateData downloadUpdateData){Debug.Log($"文件总数:{downloadUpdateData.TotalDownloadCount},已下载文件数:{downloadUpdateData.CurrentDownloadCount},下载总大小:{downloadUpdateData.TotalDownloadBytes},已下载大小{downloadUpdateData.CurrentDownloadBytes}");}/// <summary>/// 下载出错/// </summary>/// <param name="errorData"></param>private void OnDownloadErrorFunction(DownloadErrorData errorData){Debug.Log($"下载出错:包名:{errorData.PackageName} 文件名:{errorData.FileName},错误信息:{errorData.ErrorInfo}");}//===================================适应新版本YooAsset插件的修改===================================#endregion#region 补充元数据//补充元数据dll的列表//通过RuntimeApi.LoadMetadataForAOTAssembly()函数来补充AOT泛型的原始元数据private static List<string> AOTMetaAssemblyFiles { get; } = new() { "mscorlib.dll", "System.dll", "System.Core.dll", };private static Dictionary<string, TextAsset> s_assetDatas = new Dictionary<string, TextAsset>();private static Assembly _hotUpdateAss;public static byte[] ReadBytesFromStreamingAssets(string dllName){if (s_assetDatas.ContainsKey(dllName)){return s_assetDatas[dllName].bytes;}return Array.Empty<byte>();}/// <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}");}}#endregion#region 运行测试void StartGame(){// 加载AOT dll的元数据LoadMetadataForAOTAssemblies();// 加载热更dll
#if !UNITY_EDITOR_hotUpdateAss = Assembly.Load(ReadBytesFromStreamingAssets("HotUpdate.dll"));
#else_hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
#endifDebug.Log("运行热更代码");StartCoroutine(Run_InstantiateComponentByAsset());}IEnumerator Run_InstantiateComponentByAsset(){// 通过实例化assetbundle中的资源,还原资源上的热更新脚本var package = YooAssets.GetPackage("DefaultPackage");var handle = package.LoadAssetAsync<GameObject>("Cube");yield return handle;handle.Completed += Handle_Completed;}private void Handle_Completed(AssetHandle obj){Debug.Log("准备实例化");GameObject go = obj.InstantiateSync();Debug.Log($"Prefab name is {go.name}");}#endregion
}
//PS:版本不同可能有一些类名发生变化,请参照现阶段版本自行修改,官网可能更新不及时。

2.YooAssetSettings资源放到别的文件夹,修改如下:
原位置
新位置

3.其他操作不变

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/70086.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zabbix——监控Windows下某个文件夹的所有文件变化

获取所有的指定路径下的文件列表 以D:\Apps这个文件夹下的所有文件为例&#xff0c;我需要找到这个文件夹里面的子文件夹中的所有文件&#xff0c;但是排除backup这个文件夹&#xff0c;下面我们来看怎么操作 在scripts目录下创建check_file_in_D_Apps.ps1文件&#xff0c;内容…

C++ Primer 函数匹配

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

java八股文-mysql

1. 索引 1.1 什么是索引 索引(index)是帮助Mysql高效获取数据的数据结构(有序).提高数据的检索效率,降低数据库的IO成本(不需要全表扫描).通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗. 1.2 mysql索引使用的B树? 1. 没有使用二叉树&#xff0c;最坏情况o&…

Docker拉不下来镜像问题解决法案

打开docker的设置界面 配置如下&#xff1a; vi /etc/docker/daemon.json {"builder": {"gc": {"defaultKeepStorage": "20GB","enabled": true}},"experimental": false,"registry-mirrors": ["…

春招项目=图床+ k8s 控制台(唬人专用)

1. 春招伊始 马上要春招了&#xff0c;一个大气的项目&#xff08;冲击波项目&#xff09;直观重要&#xff0c;虽然大家都说基础很重要&#xff0c;但是一个足够新颖的项目完全可以把你的简历添加一个足够闪亮的点。 这就不得不推荐下我的 k8s 图床了&#xff0c;去年折腾快…

vue点击左边导航,右边出现页面步骤

vue点击左边导航&#xff0c;右边出现页面 步骤 一定要import不然会出错 index.js Course作为Homeview子路由 Homeview加入<Routerview> 点击跳转<RouterLink to> 父Homeview中有RouterView&#xff08;路由出口&#xff0c;跳转至相应路径&#xff09;和Router…

力扣 66.加一 (Java实现)

题目分析 给定一个数组&#xff0c;可以组成一个数字&#xff0c;将数字加一后&#xff0c;返回新数组 思路分析 首先跟着题目思路走&#xff0c;将数组按位*10可以得到数字&#xff0c;再加一&#xff0c;加一后按位%10&#xff0c;可以得到新的数组。但是此处数字会过大&…

visutal studio 2022使用qcustomplot基础教程

编译 下载&#xff0c;2.1.1版支持到Qt6.4 。 拷贝qcustomplot.h和qcustomplot.cpp到项目源目录&#xff08;Qt project&#xff09;。 在msvc中将它俩加入项目中。 使用Qt6.8&#xff0c;需要修改两处代码&#xff1a; L6779 # if QT_VERSION > QT_VERSION_CHECK(5, 2, …

联想笔记本电脑摄像头灯亮,但没有画面怎么解决,

联想小新电脑&#xff0c;遇到电脑黑屏。 解决方法&#xff0c;搜索打开任务管理器 打开联想管家的路径 打开BatterySetting.exe 程序 然后右下角会弹出一个东西&#xff0c;关闭这个摄像头的隐私模式。就可以打开了 就可以了

Ubuntu下载安装Docker-Desktop

下载 Ubuntu | Docker Docs 预备工作 Ubuntu增加docker apt库-CSDN博客 安装 sudo apt-get updatesudo apt install gnome-terminal# sudo apt install -y docker-composesudo apt-get install ./docker-desktop-amd64.deb 测试 sudo docker run hello-worldHello from D…

node.js + html调用ChatGPTApi实现Ai网站demo(带源码)

文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言 关注博主&#xff0c;学习每天一个小demo 今天是Ai对话网站 又到了每天一个小demo的时候咯&#xff0c;前面我写了多人实时对话demo、和视频转换demo&#xff0c;今天…

unity学习42:动画状态机:混合动画状态 blend tree

目录 1 动画状态机 1.1 新建动画状态 2 混合动画状态 blend Tree 2.1 new blend Tree 2.2 blend tree state 和普通的 state的属性不同 2.3 双击blend tree 进入下一层 blend tree内部 2.3.1 blend tree 内部 2.3.2 blend type 2.3.3 参数类型默认是float&#xff0…

Mybatisplus——Mybatisplus3.5.2版本使用Page分页插件查询,records有数据但是total显示0

目录 一、问题背景 debug 执行Mybatisplus使用Page分页插件查询时&#xff0c;发现 Page 里面的records有数据但是total显示0。 二、问题产生的原因 未配置MybatisPlus的分页插件拦截器导致的或者因mybatis-plus版本3.4或3.5版本导致原先的分页插件paginationInterceptor无法…

Android10 音频参数导出合并

A10 设备录音时底噪过大&#xff0c;让音频同事校准了下&#xff0c;然后把校准好的参数需要导出来&#xff0c;集成到项目中&#xff0c;然后出包&#xff0c;导出方式在此记录 设备安装debug系统版本调试好后&#xff0c; adb root adb remount adb shell 进入设备目录 导…

C#(Winform)通过添加AForge添加并使用系统摄像机

先展示效果 AForge介绍 AForge是一个专门为开发者和研究者基于C#框架设计的, 也是NET平台下的开源计算机视觉和人工智能库 它提供了许多常用的图像处理和视频处理算法、机器学习和神经网络模型&#xff0c;并且具有高效、易用、稳定等特点。 AForge主要包括: 计算机视觉与人…

【苍穹外卖】学习

软件开发整体介绍 作为一名软件开发工程师,我们需要了解在软件开发过程中的开发流程&#xff0c; 以及软件开发过程中涉及到的岗位角色&#xff0c;角色的分工、职责&#xff0c; 并了解软件开发中涉及到的三种软件环境。那么这一小节&#xff0c;我们将从 软件开发流程、角色…

yanshee机器人初次使用说明(备注)-PyCharm

准备 需要&#xff1a; 1&#xff0c;&#xff08;优必选&#xff09;yanshee机器人Yanshee 开发者说明 2&#xff0c;手机-联网简单操控 / HDMI线与显示器和键鼠标-图形化开发环境 / 笔记本&#xff08;VNC-内置图形化开发环境/PyCharm等平台&#xff09;。 3&#xff0c;P…

#渗透测试#批量漏洞挖掘#致远互联AnalyticsCloud 分析云 任意文件读取

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

时间序列分析(四)——差分运算、延迟算子、AR(p)模型

此前篇章&#xff1a; 时间序列分析&#xff08;一&#xff09;——基础概念篇 时间序列分析&#xff08;二&#xff09;——平稳性检验 时间序列分析&#xff08;三&#xff09;——白噪声检验 一、差分运算 差分运算的定义&#xff1a;差分运算是一种将非平稳时间序列转换…

信息收集-Web应用JS架构URL提取数据匹配Fuzz接口WebPack分析自动化

知识点&#xff1a; 1、信息收集-Web应用-JS提取分析-人工&插件&项目 2、信息收集-Web应用-JS提取分析-URL&配置&逻辑 FUZZ测试 ffuf https://github.com/ffuf/ffuf 匹配插件 Hae https://github.com/gh0stkey/HaE JS提取 JSFinder https://github.com/Threez…