UE DataTable
一、DataTable 是什么
DataTable 就是数据表,也就是一个二维的 M 行 N 列的矩阵,如下图所示就是一个七行六列的数据表:
程序可以通过策划配置的数据表找到对应关系做相应的逻辑,对策划很友好。
二、在编辑器中使用
1.创建一个结构体
首先创建一个结构体,该结构体就是我们要创建的数据表的列数据,然后再在新创建的结构体中添加变量,可以在Default Values页面设置添加数据时的默认值:
2. 创建一个数据表
在编辑器中右键,Miscellaneous -> DataTable
即可创建一个 DataTable:
创建数据表的时候,需要选择一个结构体,选择我们刚才新创建的那个结构体即可,这样创建出来的数据表的列就是刚才结构体中的变量:
新创建的数据表默认是空的, 点击 Add 按钮可以添加一个默认行,第一列的Row Name是自动生成的。Row Name 用来唯一标识每一行,相当于数据库中的主键,可以修改,但不能有相同的值。添加完成后,点击数据表中的一行,这一行会高亮,且可以在 Row Editor 中修改这一行的值。
3. 蓝图中获取数据表中数据
可以使用节点GetDataTableRowNames获取数据表中全部行的Row Name:
使用节点GetDataTableRow根据Row Name获取该Row Name那一行的数据:
可以这样读取数据表中的数据打印出来:
4. 导入CSV为数据表
在编辑器中右键,导入资源到文件夹,然后选择要导入的CSV文件:
导入的时候也需要选择该数据表所使用的结构体。
三、代码中使用
1. 使用代码创建一个列结构
继承FTableRowBase类,需要包含头文件"Engine/DataTable.h",同时由于添加结构体用到USTRUCT,加入了反射系统,还需要包含该文件的.generated.h头文件:
USTRUCT(BlueprintType)
struct FTableRowTest : public FTableRowBase
{GENERATED_USTRUCT_BODY()public:FTableRowTest(){}FTableRowTest(FString InName, int32 InCurrentCount, int32 InMaxNum, float InLifeTime):name(InName), CurrentCount(InCurrentCount), MaxNum(InMaxNum), LifeTime(InLifeTime){}UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "名字")FString name;UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "当前数量")int64 CurrentCount = 0;UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "最大数量")int64 MaxNum = 100;UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "生命周期")float LifeTime = 10.0f;
};
编译过后就可以在创建数据表的时候看到刚才创建的结构体选项了:
2. 通过代码读数据表
可以通过FindRow读取某一行的数据:
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{for (FName RowName : UserInfoDataTable->GetRowNames()){FTableRowTest* TestInfo = UserInfoDataTable->FindRow<FTableRowTest>(RowName, TEXT("name"));if (TestInfo){UKismetSystemLibrary::PrintString(GetWorld(), TestInfo->name);}}
}
else
{UKismetSystemLibrary::PrintString(GetWorld(), TEXT(" Not Find DataTable!"));
}
可以通过GetRowMap读取数据表中全部数据:
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{for (auto it : UserInfoDataTable->GetRowMap()){FString RowName = (it.Key).ToString();FTableRowTest* TestInfo = (FTableRowTest*)it.Value;UKismetSystemLibrary::PrintString(GetWorld(), FString::Printf(TEXT("%s %s"), *RowName, *TestInfo->name));}
}
3. 通过代码写数据表
在代码中可以直接通过资源路径和名称加载数据表,比如在 Content/TestForDT 目录下的 “MyTestDT”,可以这样加载:
UDataTable* const TestTable = LoadObject<UDataTable>(nullptr, TEXT("/Game/TestForDT/MyTestDT.MyTestDT"));
然后就可以通过 void UDataTable::AddRow(FName RowName, const FTableRowBase& RowData)
来新增行了。比如:
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{FSimpleStruct* UserInfo = new FSimpleStruct();UserInfo->name = TEXT("Lily");UserInfo->health = 80;FName RowName = TEXT("Player3");UserInfoDataTable->AddRow(RowName, *UserInfo);
}
4. 导入CSV
- csv 文件
---,name,health,icon
Player4,"小明","200","Texture2D'/Game/FourEvilDragonsHP/Textures/DragonTheUsurper/BlueHPTex.BlueHPTex'"
Player5,"小红","90","Texture2D'/Game/FourEvilDragonsHP/Textures/DragonTheSoulEater/BlueHPTex.BlueHPTex'"
Player6,"小张","150","None"
- 填充现有的 DataTable
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo.csv");CSVPath = FPaths::ConvertRelativePathToFull(CSVPath);if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*CSVPath)){UDataTableFunctionLibrary::FillDataTableFromCSVFile(UserInfoDataTable, CSVPath);}
}
- 生成 UDataTable
UDataTable* const UDataTable* ADataDriveActor::CreateDataTableFromCSV()
{FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo.csv");CSVPath = FPaths::ConvertRelativePathToFull(CSVPath);if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*CSVPath)){UKismetSystemLibrary::PrintString(GetWorld(), *CSVPath);FString CSVData;FFileHelper::LoadFileToString(CSVData, *CSVPath);UDataTable* DT_UserInfo = NewObject<UDataTable>(GetTransientPackage(), FName(TEXT("DT_UserInfo2")));DT_UserInfo->RowStruct = FSimpleStruct::StaticStruct();DT_UserInfo->CreateTableFromCSVString(CSVData);return DT_UserInfo;}return nullptr;
}
5. 导出 CSV
使用GetTableAsCSV():
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{FString CSVString = UserInfoDataTable->GetTableAsCSV();FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");FFileHelper::SaveStringToFile(CSVString, *CSVPath, FFileHelper::EEncodingOptions::ForceUTF8);
}
UE DataTable
一、DataTable 是什么
DataTable 就是数据表,也就是一个二维的 M 行 N 列的矩阵,如下图所示就是一个七行六列的数据表:
程序可以通过策划配置的数据表找到对应关系做相应的逻辑,对策划很友好。
二、在编辑器中使用
1.创建一个结构体
首先创建一个结构体,该结构体就是我们要创建的数据表的列数据,然后再在新创建的结构体中添加变量,可以在Default Values页面设置添加数据时的默认值:
2. 创建一个数据表
在编辑器中右键,Miscellaneous -> DataTable
即可创建一个 DataTable:
创建数据表的时候,需要选择一个结构体,选择我们刚才新创建的那个结构体即可,这样创建出来的数据表的列就是刚才结构体中的变量:
新创建的数据表默认是空的, 点击 Add 按钮可以添加一个默认行,第一列的Row Name是自动生成的。Row Name 用来唯一标识每一行,相当于数据库中的主键,可以修改,但不能有相同的值。添加完成后,点击数据表中的一行,这一行会高亮,且可以在 Row Editor 中修改这一行的值。
3. 蓝图中获取数据表中数据
可以使用节点GetDataTableRowNames获取数据表中全部行的Row Name:
使用节点GetDataTableRow根据Row Name获取该Row Name那一行的数据:
可以这样读取数据表中的数据打印出来:
4. 导入CSV为数据表
在编辑器中右键,导入资源到文件夹,然后选择要导入的CSV文件:
导入的时候也需要选择该数据表所使用的结构体。
三、代码中使用
1. 使用代码创建一个列结构
继承FTableRowBase类,需要包含头文件"Engine/DataTable.h",同时由于添加结构体用到USTRUCT,加入了反射系统,还需要包含该文件的.generated.h头文件:
USTRUCT(BlueprintType)
struct FTableRowTest : public FTableRowBase
{GENERATED_USTRUCT_BODY()public:FTableRowTest(){}FTableRowTest(FString InName, int32 InCurrentCount, int32 InMaxNum, float InLifeTime):name(InName), CurrentCount(InCurrentCount), MaxNum(InMaxNum), LifeTime(InLifeTime){}UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "名字")FString name;UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "当前数量")int64 CurrentCount = 0;UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "最大数量")int64 MaxNum = 100;UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "生命周期")float LifeTime = 10.0f;
};
编译过后就可以在创建数据表的时候看到刚才创建的结构体选项了:
2. 通过代码读数据表
可以通过FindRow读取某一行的数据:
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{for (FName RowName : UserInfoDataTable->GetRowNames()){FTableRowTest* TestInfo = UserInfoDataTable->FindRow<FTableRowTest>(RowName, TEXT("name"));if (TestInfo){UKismetSystemLibrary::PrintString(GetWorld(), TestInfo->name);}}
}
else
{UKismetSystemLibrary::PrintString(GetWorld(), TEXT(" Not Find DataTable!"));
}
可以通过GetRowMap读取数据表中全部数据:
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{for (auto it : UserInfoDataTable->GetRowMap()){FString RowName = (it.Key).ToString();FTableRowTest* TestInfo = (FTableRowTest*)it.Value;UKismetSystemLibrary::PrintString(GetWorld(), FString::Printf(TEXT("%s %s"), *RowName, *TestInfo->name));}
}
3. 通过代码写数据表
在代码中可以直接通过资源路径和名称加载数据表,比如在 Content/TestForDT 目录下的 “MyTestDT”,可以这样加载:
UDataTable* const TestTable = LoadObject<UDataTable>(nullptr, TEXT("/Game/TestForDT/MyTestDT.MyTestDT"));
然后就可以通过 void UDataTable::AddRow(FName RowName, const FTableRowBase& RowData)
来新增行了。比如:
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{FSimpleStruct* UserInfo = new FSimpleStruct();UserInfo->name = TEXT("Lily");UserInfo->health = 80;FName RowName = TEXT("Player3");UserInfoDataTable->AddRow(RowName, *UserInfo);
}
4. 导入CSV
- csv 文件
---,name,health,icon
Player4,"小明","200","Texture2D'/Game/FourEvilDragonsHP/Textures/DragonTheUsurper/BlueHPTex.BlueHPTex'"
Player5,"小红","90","Texture2D'/Game/FourEvilDragonsHP/Textures/DragonTheSoulEater/BlueHPTex.BlueHPTex'"
Player6,"小张","150","None"
- 填充现有的 DataTable
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo.csv");CSVPath = FPaths::ConvertRelativePathToFull(CSVPath);if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*CSVPath)){UDataTableFunctionLibrary::FillDataTableFromCSVFile(UserInfoDataTable, CSVPath);}
}
- 生成 UDataTable
UDataTable* const UDataTable* ADataDriveActor::CreateDataTableFromCSV()
{FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo.csv");CSVPath = FPaths::ConvertRelativePathToFull(CSVPath);if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*CSVPath)){UKismetSystemLibrary::PrintString(GetWorld(), *CSVPath);FString CSVData;FFileHelper::LoadFileToString(CSVData, *CSVPath);UDataTable* DT_UserInfo = NewObject<UDataTable>(GetTransientPackage(), FName(TEXT("DT_UserInfo2")));DT_UserInfo->RowStruct = FSimpleStruct::StaticStruct();DT_UserInfo->CreateTableFromCSVString(CSVData);return DT_UserInfo;}return nullptr;
}
5. 导出 CSV
使用GetTableAsCSV():
UDataTable* const UserInfoDataTable = LoadObject<UDataTable>(this, TEXT("DataTable'/Game/CPPFunction/DataDrive/DT_UserInfo.DT_UserInfo'"));
if (UserInfoDataTable)
{FString CSVString = UserInfoDataTable->GetTableAsCSV();FString CSVPath = FPaths::ProjectDir() + TEXT("DataDrive/UserInfo2.csv");FFileHelper::SaveStringToFile(CSVString, *CSVPath, FFileHelper::EEncodingOptions::ForceUTF8);
}
发布评论