【UE迭代预警】5.2+ 资产编辑器破坏性迭代 #FAssetTypeActions_Base #UAssetDefinitionDefault

本文在博客园原创,转载请标注出处

前言

旧Asset Actions系统通常继承FAssetTypeActions_Base并实现核心OpenAssetEditor方法,并且一般在模块中通过IAssetTools::RegisterAssetTypeActions(MakeShareable(new FAssetTypeActions_Xxx()))手动实现注册,由于FAssetTypeActions_Base并非U类而是纯Cpp类,其智能指针体系与UE的管理方式不兼容,经常会导致自定义资产在某些复杂自定义插件中失效或者内存溢出。

UE5.2版本之后,官方逐步使用Asset Definitions取代过去旧系统Asset Actions 社区原文。其在5.2之后,引擎删除了几乎所有由旧资产操作系统的构建方式,全部转换为新系统,且在未来只对旧系统做兼容

迭代方法

笔者这里直接采用另一位博主的开源项目中的代码片段进行示例更改:

本文借用代码库:https://github.com/dzxmxd/GraphSampleEditor

代码库博主:https://santa.wang/

迭代方式分为两步,非常简单

tips:注意添加新模块依赖:"AssetDefinition"

建立新系统

UE5.2之后的新系统:

复制代码
UCLASS()
class GRAPHSAMPLEEDITOR_API UAssetDefinition_GraphSample : public UAssetDefinitionDefault
{
	GENERATED_BODY()

public:
	virtual FText GetAssetDisplayName() const override;
	virtual TSoftClassPtr<UObject> GetAssetClass() const override;
	/** Returns the color associated with this type */
	virtual FLinearColor GetAssetColor() const override;
	
	virtual EAssetCommandResult OpenAssets(const FAssetOpenArgs& OpenArgs) const override;

};

// 其余方式均以原本的一致,区别在于OpenAssets的实现

EAssetCommandResult UAssetDefinition_GraphSample::OpenAssets(const FAssetOpenArgs& OpenArgs) const
{
	const EToolkitMode::Type Mode = OpenArgs.ToolkitHost.IsValid() ? EToolkitMode::WorldCentric : EToolkitMode::Standalone;

	for (const FAssetData& AssetData : OpenArgs.Assets)
	{
		// 将 FAssetData 转为 UObject*(会在需要时加载 asset)
		UObject* LoadedObject = AssetData.GetAsset();
		if (UGraphSampleAsset* GraphSampleAsset = Cast<UGraphSampleAsset>(LoadedObject))
		{
			// 使用现有编辑器模块工厂函数打开编辑器(与原 FAssetTypeActions 的逻辑一致)
			FGraphSampleEditorModule::CreateGraphSampleAssetEditor(Mode, OpenArgs.ToolkitHost, GraphSampleAsset);
		}
	}

	return EAssetCommandResult::Handled;
}

删除原有资产构建方式

UAssetDefinitionDefault会自动注册继承类的资产,不需要进行手动操作。且会自动调用OpenAssets方法.

旧系统可以直接删除,如下所示

复制代码
//删除整个类即可
class GRAPHSAMPLEEDITOR_API FAssetTypeActions_GraphSampleAsset final : public FAssetTypeActions_Base
{
public:
	virtual FText GetName() const override;
	virtual uint32 GetCategories() override;
	virtual FColor GetTypeColor() const override { return FColor(255, 0, 255); }

	virtual UClass* GetSupportedClass() const override;
	virtual void OpenAssetEditor(const TArray<UObject*>& InObjects, TSharedPtr<class IToolkitHost> EditWithinLevelEditor = TSharedPtr<IToolkitHost>()) override;
};
//同时删除在模块启动时对自定义资产的手动注册
void FGraphSampleEditorModule::StartupModule()
{
	FGraphSampleEditorStyle::Initialize();
	//RegisterAssets(); //删除旧系统原有手动注册
	RegisterDelegates();
}

void FGraphSampleEditorModule::ShutdownModule()
{
	FGraphSampleEditorStyle::Shutdown();
	//UnregisterAssets(); //删除旧系统原有手动取消注册
	UnregisterDelegates();
}

void FGraphSampleEditorModule::RegisterAssets()
{
	IAssetTools& AssetTools = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get();

	if (GraphSampleAssetCategory == EAssetTypeCategories::None)
	{
		GraphSampleAssetCategory = AssetTools.RegisterAdvancedAssetCategory(FName(TEXT("GraphSample")), LOCTEXT("GraphSampleEditorModule_GraphSampleCategory", "GraphSample"));
	}

	const TSharedRef<IAssetTypeActions> GraphSampleAssetActions = MakeShareable(new FAssetTypeActions_GraphSampleAsset());
	RegisteredAssetActions.Add(GraphSampleAssetActions);
	AssetTools.RegisterAssetTypeActions(GraphSampleAssetActions);
}

void FGraphSampleEditorModule::UnregisterAssets()
{
	if (FModuleManager::Get().IsModuleLoaded("AssetTools"))
	{
		IAssetTools& AssetTools = FModuleManager::GetModuleChecked<FAssetToolsModule>("AssetTools").Get();
		for (const TSharedRef<IAssetTypeActions>& TypeAction : RegisteredAssetActions)
		{
			AssetTools.UnregisterAssetTypeActions(TypeAction);
		}
	}

	RegisteredAssetActions.Empty();
}