【转载】C++ 结合 DataTable 批量快速创建 DataAsset

582 阅读3分钟

原文链接:【UE4】C++ 结合 DataTable 批量快速创建 DataAsset | a飞雷神

正文

剖析某些大型游戏的框架,可以发现广泛运用了 DataTableDataAsset 来管理数据,DataTable 的导入直接用 Excel 就能很轻易的完成,但是 DataAsset 却要一直手动去填,当 DataAsset 有几百个时,哪怕通过引擎自带的 Bulk Edit 去调也是一个噩梦。

那么假如可以将 DataTableDataAsset 结合起来去填充 DataAsset 的数据,那么不香么?

结合了钊哥的数据驱动教程

数据驱动开发

提供的将 DataTable 在编辑器中编辑的思路,我简易地实现了这个非常方便的功能。想直接看效果的可以看我的这个视频

UE4 C++结合DataTable批量快速创建DataAsset


现在简要地说明一下实现流程

在阅读本文之前,假设你已经对 DataTableDataAsset 已经有了初步的了解。

为了简单起见,本文不结合 AssetManagerDataAsset 中应用 FPrimaryAssetType 这个概念,读者有需要可以自行补充。

  1. 在 C++ 中创建以 FTableRowBase 为父类的结构体 FItemsProperties

其余属性,读者自行填充

  1. 以该结构体为基准,在 Excel 中填好数据,并将 csv 文件导入虚幻4,生成 DataTable。(这一步的具体实现请参考官方文档有关教程

导入完成后在 UE4 中如下图所示

打开为

  1. 在 C++ 中以 UPrimaryDataAsset 为父类创建自定义的 DataAsset,其中 ItemProperty 是刚才创建的 DataTable 结构体 FItemsProperties
/** Base class for all items*/
UCLASS(BlueprintType)
class MYGAME_API UItemBase : public UPrimaryDataAsset
{
	GENERATED_BODY()

public:
	/*ItemProperty*/
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Item)
	FItemsProperties ItemProperty;
};
  1. 在 C++ 中以 UBlueprintFunctionLibrary 为父类创建蓝图函数库

并创建 CreateNewDataAsset 函数

.h 如下

UCLASS(Blueprintable, Category = "DataDriven")
class MYGAME_API UMyDataFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

public:
#if WITH_EDITOR
	/*Create NewDataAsset in the Editor.The PackagePath cannot end with /.*/
	UFUNCTION(BlueprintCallable, Category = "Editor Scripting | DataAsset")
	static void CreateNewDataAsset(const FString PackagePath, const FString AssetName, const FItemsProperties& ItemProperty);

#endif
	
};

在 cpp 文件中的具体实现为(没错,就是标准的创建 Asset 的流程注意必要时需要对 DataTable 结构体中的拷贝赋值运算符进行重载,防止浅拷贝)

.cpp 如下

void UMyDataFunctionLibrary::CreateNewDataAsset(const FString PackagePath, const FString AssetName,const FItemsProperties& ItemProperty)
{
	// 创建 package
	UPackage* MyPackage = CreatePackage(nullptr, *PackagePath);

	// 创建 Object
	UItemBase* ItemDataAsset = NewObject<UItemBase>(MyPackage, UItemBase::StaticClass(), *AssetName, EObjectFlags::RF_Public | RF_Standalone);
	
	if (ItemDataAsset == nullptr)
	{
                    return;
	}

        // 初始化对象 ==
	ItemDataAsset->ItemProperty = ItemProperty;// 简要起见,直接赋值,必要时需要对拷贝赋值运算符重载
        // 结束初始化对象 ==

	FAssetRegistryModule::AssetCreated(ItemDataAsset);// 告知资源浏览器

	ItemDataAsset->GetOutermost()->MarkPackageDirty();// 标星号
}
  1. 在 UE4 中创建编辑器工具蓝图

父类选择 EditorUtilityObject

首先读取 DataTable 中的内容

再将数据表中的数据写入 DataAsset 中,并注意路径末尾 不能/ 结尾,否则创建的 DataAsset 无法保存。(忽略下面 Create New Data Asset 中的 ItemType,如果不需要用 AssetManager,就不需要在 C++ 中设置这个形参)

image.png

Package Path 可以进一步优化,否则只按上面的方式设置,在文件夹视图中,只会有一个 UAsset。按下面的方式设置,UAsset 就正常了(推荐按下面的方式)

image.png

设置好之后,编译,保存。

  1. 运行编辑器工具控件

就会快速生成一堆 DataAsset

可以看到,DataTable 中的数据,已经完全导入到 DataAsset 中了,这样再也不必手动设置 DataAsset 中的数据了,也非常方便管理 DataAsset 中的数据。

具体效果可以看我这个视频

UE4 C++结合DataTable批量快速创建DataAsset