03/14/2020

文章目录

  • Cook 单个资源
    • 控制台命令
    • 注意事项
  • 补充
    • 烘培整个(UE4Editor.exe)
    • 烘培地图
    • 简化单个资源烘培
  • 总结
  • 参考资料

Cook 单个资源

HotPatcher有一个函数叫做OnCookPlatform函数,需要资源名字和烘培平台就可以烘培资源了。简单把这个函数提取出来,我这边使用的是控制台来烘焙鼠标选中Content面板中的资源。

控制台命令

传递烘培资源的平台,然后创建烘培的路径和开始烘培,最后完成烘培结果的显示。

  • GetCookedAssetDir():获取烘培路径
  • CookPackage():烘培函数,即生成文件
  • CreateSaveFileNotify():完成烘培结果显示
// Cheat command to load all assets of a given type
static FAutoConsoleCommand CookChoosedAssets(TEXT("CookChoosedAssets"),TEXT("Cook Choosed Assets in the Content Broweser"),FConsoleCommandWithArgsDelegate::CreateStatic([](const TArray<FString>& Platforms){//Cook A single asset//1. Get Asset Path + Name  on the ContentBrowserFContentBrowserModule& ContentBrowserModule = FModuleManager::Get().LoadModuleChecked<FContentBrowserModule>(TEXT("ContentBrowser"));TArray<FAssetData> AssetsData;ContentBrowserModule.Get().GetSelectedAssets(AssetsData);if (AssetsData.Num() == 0){UE_LOG(LogTemp, Warning, TEXT("Plase Choose assets"));return;}TArray<UPackage*> AssetsPackage;for (const auto& AssetData : AssetsData){AssetsPackage.AddUnique(AssetData.GetPackage());}for (auto CurrentPlatform : Platforms){//Create folder and Cook assetsFString CookedDir = FPaths::ConvertRelativePathToFull(FPaths::Combine(FPaths::ProjectSavedDir(), TEXT("Cooked")));for (const auto& AssetPacakge : AssetsPackage){FString CookedSavePath = GetCookAssetsSaveDir(CookedDir, AssetPacakge, CurrentPlatform);//Start Cook Assetsbool bCookStatus = CookPackage(AssetPacakge, Platforms, CookedDir);auto Msg = FText::Format(LOCTEXT("CookAssetsNotify", "Cook Platform {1} for {0} {2}!"),UKismetTextLibrary::Conv_StringToText(AssetPacakge->FileName.ToString()),UKismetTextLibrary::Conv_StringToText(CurrentPlatform),bCookStatus ? UKismetTextLibrary::Conv_StringToText(TEXT("Successfuly")) : UKismetTextLibrary::Conv_StringToText(TEXT("Faild")));SNotificationItem::ECompletionState CookStatus = bCookStatus ? SNotificationItem::ECompletionState::CS_Success : SNotificationItem::ECompletionState::CS_Fail;CreateSaveFileNotify(Msg, CookedSavePath, CookStatus);UE_LOG(LogTemp, Warning, TEXT("Cook Single Assets, %s"), bCookStatus?TEXT("True"):TEXT("False"));}}UE_LOG(LogTemp, Warning, TEXT("Finish Cook Single Assets"));}), ECVF_Default);
  1. 学会使用ContentBrowser模块获取选中的资源并保存路径
  2. 认识FAssetData和UPackage类
  3. UPackage 和EditorEngine 都有一个Save函数
// Copyright Epic Games, Inc. All Rights Reserved.
#include "HAL/IConsoleManager.h"
#include "ContentBrowserModule.h"
#include "IContentBrowserSingleton.h"
#include "UObject/Package.h"
#include "IPlatformFileSandboxWrapper.h"
#include "Interfaces/IPluginManager.h"
#include "Misc/SecureHash.h"
#include "Kismet/KismetTextLibrary.h"
#include "Widgets/Notifications/SNotificationList.h"
#include "Framework/Notifications/NotificationManager.h"
#include "Interfaces/ITargetPlatformManagerModule.h"
#include "Interfaces/ITargetPlatform.h"#include "IPlatformFileSandboxWrapper.h"
#include "Misc/SecureHash.h"#include "Editor.h"#define LOCTEXT_NAMESPACE "EditorCommand"static FString ConvertToFullSandboxPath(const FString& FileName, bool bForWrite)
{FString ProjectContentAbsir = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir());if (FileName.StartsWith(ProjectContentAbsir)){FString GameFileName = FileName;GameFileName.RemoveFromStart(ProjectContentAbsir);return FPaths::Combine(FApp::GetProjectName(), TEXT("Content"), GameFileName);}if (FileName.StartsWith(FPaths::EngineContentDir())){FString EngineFileName = FileName;EngineFileName.RemoveFromStart(FPaths::EngineContentDir());return FPaths::Combine(TEXT("Engine/Content"), EngineFileName);;}TArray<TSharedRef<IPlugin> > PluginsToRemap = IPluginManager::Get().GetEnabledPlugins();// Ideally this would be in the Sandbox File but it can't access the project or pluginif (PluginsToRemap.Num() > 0){// Handle remapping of pluginsfor (TSharedRef<IPlugin> Plugin : PluginsToRemap){FString PluginContentDir;if (FPaths::IsRelative(FileName))PluginContentDir = Plugin->GetContentDir();elsePluginContentDir = FPaths::ConvertRelativePathToFull(Plugin->GetContentDir());// UE_LOG(LogHotPatcherEditorHelper,Log,TEXT("Plugin Content:%s"),*PluginContentDir);if (FileName.StartsWith(PluginContentDir)){FString SearchFor;SearchFor /= Plugin->GetName() / TEXT("Content");int32 FoundAt = FileName.Find(SearchFor, ESearchCase::IgnoreCase, ESearchDir::FromEnd);check(FoundAt != -1);// Strip off everything but <PluginName/Content/<remaing path to file>FString SnippedOffPath = FileName.RightChop(FoundAt);FString LoadingFrom;switch (Plugin->GetLoadedFrom()){case EPluginLoadedFrom::Engine:{LoadingFrom = TEXT("Engine/Plugins");break;}case EPluginLoadedFrom::Project:{LoadingFrom = FPaths::Combine(FApp::GetProjectName(), TEXT("Plugins"));break;}}return FPaths::Combine(LoadingFrom, SnippedOffPath);}}}return TEXT("");
}static FString GetCookAssetsSaveDir(const FString& BaseDir, UPackage* Package, const FString& Platform)
{FString Filename;FString PackageFilename;FString StandardFilename;FName StandardFileFName = NAME_None;//Content folderif (FPackageName::DoesPackageExist(Package->FileName.ToString(), NULL, &Filename, false)){StandardFilename = PackageFilename = FPaths::ConvertRelativePathToFull(Filename);FPaths::MakeStandardFilename(StandardFilename);StandardFileFName = FName(*StandardFilename);}//MakeSure Engine or Project or Plugin ContentsFString SandboxFilename = ConvertToFullSandboxPath(*StandardFilename, true);// UE_LOG(LogHotPatcherEditorHelper,Log,TEXT("Filename:%s,PackageFileName:%s,StandardFileName:%s"),*Filename,*PackageFilename,*StandardFilename);FString CookDir = FPaths::Combine(BaseDir, Platform, SandboxFilename);return  CookDir;
}static bool CookPackage(UPackage* Package, const TArray<FString>& Platforms, const FString& SavePath)
{bool bSuccessed = false;const bool bSaveConcurrent = FParse::Param(FCommandLine::Get(), TEXT("ConcurrentSave"));bool bUnversioned = false;uint32 SaveFlags = SAVE_KeepGUID | SAVE_Async | SAVE_ComputeHash | (bUnversioned ? SAVE_Unversioned : 0);EObjectFlags CookedFlags = RF_Public;if (Cast<UWorld>(Package)){CookedFlags = RF_NoFlags;}if (bSaveConcurrent){SaveFlags |= SAVE_Concurrent;}ITargetPlatformManagerModule& TPM = GetTargetPlatformManagerRef();const TArray<ITargetPlatform*>& TargetPlatforms = TPM.GetTargetPlatforms();TArray<ITargetPlatform*> CookPlatforms;for (ITargetPlatform* TargetPlatform : TargetPlatforms){if (Platforms.Contains(TargetPlatform->PlatformName())){CookPlatforms.AddUnique(TargetPlatform);}}if (Package->FileName.IsNone())return bSuccessed;for (auto& Platform : CookPlatforms){struct FFilterEditorOnlyFlag{FFilterEditorOnlyFlag(UPackage* InPackage, ITargetPlatform* InPlatform){Package = InPackage;Platform = InPlatform;if (!Platform->HasEditorOnlyData()){Package->SetPackageFlags(PKG_FilterEditorOnly);}else{Package->ClearPackageFlags(PKG_FilterEditorOnly);}}~FFilterEditorOnlyFlag(){if (!Platform->HasEditorOnlyData()){Package->ClearPackageFlags(PKG_FilterEditorOnly);}}UPackage* Package;ITargetPlatform* Platform;};FFilterEditorOnlyFlag SetPackageEditorOnlyFlag(Package, Platform);FString CookedSavePath = GetCookAssetsSaveDir(SavePath, Package, Platform->PlatformName());// delete old cooked assetsif (FPaths::FileExists(CookedSavePath)){IFileManager::Get().Delete(*CookedSavePath);}// UE_LOG(LogHotPatcherEditorHelper,Log,TEXT("Cook Assets:%s"),*Package->GetName());Package->FullyLoad();TArray<UObject*> ExportMap;GetObjectsWithOuter(Package, ExportMap);for (const auto& ExportObj : ExportMap){ExportObj->BeginCacheForCookedPlatformData(Platform);}GIsCookerLoadingPackage = true;//UE_LOG(LogTemp, Warning, TEXT("Cook Assets:%s save to %s"), *Package->GetName(), *CookedSavePath);FSavePackageResultStruct Result = GEditor->Save(Package, nullptr, CookedFlags, *CookedSavePath,GError, nullptr, false, false, SaveFlags, Platform,FDateTime::MinValue(), false, /*DiffMap*/ nullptr);GIsCookerLoadingPackage = false;bSuccessed = Result == ESavePackageResult::Success;}return bSuccessed;
}void CreateSaveFileNotify(const FText& InMsg, const FString& InSavedFile, SNotificationItem::ECompletionState NotifyType)
{auto Message = InMsg;FNotificationInfo Info(Message);Info.bFireAndForget = true;Info.ExpireDuration = 5.0f;Info.bUseSuccessFailIcons = false;Info.bUseLargeFont = false;const FString HyperLinkText = InSavedFile;Info.Hyperlink = FSimpleDelegate::CreateLambda([](FString SourceFilePath){FPlatformProcess::ExploreFolder(*SourceFilePath);},HyperLinkText);Info.HyperlinkText = FText::FromString(HyperLinkText);FSlateNotificationManager::Get().AddNotification(Info)->SetCompletionState(NotifyType);
}

注意事项

如何引用库文件和改写Build.cs

// Copyright Epic Games, Inc. All Rights Reserved.using UnrealBuildTool;public class TestPython : ModuleRules
{public TestPython(ReadOnlyTargetRules Target) : base(Target){PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore","ContentBrowser","SandboxFile","TargetPlatform"});PrivateDependencyModuleNames.AddRange(new string[]{"Projects","UnrealEd","Engine","Slate","SlateCore","RenderCore"// ... add private dependencies that you statically link with here ...    });}
}

补充

烘培整个(UE4Editor.exe)

查看MainFrameActions.cpp::CookContent函数

D:\UE4\UE_4.25\Engine\Binaries\Win64\UE4Editor-Cmd.exe D:\unrealEngin4WorkStation\TestPython\TestPython.uproject -run=Cook  -TargetPlatform=WindowsNoEditor

烘培地图

UE4Editor.exe <GameName or uproject> -run=cook -targetplatform=<Plat1>+<Plat2> [-cookonthefly] [-iterate] [-map=<Map1>+<Map2>]
or
UE4Editor-Cmd.exe <GameName> -run=cook -targetplatform=<Plat1>+<Plat2> [-cookonthefly] [-iterate] [-map=<Map1>+<Map2>]

简化单个资源烘培


bool SaveToCookAsset(UPackage * InPackage, const FString & InSavePath)
{ITargetPlatformManagerModule& TPM = GetTargetPlatformManagerRef();const TArray<ITargetPlatform*>& TargetPlatforms = TPM.GetTargetPlatforms();ITargetPlatform* Target = nullptr;for (ITargetPlatform *TargetPlatform : TargetPlatforms){if (TargetPlatform->PlatformName() == "WindowsNoEditor"){Target = TargetPlatform;break;}}InPackage->SetPackageFlags(PKG_FilterEditorOnly);uint32 saveFlags = SAVE_KeepGUID | SAVE_Async | SAVE_Unversioned;FSavePackageResultStruct Result = GEditor->Save(InPackage, nullptr, RF_Public, *InSavePath, GError, NULL, false, false, saveFlags, Target, FDateTime::MinValue(), false);return Result == ESavePackageResult::Success;

简单使用GEditor->Save()函数来烘培资源

总结

这次烘培仅仅只能在Editor打开的时候才能使用。

参考资料

  1. 简化烘培
  2. UE4官网烘培

UE4 C++(21):Cook单个资源相关推荐

  1. 一种自动将3DMax模型转换为UE4直接可用的模型资源的方法与流程

    本发明涉及一种自动将3D Max模型转换为UE4直接可用的模型资源的方法. 背景技术: 现有技术中大部分3D模型的建模工作主要由美术师在3d Max上进行.而由于使用模型的游戏引擎采取各自的模型标准, ...

  2. assetbundle能不能删除_Addressable卸载单个资源的疑问

    1)Addressable卸载单个资源的疑问 ​2)如何判断硬件支持GPU Instance 3)StringBuilder反射实现String报错 4)Unity 2018 RequireES3.1 ...

  3. UE4中修改模型mesh资源的枢轴坐标原点位置

    UE4中修改模型mesh资源的枢轴坐标原点位置 问题阐述: 对于在UE4中自定义的mesh资源导出保存后以备未来使用,但在未来使用的时候却发现模型的坐标原点不满足需求而无法使用的想法,本篇博客将用两种 ...

  4. ue4风格化材质_ue4商城资源Stylized Terrain Pack of 50 Materials50种材质风格化地形包

    Unreal Engine虚幻游戏引擎素材资源 Unreal Engine Marketplace –Stylized Terrain Pack of 50 Materials风格化地形包,50种材质 ...

  5. UE4源码加密及资源加密

    虚幻引擎4是由游戏开发者为开发游戏而制作的.完整的游戏开发工具套件.从二维的移动平台游戏到主机平台的大作,虚幻引擎是一个纯C++引擎,专为高性能而设计.它先进CPU/GPU性能分析工具和灵活的渲染器能 ...

  6. UE4如何将虚幻商城资源导入到自己的工程中+保管库的使用

    一.目的: 1.导入资源到UE4工程里面很多,下面介绍一个 一.参考 1.Unreal初级案例-动作游戏入门中-保管库的使用 http://www.sikiedu.com/course/514/tas ...

  7. (UE4 4.21 ) UE4给编辑器添加菜单栏(Menu),工具栏(TooBar),Tab窗口

    前言 在UE4中存在大量的菜单栏和工具栏.如下面所示 本质上上面都是菜单栏和工具栏. 菜单(Menu)的扩展点(ExtendPoints) 在Edit->Editor Preferences-& ...

  8. 【Altium Designer 21】单个元器件更新对应PCB封装

    主题:目前C16的封装为1206,打算换为1210 一. 初始状态: 初始原理图局部C16: 初始C16封装: 初始C16的PCB: 二. 更新状态: 更新后原理图局部C16(没动): 但我们调整了属 ...

  9. UE4资源热更打包工具HotPatcher

    UE4资源热更打包工具HotPatcher https://imzlp.me/posts/17590/ Z's Blog 首页 归档 分类 标签 笔记 微言 资源 简历 关于 待办事项 站点日志 搜索 ...

最新文章

  1. 【Git】git系统学习(一):常用指令
  2. jmeter获取时间_time 函数
  3. poj 2482 Stars in Your Window(线段树+离散化+线扫描)
  4. c语言综合性实验数字益智游戏排行榜,C语言综合性实验报告1.doc
  5. win10打开本机telnet客户端
  6. python做项目看板_三、使用python数据仓库实现可视化看板
  7. Elasticsearch 单机安装
  8. 微店的Flutter混合开发组件化与工程化架构
  9. GB/T 36964-2018《软件工程 软件开发成本度量规范》国家标准正式发布...
  10. 好看的字体:华康流风体
  11. 一个完整的产品设计都要哪些设计流程
  12. python职位要求_python 开发工程师职位描述与岗位职责任职要求
  13. 移动端pc端兼容element-ui
  14. 【转】如何评价 Apple 新推出的编程语言 Swift?
  15. 【安卓USB开发】让手机与物联网设备鹊桥相会
  16. 大多数人都会遇到的几个H5坑(实战)
  17. 什么是上下变频器?以及对5G应用的作用
  18. 打成jar包 在命令行下执行java工程
  19. 一些应急响应教学视频笔记
  20. 金丝桃素白蛋白纳米粒-大肠杆菌血清抗体复合物|凝血因子Ⅷ人血清白蛋白HSA纳米粒|地奥司明人血清白蛋白纳米粒

热门文章

  1. 文科生学python系列_文科生学Python系列15:泰坦尼克数据1
  2. Datawhale六月学习数据分析打卡task2
  3. Git Your branch and 'origin/master' have diverged
  4. 2012年半程盘点之最佳iPad应用
  5. Scala基础(一)——常用数据类型
  6. 产品经理的互联网思维(三)
  7. 2008年DIY配台电脑
  8. Mac 清除本地DNS缓存
  9. 《戏说大前端》第一章-键盘上的梦想
  10. 实验七 路由器的基本配置