原文链接: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.

  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

最后代码为:

// 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【转】的更多相关文章

  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. powerpoint 无法打开文件

    PowerPoint 无法打开文件 出现的问题 今天下载老师放在学习通的ppt,居然不能打开,记录一下 点击修复后出现: 这并不是文件损坏了,而是powerpoint出于安全的考虑,为了保护我们的计算 ...

  2. c#笔记(3) 委托回调

    委托回调是刚接触c#时最头疼的东西,老看老忘,遂整理一下现在对委托回调的理解.如有错误,请指出,感谢. 委托 C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针.委托是存有对某个方 ...

  3. jquery的循环 tab切换

        <ul>         <li>1</li>         <li>2</li>         <li>3< ...

  4. minos 2.3 中断虚拟化——GICv2 管理

    首发公号:Rand_cs 硬件肯定需要软件配合,这一节就来实战 GICv2 首先准备好 GICv2 手册:https://developer.arm.com/documentation/ihi0048 ...

  5. python 如何判断一组数呈上升还是下降趋势

    1. python 判断一组数呈上升还是下降趋势的方法 要判断一组数(数列)是呈上升趋势.下降趋势还是无明显趋势,我们可以比较数列中相邻元素的差值.如果大部分差值都是正数,则数列呈上升趋势:如果大部分 ...

  6. Mysql性能优化(详解)

    引言 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情.当我们去设计数据库表结构,对操 ...

  7. #PowerBi Superchange PowerBi 开篇(1)

    本书由B站京西漫步老师推荐,并提供了相应的学习资源,有同感兴趣的朋友,可以加我好友免费分享资源. 本书主要以总结笔记,原文+译文+部分案例实操为主. 预计更新时间为23年6月-23年7月. 本系列笔记 ...

  8. iOS开发之弹窗管理

    前言 "千淘万漉虽辛苦,吹尽狂沙始到金."在这快速变化的互联网行业,身边的朋友有的选择了勇敢创业,有的则在技术的海洋中默默耕耘.时常在深夜反思,作为一个开发者,我们的价值何在?答案 ...

  9. DPO: Direct Preference Optimization 直接偏好优化(学习笔记)

    学习参考:链接1   一.为什么要提出DPO 在之前,我们已经了解到基于人类反馈的强化学习RLHF分为三个阶段:全监督微调(SFT).奖励模型(RM).强化学习(PPO).但是RLHF面临缺陷:RLH ...

  10. 基于 JuiceFS 构建高校 AI 存储方案:高并发、系统稳定、运维简单

    中山大学的 iSEE 实验室(Intelligence Science and System) Lab)在进行深度学习任务时,需要处理大量小文件读取.在高并发读写场景下,原先使用的 NFS 性能较低, ...