原文链接:https://baijiahao.baidu.com/s?id=1745200406976270792&wfr=spider&for=pc

这是百度可以直接搜索到的

UE4官网针对热更新有较为详细的步骤,但是其中漏掉的几个问题导致实现不了效果。

总的来说可以分为四大步。

第一步:自己的项目设置好插件ChunkDownloader

1.新建第三人称c++项目工程,设置分块打包

2.勾选插件ChunkDownloader

3.修改项目的 Build.cs 文件

PrivateDependencyModuleNames.AddRange(

  1. new string[]{ "ChunkDownloader"}

4.保存后重新生成项目文件。操作:右键点击你的 .uproject 文件,然后点击 生成项目文件(Generate Project Files)

第二步:资源分块,然后打包。为了测试方便,新建三个map,分别放在不同的文件夹。我的是Test,Test2,Test3.

  1. 添加资源分块标签。

 

标签设置如图:红框内需必备

属性解释:

依次对自己的测试资源添加标签。

2.打包默认设置即可。这样你可以在打出的包里看到分好的pak文件。红框ID与你的标签ID对应。

第三步:构建资源清单与托管本地测试服务器

1.构建资源清单。这里注意,英文字符下 TAB建进行属性空格。

我的清单如下:

 

资源文件夹结构,其中Windows文件夹中放的是分块后的pak文件

稍作解释:

第1行是需要下载更新的pak数目

第2行理解为资源和清单所在的文件夹

后面的几行就是pak资源相关的。共5个属性。资源名字,资源大小(右键资源看其属性字节数),版本号,ChunkID,资源所在位置。

2.文件托管到本地测试服务器

如何创建本地测试服务器这里不啰嗦,可以参考ue4官网。

但是这里要注意:新建文件夹PatchingDemoCDN,除了上传我们前面准备好的资源和清单即PatchingDemoKey文件夹。我们还需要在PatchingDemoCDN文件夹中新建表单

这个表单中我们要写上$BUILD_ID对应的也就是资源和清单所在的文件夹PatchingDemoKey

最后我们还需要在项目的配置表DefaultGame.ini中添加用来下载资源的网站地址。这里我们是用本地服务器测试的。

[/Script/Plugins.ChunkDownloader PatchingDemoLive]

+CdnBaseUrls=127.0.0.1/PatchingDemoCDN

第三步:编辑代码和逻辑。(开始不必扩展,实现基本功能即可)

1.GameInstance不仅具有可以绑定的相应初始化和关闭函数,而且还可以在游戏运行时持续访问ChunkDownloader。

所以使用 GameInstance 作为基类创建 新C++类。将其命名为 PatchingDemoGameInstance

最后代码为:

  1. // Fill out your copyright notice in the Description page of Project Settings.
  2.  
  3. #pragma once
  4.  
  5. #include "CoreMinimal.h"
  6.  
  7. #include "Engine/GameInstance.h"
  8.  
  9. #include "PatchingDemoGameInstance.generated.h"
  10.  
  11. /**
  12.  
  13. *
  14.  
  15. */
  16.  
  17. DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPatchCompleteDelegate, bool, Succeeded);
  18.  
  19. UCLASS()
  20.  
  21. class UPatchingDemoGameInstance : public UGameInstance
  22.  
  23. {
  24.  
  25. GENERATED_BODY()
  26.  
  27. public:
  28.  
  29. /** Overrides */
  30.  
  31. virtual void Init() override;
  32.  
  33. virtual void Shutdown() override;
  34.  
  35. /** Delegates */
  36.  
  37. /** Fired when the patching process succeeds or fails */
  38.  
  39. UPROPERTY(BlueprintAssignable, Category = "Patching")
  40.  
  41. FPatchCompleteDelegate OnPatchComplete;
  42.  
  43. /** Starts the game patching process. Returns false if the patching manifest is not up to date. */
  44.  
  45. UFUNCTION(BlueprintCallable, Category = "Patching")
  46.  
  47. bool PatchGame();
  48.  
  49. UFUNCTION(BlueprintPure, Category = "Patching|Stats")
  50.  
  51. void GetLoadingProgress(int32& FilesDownloaded, int32& TotalFilesToDownload, float& DownloadPercent, int32& ChunksMounted, int32& TotalChunksToMount, float& MountPercent) const;
  52.  
  53. protected:
  54.  
  55. //Tracks Whether or not our local manifest file is up to date with the one hosted on our website
  56.  
  57. bool bIsDownloadManifestUpToDate;
  58.  
  59. void OnManifestUpdateComplete(bool bSuccess);
  60.  
  61. /** List of Chunk IDs to try and download */
  62.  
  63. UPROPERTY(EditDefaultsOnly, Category = "Patching")
  64.  
  65. TArray<int32> ChunkDownloadList;
  66.  
  67. /** Called when the chunk download process finishes */
  68.  
  69. void OnDownloadComplete(bool bSuccess);
  70.  
  71. /** Called whenever ChunkDownloader's loading mode is finished*/
  72.  
  73. void OnLoadingModeComplete(bool bSuccess);
  74.  
  75. /** Called when ChunkDownloader finishes mounting chunks */
  76.  
  77. void OnMountComplete(bool bSuccess);
  78.  
  79. };
  1. .cpp
  2.  
  3. // Fill out your copyright notice in the Description page of Project Settings.
  4.  
  5. #include "PatchingDemoGameInstance.h"
  6.  
  7. #include "ChunkDownloader.h"
  8.  
  9. #include "Misc/CoreDelegates.h"
  10.  
  11. #include "AssetRegistryModule.h"
  12.  
  13. void UPatchingDemoGameInstance::Init()
  14.  
  15. {
  16.  
  17. Super::Init();
  18.  
  19. const FString DeploymentName = "PatchingDemoLive";
  20.  
  21. const FString ContentBuildId = "PatchingDemoKey";
  22.  
  23. // initialize the chunk downloader
  24.  
  25. TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetOrCreate();
  26.  
  27. // TODO 安卓下载方式
  28.  
  29. // Downloader->Initialize("Android", 8);
  30.  
  31. Downloader->Initialize("Windows", 8);
  32.  
  33. // load the cached build ID
  34.  
  35. Downloader->LoadCachedBuild(DeploymentName);
  36.  
  37. // update the build manifest file
  38.  
  39. TFunction<void(bool bSuccess)> UpdateCompleteCallback = [&](bool bSuccess){bIsDownloadManifestUpToDate = true;};
  40.  
  41. Downloader->UpdateBuild(DeploymentName, ContentBuildId, UpdateCompleteCallback);
  42.  
  43. }
  44.  
  45. void UPatchingDemoGameInstance::Shutdown()
  46.  
  47. {
  48.  
  49. Super::Shutdown();
  50.  
  51. // Shut down ChunkDownloader
  52.  
  53. FChunkDownloader::Shutdown();
  54.  
  55. }
  56.  
  57. void UPatchingDemoGameInstance::OnManifestUpdateComplete(bool bSuccess)
  58.  
  59. {
  60.  
  61. bIsDownloadManifestUpToDate = bSuccess;
  62.  
  63. }
  64.  
  65. void UPatchingDemoGameInstance::GetLoadingProgress(int32& BytesDownloaded, int32& TotalBytesToDownload, float& DownloadPercent, int32& ChunksMounted, int32& TotalChunksToMount, float& MountPercent) const
  66.  
  67. {
  68.  
  69. //Get a reference to ChunkDownloader
  70.  
  71. TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetChecked();
  72.  
  73. //Get the loading stats struct
  74.  
  75. FChunkDownloader::FStats LoadingStats = Downloader->GetLoadingStats();
  76.  
  77. //Get the bytes downloaded and bytes to download
  78.  
  79. BytesDownloaded = LoadingStats.BytesDownloaded;
  80.  
  81. TotalBytesToDownload = LoadingStats.TotalBytesToDownload;
  82.  
  83. //Get the number of chunks mounted and chunks to download
  84.  
  85. ChunksMounted = LoadingStats.ChunksMounted;
  86.  
  87. TotalChunksToMount = LoadingStats.TotalChunksToMount;
  88.  
  89. //Calculate the download and mount percent using the above stats
  90.  
  91. DownloadPercent = ((float)BytesDownloaded / (float)TotalBytesToDownload)*100.0f;
  92.  
  93. MountPercent = ((float)ChunksMounted / (float)TotalChunksToMount)*100.0f;
  94.  
  95. }
  96.  
  97. void UPatchingDemoGameInstance::OnLoadingModeComplete(bool bSuccess)
  98.  
  99. {
  100.  
  101. OnDownloadComplete(bSuccess);
  102.  
  103. }
  104.  
  105. void UPatchingDemoGameInstance::OnMountComplete(bool bSuccess)
  106.  
  107. {
  108.  
  109. OnPatchComplete.Broadcast(bSuccess);
  110.  
  111. }
  112.  
  113. bool UPatchingDemoGameInstance::PatchGame()
  114.  
  115. {
  116.  
  117. // make sure the download manifest is up to date
  118.  
  119. if (bIsDownloadManifestUpToDate)
  120.  
  121. {
  122.  
  123. // get the chunk downloader
  124.  
  125. TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetChecked();
  126.  
  127. // report current chunk status
  128.  
  129. for (int32 ChunkID : ChunkDownloadList)
  130.  
  131. {
  132.  
  133. int32 ChunkStatus = static_cast<int32>(Downloader->GetChunkStatus(ChunkID));
  134.  
  135. UE_LOG(LogTemp, Display, TEXT("Chunk %i status: %i"), ChunkID, ChunkStatus);
  136.  
  137. }
  138.  
  139. TFunction<void(bool bSuccess)> DownloadCompleteCallback = [&](bool bSuccess) {OnDownloadComplete(bSuccess); };
  140.  
  141. Downloader->DownloadChunks(ChunkDownloadList, DownloadCompleteCallback, 1);
  142.  
  143. // start loading mode
  144.  
  145. TFunction<void(bool bSuccess)> LoadingModeCompleteCallback = [&](bool bSuccess) {OnLoadingModeComplete(bSuccess); };
  146.  
  147. Downloader->BeginLoadingMode(LoadingModeCompleteCallback);
  148.  
  149. return true;
  150.  
  151. }
  152.  
  153. // we couldn't contact the server to validate our manifest, so we can't patch
  154.  
  155. UE_LOG(LogTemp, Display, TEXT("Manifest Update Failed. Can't patch the game"));
  156.  
  157. return false;
  158.  
  159. }
  160.  
  161. void UPatchingDemoGameInstance::OnDownloadComplete(bool bSuccess)
  162.  
  163. {
  164.  
  165. if (bSuccess)
  166.  
  167. {
  168.  
  169. UE_LOG(LogTemp, Display, TEXT("Download complete"));
  170.  
  171. // get the chunk downloader
  172.  
  173. TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetChecked();
  174.  
  175. FJsonSerializableArrayInt DownloadedChunks;
  176.  
  177. for (int32 ChunkID : ChunkDownloadList)
  178.  
  179. {
  180.  
  181. DownloadedChunks.Add(ChunkID);
  182.  
  183. }
  184.  
  185. //Mount the chunks
  186.  
  187. TFunction<void(bool bSuccess)> MountCompleteCallback = [&](bool bSuccess) {OnMountComplete(bSuccess); };
  188.  
  189. Downloader->MountChunks(DownloadedChunks, MountCompleteCallback);
  190.  
  191. OnPatchComplete.Broadcast(true);
  192.  
  193. }
  194.  
  195. else
  196.  
  197. {
  198.  
  199. UE_LOG(LogTemp, Display, TEXT("Load process failed"));
  200.  
  201. // call the delegate
  202.  
  203. OnPatchComplete.Broadcast(false);
  204.  
  205. }
  206.  
  207. }

2.使用 PatchingDemoGameInstance 作为基类创建 新蓝图,命名为 CDGameInstance

3.打开CDGameInstance,添加chunk列表

4.创建名为 PatchingGameMode 的新游戏模式 蓝图

5.项目做如下设置。

6.第三人称游戏map设置gamemode为PatchingGameMode

7.打开PatchingGameMode,添加如下蓝图逻辑。

beginPlay后添加:patchGame返回值为true则进入tick即开始下载资源。否则根据资源数进行进一步检测。

tick后添加:大概意思就是资源下载并且装载完打开Test3地图。

到此代码,逻辑都写好了。

第四步:打包测试

1.直接打包。

结果是包文件夹里的Content中的paks文件夹有四个pak文件。删掉ID为1001-1003的pak。

2.运行.exe

结果如下:

下载中

下载完成,3秒后进入Test3地图。

下载的文件:

 
 

UE-自带的HotUpdate【转】的更多相关文章

  1. UE编辑器加载格式化代码插件astyle

    UE 的格式化功能不强,自带的astyle版本陈旧,一般采用开源工具astyle来实现代码格式化. 1. 首先下载最新的astyle,因为ue自带的astyle版本太老,不支持空格.中文名等. 2. ...

  2. 【Tips】【UE】总结自己常用的UltraEdit使用技巧

    如果您问我每天都要打开的软件是什么,那毫无疑问是UltraEdit!作为一位DBA,每天都要写各种脚本,尤其是在对具有超多行行的大文件进行精心编辑时,没有一个好的文本编辑器是不成的.掐指一算,哇塞,自 ...

  3. 【UE】常用的UltraEdit使用技巧

    Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...

  4. Ultraedit中使用Astyle格式化代码

    方法: 使用UE的自定义工具栏并借助开源工具astyle.exe来完成. 1. 首先下载最新的astyle,因为ue自带的astyle版本太老,不支持空格.中文名等. http://astyle.so ...

  5. 常用的UltraEdit使用技巧

    Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为"她"具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个 ...

  6. org.json.JSONException: A JSONObject text must begin with &#39;{&#39; at character 1 of {解决方法

    在使用java读取一个本地的json配置文件的时候,产生了这个异常:org.json.JSONException: A JSONObject text must begin with '{' at c ...

  7. ultraedit 实际应用技巧

    Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...

  8. UltraEdit常用技巧

    Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...

  9. 带交互的 iOS 产品原型可以用什么软件制作?

    摘自知乎http://www.zhihu.com/question/20326729 来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 首先如果你小团队或者个人开发,当然 ...

  10. Unity外包团队:U3D与UE我选哪个好?请别再问这种问题了!

    原本预先决定的两家VR游戏公司采访,思熊和星为棋,并没有发现什么共性之初.结果在采访之后却意外发现,两家的经历有着非常相似的地方.他们都是来自于开发游戏所用的引擎的原开发商,比如思熊的主力来自Epic ...

随机推荐

  1. 通过axios实现数据请求

    vue.js默认没有提供ajax功能的. 所以使用vue的时候,一般都会使用axios的插件来实现ajax与后端服务器的数据交互. 注意,axios本质上就是javascript的ajax封装,所以会 ...

  2. Android OpenMAX(三)高通OMX组件实现基础

    上一节了解了OMX组件实现的基础内容,这一节我们以高通OMX实现为例,简单看看如何实现一个OMX组件.本节代码参考自: omx_core_cmp.cpp qc_omx_component.h omx_ ...

  3. (八十八)c#Winform自定义控件-转子

    官网 http://www.hzhcontrols.com/ 前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kw ...

  4. vue3拉取代码install 报错 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: npm ERR! Found: vue@3.2.31

    先看报错 说明安装的包和现有的包已经冲突了版本不一致 我们先试一下npm install @vue/cli -- force然后再试一下npm install @vue/cli --legacy-pe ...

  5. 使用线程池实现为多个客户端提供Echo服务

    import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Scanner; im ...

  6. 洛谷 P4913 二叉树深度

    题目链接:二叉树深度 思路 存储二叉树的各个节点并递归搜索二叉树深度. 题解 #include <bits/stdc++.h> using namespace std; #define l ...

  7. transformer原理

    Transformer注意力架构原理 输入层 embedding词嵌入向量 将文本中词汇的数字表示转变为向量表示,在这样的高维空间捕捉词汇间的关系 语义相近的词语对应的向量位置也更相近 每个词先通过词 ...

  8. 使用 GPU 进行 Lightmap 烘焙 - 简单 demo

    作者:i_dovelemon 日期:2024-06-16 主题:Lightmap, PathTracer, Compute Shader 引言 一直以来,我都对离线 bake lightmap 操作很 ...

  9. Sql Server中Cross Apply关键字的使用

    Sql Server中Cross Apply关键字的使用 前言 在写一个业务的时候,有1列数据如下: 车牌号 湘A00001/湘G00001 湘A00002/湘G00002 湘A00003/湘G000 ...

  10. Linux 内核:设备驱动模型 学习总结

    背景 其实之前就转载过别人针对Linux的设备驱动模型(Linux Device Driver Model,LDDM)的文章,但是受限于自身的能力,因此花了点时间重新学习了一下. 前人写的文章很好,我 ...