В этой статье используется UE 4.26, движок поставляется с проектом ARPG и записывает DataTable в UE4, то есть использование таблицы данных, как с точки зрения кода, так и с точки зрения редактора.
1. Что такое таблица данных?
DataTable — это таблица данных (далее — DT), которая представляет собой двумерную матрицу с M строками и N столбцами, как показано на следующем рисунке:
Это таблица данных с 5 строками (Row) и тремя столбцами (Col). Программа может найти соответствующую взаимосвязь и реализовать соответствующую логику с помощью таблицы данных конфигурации планирования, что очень удобно для планирования.
2. Использование в редакторе
2.1 Создайте таблицу данных
В редакторе щелкните правой кнопкой мыши Miscellaneous -> DataTable
, чтобы создать ОУ:
Вам необходимо выбрать структуру данных строки (т. е. столбца). Например, если вы выберете GameplayTagTableRow, ОУ будет создано, как показано ниже: Вновь
созданное ОУ по умолчанию пусто. Нажмите кнопку «Добавить», чтобы создать строку по умолчанию. Если структура столбца ОУ — В коде, значение по умолчанию задается в коде; если структура столбца ОУ является ресурсом, она задается в ресурсе. В этом примере GameplayTagTableRow записан в коде, поэтому значение по умолчанию установлено в коде (значение по умолчанию не установлено, поэтому по умолчанию для тега установлено значение None, а для DevComment по умолчанию — пустое значение):
/** Simple struct for a table row in the gameplay tag table and element in the ini list */
USTRUCT()
struct FGameplayTagTableRow : public FTableRowBase
{
GENERATED_USTRUCT_BODY()
/** Tag specified in the table */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=GameplayTag)
FName Tag;
/** Developer comment clarifying the usage of a particular tag, not user facing */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=GameplayTag)
FString DevComment;
/** Constructors */
FGameplayTagTableRow() {
}
FGameplayTagTableRow(FName InTag, const FString& InDevComment = TEXT("")) : Tag(InTag), DevComment(InDevComment) {
}
GAMEPLAYTAGS_API FGameplayTagTableRow(FGameplayTagTableRow const& Other);
/** Assignment/Equality operators */
GAMEPLAYTAGS_API FGameplayTagTableRow& operator=(FGameplayTagTableRow const& Other);
GAMEPLAYTAGS_API bool operator==(FGameplayTagTableRow const& Other) const;
GAMEPLAYTAGS_API bool operator!=(FGameplayTagTableRow const& Other) const;
GAMEPLAYTAGS_API bool operator<(FGameplayTagTableRow const& Other) const;
};
Нажмите на строку в DT, строка будет выделена, и значение этой строки можно будет изменить в редакторе строк (Уведомление: первый столбец представляет количество строк, имя столбца нельзя изменить)
2.2 Настройте столбцы таблицы данных
Столбцы DT фиксируются после их создания. Вы не можете случайно добавить или удалить столбец. Если вам нужно настроить таблицу данных столбца, вы можете щелкнуть правой кнопкой мыши в Содержимом и создать «Структуру»:
В Структуре вы можете добавлять переменные, регулировать положение переменных (чем выше, тем левее в DT) и Default Values
устанавливать значение по умолчанию для каждого столбца (Уведомление: Переменные и строковые значения, оба могут быть китайскими):
Затем щелкните правой кнопкой мыши, чтобы создать ОУ, используйте только что созданную структуру пользовательского столбца, нажмите «Добавить», и вы увидите значение по умолчанию:
3. Использование в коде
3.1 Создайте структуру столбца с помощью кода
В коде вы можете имитировать FGameplayTagTableRow и написать его:
USTRUCT(BlueprintType)
struct FTableRowTest : public FTableRowBase
{
GENERATED_USTRUCT_BODY()
public:
FTableRowTest() {
}
FTableRowTest(bool InLoop, int32 InCurrentCount, int32 InMaxNum, float InLifeTime)
: bLoop(InLoop)
, CurrentCount(InCurrentCount)
, MaxNum(InMaxNum)
, LifeTime(InLifeTime)
{
}
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "是否循环")
bool bLoop = false;
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "当前数量")
int64 CurrentCount = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "最大数量")
int64 MaxNum = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, DisplayName = "生命周期")
float LifeTime = 0.f;
};
Таким образом, вы можете создать ОУ этой структуры столбца в редакторе (а поскольку структура столбца создается кодом, к ней нельзя перейти в структуре строк. Если это ресурс, вы можете перейти непосредственно к ресурсу структуры. ):
3.2 Чтение/запись ОУ через код
DT можно загрузить непосредственно через путь и имя ресурса в коде. Например, «MyTestDT» в каталоге Content/TestForDT можно загрузить следующим образом:
UDataTable* const TestTable = LoadObject<UDataTable>(nullptr, TEXT("/Game/TestForDT/MyTestDT.MyTestDT"));
Затем вы можете void UDataTable::AddRow(FName RowName, const FTableRowBase& RowData)
добавлять новые строки через . например:
TestTable->AddRow(FName("Bob"), FTableRowTest(true, 3, 8, 2.7f));
3.3 CSV, JSON
После создания DT вы можете щелкнуть правой кнопкой мыши и экспортировать его в файл CSV или JSON:
В редакторе вы можете импортировать через CSV или JSON через Reimport. Конкретный формат вы узнаете после того, как попробуете:
Вы также можете создать ОУ непосредственно из CSV или JSON в коде (или проекте):
/**
* Create table from CSV style comma-separated string.
* RowStruct must be defined before calling this function.
* @return Set of problems encountered while processing input
*/
ENGINE_API TArray<FString> CreateTableFromCSVString(const FString& InString);
4. Меры предосторожности
4.1 Копирование контента
Если после выбора строки вы хотите скопировать ее содержимое, возможны две ситуации:
-
Если это первый столбец, который является ключевым, выберите строку и
F2
нажмите
-
Если это другой столбец, а именно «Значение», вы можете скопировать его в редакторе строк после выбора строки.
4.2 Сортировка
DT можно отсортировать по значению определенного столбца, но это нонсенс: независимо от того, какого он типа, TEXT преобразуется в FString и затем сравнивается.Исходный код следующий (в функции) FDataTableEditor::OnColumnSortModeChanged
:
if (InSortMode == EColumnSortMode::Ascending)
{
VisibleRows.Sort([ColumnIndex](
const FDataTableEditorRowListViewDataPtr& first,
const FDataTableEditorRowListViewDataPtr& second)
{
// 返回值:大于 0 表示 A > B; 0 表示相等; 小于 0 表示 A < B
int32 Result = (first->CellData[ColumnIndex].ToString()).Compare(second->CellData[ColumnIndex].ToString());
if (!Result)
{
return first->RowNum < second->RowNum;
}
return Result < 0;
});
}
Сравнение FString — это сортировка по словарю , поэтому 99
> 963
:
и 2.87
> 11.09
:
Мой собственный метод модификации — напрямую изменить движок. Если он числовой, сортируйте по числовому типу, а не по строке:
VisibleRows.Sort([ColumnIndex](
const FDataTableEditorRowListViewDataPtr& first,
const FDataTableEditorRowListViewDataPtr& second)
{
int32 Result = (first->CellData[ColumnIndex].ToString()).Compare(second->CellData[ColumnIndex].ToString());
FString const FirstColumnStr = first->CellData[ColumnIndex].ToString();
FString const SecondColumnStr = second->CellData[ColumnIndex].ToString();
bool const bNumeric = FCString::IsNumeric(*FirstColumnStr) && FCString::IsNumeric(*SecondColumnStr);
if (bNumeric)
{
double const FirstNum = FCString::Atod(*FirstColumnStr);
double const SecondNum = FCString::Atod(*SecondColumnStr);
Result = (FirstNum > SecondNum) ? 1 : ((FirstNum < SecondNum) ? -1 : 0);
}
if (!Result)
{
return first->RowNum < second->RowNum;
}
return Result < 0;
});