自定义资源的定义
在UE4里存在大量的内置资源, 例如UStaticMesh(镜头),USkeletalMesh(骨骼网格), UMaterial(材质), UMaterialInstance(材质实例), UTexture(纹理),如下所示.
这些资源在C++层面都是继承UObject形成的对象,如UStaticMesh
我们由于项目需求得定义属于自己的资源,扩展出我们的自定义资源。
(1)继承UObject,创建我们资源对象,注意这个自定义的UMyObject可位于Runtime模块或者Editor模块,取决于你的需求
UCLASS()
class MYTEST_API UMyObject : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
int A;
};
(2)创建我们的UObject对应的Factory, 注意UMyObjectFactory必须位于Editor模块
#include "CoreMinimal.h"
#include "Factories/Factory.h"
#include "MyObjectFactory.generated.h"
/**
*
*/
UCLASS()
class MYTEST_API UMyObjectFactory : public UFactory
{
GENERATED_BODY()
public:
UMyObjectFactory();
virtual UObject* FactoryCreateNew(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn);
};
#include "MyObjectFactory.h"
#include "MyObject.h"
UMyObjectFactory::UMyObjectFactory()
{
bCreateNew = true;
bEditAfterNew = true;
SupportedClass = UMyObject::StaticClass();
}
UObject* UMyObjectFactory::FactoryCreateNew(UClass* InClass, UObject* InParent,
FName InName, EObjectFlags Flags, UObject* Context, FFeedbackContext* Warn)
{
UMyObject* MyObject = NewObject<UMyObject>(InParent, InName, Flags | RF_Transactional);
return MyObject;
}
在修改配置模块.cs文件,添加 “UnrealEd”
之后就可以在编辑器创建我们的自定义资源了
自定义资源的类别和筛选功能
按照上面的步骤得到的资源默认在 “Miscellaneous”
并且筛选类别无法找到该资源
下面我们通过注册自定义Category, 并且将我们自定义的资源资源放在自定义Category上
(1)继承FAssetTypeActions_Base
#include "AssetTypeActions_Base.h"
class FMyObjectTypeAction : public FAssetTypeActions_Base
{
public:
virtual FText GetName() const override;
virtual uint32 GetCategories() override;
virtual FColor GetTypeColor() const override;
virtual FText GetAssetDescription(const FAssetData& AssetData) const override;
virtual UClass* GetSupportedClass() const override;
};
#include "MyObject.h"
FText FMyObjectTypeAction::GetName() const
{
return FText::FromString("MyObject");
}
uint32 FMyObjectTypeAction::GetCategories()
{
return MyCustomCategory;
}
FColor FMyObjectTypeAction::GetTypeColor() const
{
return FColor(255, 0, 0, 255);
}
FText FMyObjectTypeAction::GetAssetDescription(const FAssetData& AssetData) const
{
return FText::FromString("MyObjectDes");
}
UClass* FMyObjectTypeAction::GetSupportedClass() const
{
return UMyObject::StaticClass();
}
(2)在模块StartupModule里注册自定义类别EAssetTypeCategories::Type,EAssetTypeCategories::Type为筛选资源的类别, 并且注册AssetTypeActions
// The list of categories for Asset Type Actions and UFactory subclasses
namespace EAssetTypeCategories
{
enum Type
{
None = 0,
Basic = 1 << 0,
Animation = 1 << 1,
MaterialsAndTextures = 1 << 2,
Sounds = 1 << 3,
Physics = 1 << 4,
UI = 1 << 5,
Misc = 1 << 6,
Gameplay = 1 << 7,
Blueprint = 1 << 8,
Media = 1 << 9,
// Items below this will be allocated at runtime via RegisterAdvancedAssetCategory
FirstUser = 1 << 10,
LastUser = 1 << 31,
// Last allowed value is 1 << 31
};
}
IAssetTools& AssetTools = FModuleManager::Get().GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
MyCustomCategory = AssetTools.RegisterAdvancedAssetCategory(FName("MyCustom"), FText::FromString("MyCustom"));
AssetTools.RegisterAssetTypeActions(MakeShareable(new FMyObjectTypeAction));
记得卸载模块
if (FModuleManager::Get().IsModuleLoaded("AssetTools"))
{
IAssetTools& AssetTools = FModuleManager::Get().GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
AssetTools.UnregisterAssetTypeActions(MakeShareable(new FMyObjectTypeAction));
}
这样我们的自定义资源(MyObject)出现在我们的自定义类别(MyCustom)里.
筛选功能也具备了
自定义资源的读取和修改
我们在编辑器创建一个自定义资源对象,如何在C++代码里修改它呢?怎么读取并且修改呢,其实就是之前文章说过的LoadObject. 不过修改属性之钱得调用Modify
自定义资源的生成
const FString PackageName = "/Game/Test";
const FString ObjectName = "Test";
UPackage* Package = CreatePackage(NULL, *PackageName);
UMyObject* MyObject = NewObject<UMyObject>(Package, *ObjectName, RF_Standalone | RF_Public);
MyObject->A = 100;
MyObject->PostEditChange();
MyObject->MarkPackageDirty();
FAssetRegistryModule::AssetCreated(MyObject);
调用资源创建器创建资源
FAssetToolsModule& AssetToolsModule = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools");
UMyObjectFactory* FactoryInstance = NewObject<UMyObjectFactory>();
UObject* NewAsset = AssetToolsModule.Get().CreateAssetWithDialog(UMyObject::StaticClass(), FactoryInstance);
if (NewAsset)
{
UMyObject* MyObject = Cast<UMyObject>(NewAsset);
if (MyObject)
{
MyObject->Modify();
MyObject->A = 100;
}
}
参考资料
[1] https://answers.unrealengine.com/questions/337715/custom-asset-category.html