看完能得到什么?

对自定义的资源进行导出、导入、覆盖

展示效果如下

导出,可以看到桌面上多了一个以simpAnim为后缀的文件

unreal打包h5 unreal document_c++

导入,导入我们上面导出的文件,可以看到导入后里面的数值还是18

unreal打包h5 unreal document_自定义_02

覆盖,我们将原来的文件里面的Value修改,并将第一个gif导出的文件拖进来,可以看到文件的Value又变成18了

unreal打包h5 unreal document_c++_03

1、导出

#pragma once

#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Exporters/Exporter.h"
#include "SimpleAnimationAssetExporter.generated.h"

UCLASS()
class USimpleAnimationAssetExporter : public UExporter
{
	GENERATED_UCLASS_BODY()

	virtual bool SupportsObject(UObject* Object) const override;
	virtual bool ExportBinary(UObject* Object, const TCHAR* Type, FArchive& Ar, FFeedbackContext* Warn, int32 FileIndex = 0, uint32 PortFlags = 0) override;
};

我们需要继承 UExporter,并且重写上述两个方法,上述两个方法分别代表:
SupportsObject: 支持导出的对象
ExportBinary: 导出对象保存的数据形式(或者说把数据保存成什么样)

#include "SimpleAnimationAssetExporter.h"
#include "SimpleAnimationAsset.h"

USimpleAnimationAssetExporter::USimpleAnimationAssetExporter(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	SupportedClass = USimpleAnimationAsset::StaticClass();
	PreferredFormatIndex = 0;
	FormatExtension.Add(TEXT("simpAnim"));
	FormatDescription.Add(TEXT("Simple Animation Asset"));
}

bool USimpleAnimationAssetExporter::SupportsObject(UObject* Object) const
{
	bool bSupportsObject = false;
	if (Super::SupportsObject(Object))
	{
		bSupportsObject = IsValid(Cast<USimpleAnimationAsset>(Object));
	}
	return bSupportsObject;
}

bool USimpleAnimationAssetExporter::ExportBinary(UObject* Object, const TCHAR* Type, FArchive& Ar, FFeedbackContext* Warn, int32 FileIndex, uint32 PortFlags)
{
	USimpleAnimationAsset* Asset = CastChecked<USimpleAnimationAsset>(Object);

	if (!IsValid(Asset))
	{
		return false;
	}
	Ar << Asset->IntValue;
	return true;
}

需要注意的是,在构造函数中,我们要定义 “导出所支持的资源类型”,也就是SupportedClass ,后面几个参数分别代表:
1、使用下面定义的后缀、文件说明的优先级索引
2、文件后缀
3、文件说明
后缀和说明如下面“保存类型里”所示,
在ExportBinary函数中,简单的将IntValue的值以字节的形式保存到文件中,所以你会看到 str其实是不会保存的也就无法加载 哈哈哈哈

unreal打包h5 unreal document_#include_04

2、导入

#include "CoreMinimal.h"
#include "Factories/Factory.h"
#include "SimpleAnimationAssetFactoryImport.generated.h"

UCLASS()
class USimpleAnimationAssetFactoryImport : public UFactory
{
	GENERATED_UCLASS_BODY()
public:
	virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent,
		FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms,
		FFeedbackContext* Warn, bool& bOutOperationCanceled) override;
};

导入相当于利用重新创建一个新的资源,因此和我们最开始定义的创建新资源一样继承自 “UFactory”,我们需要重写其FactoryCreateFile,用于导入的时候创建对应的UE内资源

#pragma once

#include "SimpleAnimationAssetFactoryImport.h"
#include "SimpleAnimationAsset.h"
#include "Containers/UnrealString.h"
#include "Misc/FileHelper.h"

USimpleAnimationAssetFactoryImport::USimpleAnimationAssetFactoryImport(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	Formats.Add(FString(TEXT("simpAnim;")));
	SupportedClass = USimpleAnimationAsset::StaticClass();
	bCreateNew = false;
	bEditorImport = true;
}

UObject* USimpleAnimationAssetFactoryImport::FactoryCreateFile(UClass* InClass, UObject* InParent,
	FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms,
	FFeedbackContext* Warn, bool& bOutOperationCanceled)
{
	USimpleAnimationAsset* SimpleAnimationAsset = nullptr;
	TArray<uint8> Bytes;

	if (FFileHelper::LoadFileToArray(Bytes, *Filename) && Bytes.Num() >= sizeof(int32))
	{
		SimpleAnimationAsset = NewObject<USimpleAnimationAsset>(InParent, InClass, InName, Flags);
		for (uint32 i = 0; i < sizeof(int32); ++i) {
			SimpleAnimationAsset->IntValue |= Bytes[i] << (i * 8);
		}
	}

	bOutOperationCanceled = false;

	return SimpleAnimationAsset;
}

需要注意的是,在构造函数中,我们要定义 “导入所支持的资源类型”,也就是SupportedClass ,其他几个参数分别代表:
1、支持的文件后缀(工厂支持的格式列表)
2、导入的时候是否从CanCreateNew()返回的默认值
3、是否允许工厂从文件导入对象

在FactoryCreateFile方法中,简单的将IntValue的值以字节的形式读取到UE中,并将其赋值给IntValue

3、覆盖

#pragma once

#include "CoreMinimal.h"
#include "Factories/Factory.h"
#include "EditorReimportHandler.h"
#include "SimpleAnimationAssetFactoryImport.generated.h"

UCLASS()
class USimpleAnimationAssetFactoryImport : public UFactory
	, public FReimportHandler
{
	GENERATED_UCLASS_BODY()
public:
	virtual UObject* FactoryCreateFile(UClass* InClass, UObject* InParent,
		FName InName, EObjectFlags Flags, const FString& Filename, const TCHAR* Parms,
		FFeedbackContext* Warn, bool& bOutOperationCanceled) override;
	virtual bool CanReimport(UObject* Obj, TArray<FString>& OutFilenames) override;
	virtual EReimportResult::Type Reimport(UObject* Obj) override;

};

我们需要在import中多继承一个基类 FReimportHandler,该类用于重新导入,也就是覆盖

新增几个导入相关的函数:
CanReimport: 是否可以进行重新导入操作
Reimport: 导入的实际数据操作

bool USimpleAnimationAssetFactoryImport::CanReimport(UObject* Obj, TArray<FString>& OutFilenames)
{
	return true;
}

EReimportResult::Type USimpleAnimationAssetFactoryImport::Reimport(UObject* Obj)
{
	if (IsValid(Obj)) {
		bool OutCancel = false;
		UObject* NewObj = ImportObject(Obj->GetClass(), Obj->GetOuter(),
			Obj->GetFName(), Obj->GetFlags(), PreferredReimportPath,
			nullptr, OutCancel);
		if (!OutCancel) {
			USimpleAnimationAsset* SimpleAnimationAsset = Cast<USimpleAnimationAsset>(NewObj);
			return EReimportResult::Succeeded;
		}
	}
	return EReimportResult::Failed;
}

是否可以重新导入,我们直接定义为True,这里可以根据需求增加导入的限制

Reimport 中 我们将导入的对象转为我们定义的资源类型 USimpleAnimationAsset