UE-自带的HotUpdate【转】
原文链接:https://baijiahao.baidu.com/s?id=1745200406976270792&wfr=spider&for=pc
这是百度可以直接搜索到的
UE4官网针对热更新有较为详细的步骤,但是其中漏掉的几个问题导致实现不了效果。
总的来说可以分为四大步。
第一步:自己的项目设置好插件ChunkDownloader
1.新建第三人称c++项目工程,设置分块打包

2.勾选插件ChunkDownloader

3.修改项目的 Build.cs 文件
PrivateDependencyModuleNames.AddRange(
new string[]{ "ChunkDownloader"}

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

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

添加资源分块标签。

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

属性解释:

依次对自己的测试资源添加标签。
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。
最后代码为:
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "PatchingDemoGameInstance.generated.h"
/**
*
*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPatchCompleteDelegate, bool, Succeeded);
UCLASS()
class UPatchingDemoGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
/** Overrides */
virtual void Init() override;
virtual void Shutdown() override;
/** Delegates */
/** Fired when the patching process succeeds or fails */
UPROPERTY(BlueprintAssignable, Category = "Patching")
FPatchCompleteDelegate OnPatchComplete;
/** Starts the game patching process. Returns false if the patching manifest is not up to date. */
UFUNCTION(BlueprintCallable, Category = "Patching")
bool PatchGame();
UFUNCTION(BlueprintPure, Category = "Patching|Stats")
void GetLoadingProgress(int32& FilesDownloaded, int32& TotalFilesToDownload, float& DownloadPercent, int32& ChunksMounted, int32& TotalChunksToMount, float& MountPercent) const;
protected:
//Tracks Whether or not our local manifest file is up to date with the one hosted on our website
bool bIsDownloadManifestUpToDate;
void OnManifestUpdateComplete(bool bSuccess);
/** List of Chunk IDs to try and download */
UPROPERTY(EditDefaultsOnly, Category = "Patching")
TArray<int32> ChunkDownloadList;
/** Called when the chunk download process finishes */
void OnDownloadComplete(bool bSuccess);
/** Called whenever ChunkDownloader's loading mode is finished*/
void OnLoadingModeComplete(bool bSuccess);
/** Called when ChunkDownloader finishes mounting chunks */
void OnMountComplete(bool bSuccess);
};
.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "PatchingDemoGameInstance.h"
#include "ChunkDownloader.h"
#include "Misc/CoreDelegates.h"
#include "AssetRegistryModule.h"
void UPatchingDemoGameInstance::Init()
{
Super::Init();
const FString DeploymentName = "PatchingDemoLive";
const FString ContentBuildId = "PatchingDemoKey";
// initialize the chunk downloader
TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetOrCreate();
// TODO 安卓下载方式
// Downloader->Initialize("Android", 8);
Downloader->Initialize("Windows", 8);
// load the cached build ID
Downloader->LoadCachedBuild(DeploymentName);
// update the build manifest file
TFunction<void(bool bSuccess)> UpdateCompleteCallback = [&](bool bSuccess){bIsDownloadManifestUpToDate = true;};
Downloader->UpdateBuild(DeploymentName, ContentBuildId, UpdateCompleteCallback);
}
void UPatchingDemoGameInstance::Shutdown()
{
Super::Shutdown();
// Shut down ChunkDownloader
FChunkDownloader::Shutdown();
}
void UPatchingDemoGameInstance::OnManifestUpdateComplete(bool bSuccess)
{
bIsDownloadManifestUpToDate = bSuccess;
}
void UPatchingDemoGameInstance::GetLoadingProgress(int32& BytesDownloaded, int32& TotalBytesToDownload, float& DownloadPercent, int32& ChunksMounted, int32& TotalChunksToMount, float& MountPercent) const
{
//Get a reference to ChunkDownloader
TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetChecked();
//Get the loading stats struct
FChunkDownloader::FStats LoadingStats = Downloader->GetLoadingStats();
//Get the bytes downloaded and bytes to download
BytesDownloaded = LoadingStats.BytesDownloaded;
TotalBytesToDownload = LoadingStats.TotalBytesToDownload;
//Get the number of chunks mounted and chunks to download
ChunksMounted = LoadingStats.ChunksMounted;
TotalChunksToMount = LoadingStats.TotalChunksToMount;
//Calculate the download and mount percent using the above stats
DownloadPercent = ((float)BytesDownloaded / (float)TotalBytesToDownload)*100.0f;
MountPercent = ((float)ChunksMounted / (float)TotalChunksToMount)*100.0f;
}
void UPatchingDemoGameInstance::OnLoadingModeComplete(bool bSuccess)
{
OnDownloadComplete(bSuccess);
}
void UPatchingDemoGameInstance::OnMountComplete(bool bSuccess)
{
OnPatchComplete.Broadcast(bSuccess);
}
bool UPatchingDemoGameInstance::PatchGame()
{
// make sure the download manifest is up to date
if (bIsDownloadManifestUpToDate)
{
// get the chunk downloader
TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetChecked();
// report current chunk status
for (int32 ChunkID : ChunkDownloadList)
{
int32 ChunkStatus = static_cast<int32>(Downloader->GetChunkStatus(ChunkID));
UE_LOG(LogTemp, Display, TEXT("Chunk %i status: %i"), ChunkID, ChunkStatus);
}
TFunction<void(bool bSuccess)> DownloadCompleteCallback = [&](bool bSuccess) {OnDownloadComplete(bSuccess); };
Downloader->DownloadChunks(ChunkDownloadList, DownloadCompleteCallback, 1);
// start loading mode
TFunction<void(bool bSuccess)> LoadingModeCompleteCallback = [&](bool bSuccess) {OnLoadingModeComplete(bSuccess); };
Downloader->BeginLoadingMode(LoadingModeCompleteCallback);
return true;
}
// we couldn't contact the server to validate our manifest, so we can't patch
UE_LOG(LogTemp, Display, TEXT("Manifest Update Failed. Can't patch the game"));
return false;
}
void UPatchingDemoGameInstance::OnDownloadComplete(bool bSuccess)
{
if (bSuccess)
{
UE_LOG(LogTemp, Display, TEXT("Download complete"));
// get the chunk downloader
TSharedRef<FChunkDownloader> Downloader = FChunkDownloader::GetChecked();
FJsonSerializableArrayInt DownloadedChunks;
for (int32 ChunkID : ChunkDownloadList)
{
DownloadedChunks.Add(ChunkID);
}
//Mount the chunks
TFunction<void(bool bSuccess)> MountCompleteCallback = [&](bool bSuccess) {OnMountComplete(bSuccess); };
Downloader->MountChunks(DownloadedChunks, MountCompleteCallback);
OnPatchComplete.Broadcast(true);
}
else
{
UE_LOG(LogTemp, Display, TEXT("Load process failed"));
// call the delegate
OnPatchComplete.Broadcast(false);
}
}
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【转】的更多相关文章
- UE编辑器加载格式化代码插件astyle
UE 的格式化功能不强,自带的astyle版本陈旧,一般采用开源工具astyle来实现代码格式化. 1. 首先下载最新的astyle,因为ue自带的astyle版本太老,不支持空格.中文名等. 2. ...
- 【Tips】【UE】总结自己常用的UltraEdit使用技巧
如果您问我每天都要打开的软件是什么,那毫无疑问是UltraEdit!作为一位DBA,每天都要写各种脚本,尤其是在对具有超多行行的大文件进行精心编辑时,没有一个好的文本编辑器是不成的.掐指一算,哇塞,自 ...
- 【UE】常用的UltraEdit使用技巧
Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...
- Ultraedit中使用Astyle格式化代码
方法: 使用UE的自定义工具栏并借助开源工具astyle.exe来完成. 1. 首先下载最新的astyle,因为ue自带的astyle版本太老,不支持空格.中文名等. http://astyle.so ...
- 常用的UltraEdit使用技巧
Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为"她"具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个 ...
- org.json.JSONException: A JSONObject text must begin with '{' at character 1 of {解决方法
在使用java读取一个本地的json配置文件的时候,产生了这个异常:org.json.JSONException: A JSONObject text must begin with '{' at c ...
- ultraedit 实际应用技巧
Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...
- UltraEdit常用技巧
Tip 1: Alt+C 列模式可以说最初选择使用这个文本编辑软件,原因很简单,就是因为“她”具有列编辑模式.如果您还不知道什么是列编辑模式的话,我想您应该好好研究一下啦.这是一个超级“赞”的功能.在 ...
- 带交互的 iOS 产品原型可以用什么软件制作?
摘自知乎http://www.zhihu.com/question/20326729 来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 首先如果你小团队或者个人开发,当然 ...
- Unity外包团队:U3D与UE我选哪个好?请别再问这种问题了!
原本预先决定的两家VR游戏公司采访,思熊和星为棋,并没有发现什么共性之初.结果在采访之后却意外发现,两家的经历有着非常相似的地方.他们都是来自于开发游戏所用的引擎的原开发商,比如思熊的主力来自Epic ...
随机推荐
- vue-cli3 项目路由 history 模式部署到 nginx 服务器
1.项目修改vue.config.js增加 publicPath: '/' 2.nginx配置 location / {#访问前端页面 root /data/dist;#vue项目存放路径 index ...
- NSInvocation 返回值在ARC下面的释放问题
一.先看下面的代码 -(NSArray *) operationFromTakeoffAction:(NSString *) action AtPoint:(CGPoint) flightPoint ...
- iOS面试题详解-开篇
一.前言 转眼之前,已经毕业5年,从事iOS开发5年.5年的时间说长不长,却把我从刚毕业的毛头小伙子变成了现在的"中年大叔",不仅仅是外表还有心态. 一方面不愿意接收自己形体的改变 ...
- NOIP模拟59
T1 柱状图 解题思路 二分答案+线段树check 显然对于最后的限制,我们希望向上移的和向下移的柱子数尽量接近. 因此枚举每一个柱子当做最高的一个的时刻,二分找到一个当前最优解更新答案. 开两棵线段 ...
- Opencv笔记(11)随机数发生器cv::RNG
一个随机数对象(RNG)用来产生随机数的伪随机序列.这样做的好处是你可以方便地得到多重伪随机数流.一旦随机数发生器创建,就会开始按需提供产生随机数的"服务",无论是平均分布还是正态 ...
- itest work 开源接口测试&敏捷测试管理平台 9.5.0 GA_u3,优化及修复关键 BUG
(一)itest work 简介 itest work (爱测试) 一站式工作站让测试变得简单.敏捷,"好用.好看,好敏捷" ,是itest wrok 追求的目标.itest w ...
- 开源一站式敏捷测试管理平台 itest(爱测试) 6.6.1 发布,安全升级及新增强
(一)itest 简介及更新说明 itest 开源敏捷测试管理,testOps 践行者,极简的任务管理,测试管理,缺陷管理,测试环境管理,接口测试5合1,又有丰富的统计分析.可按测试包分配测试用例执行 ...
- Java中将jsonArray导出为Excel
java中使用jxl导出excel时,需指定WritableSheet对象中对应于每个单元格的数据.List类型是一种常用的数据类型,它里面的元素是实体对象,当将它创建为WritableShe ...
- linux Centos8系统,防火墙配置常用命令,systemctl 和firewall
本文环境:Linux系统CentOS 8.2 64bit CentOS 7版本及以上版本较centos 6有较大改动,例如:采用systemctl命令来开启service,它是服务管理中主要的工具,融 ...
- INFINI Labs 产品更新 | 修复 Easysearch 跨集群复制索引同步问题,Gateway 内存异常增长等问题
INFINI Labs 产品又更新啦~,本次更新主要对 Easysearch.Gateway.Console.Agent 等产品功能进行优化和相关 Bug 修复,解决了内存异常增长等问题,以下是详细说 ...