1. Overview
本教程以自定义函数GetTableAsJsonString()实现过程为例,旨在讲解如何将UE4源码中的部分源代码改写为自定义函数代码,同时也是为了补充上一期(第6期 UE4 动态读写DataTable数据表)的缺漏。
2. Introduction
虽然虚幻引擎功能强大,但也并非想要的功能都有。某些情况下,虽然在虚幻引擎源代码中已经存在你想要的功能,但是这些函数代码无法直接调用,常常也会遇到源代码中部分功能被WITH_EDITOR宏包裹,以至于这些函数无法在打包后调用。所以常常需要修改(改写)引擎源代码,它不仅可以弥补引擎内置功能的不足,而且相较于自己编写同样功能的代码的过程,耗时耗力、产生更多隐藏bug等问题;直接改写源代码工作量小,出错率相对低。修改引擎源代码,同时也是一种编程水平的体现,反映个人对源代码的理解程度。
上一期讲述了动态读写UE4 DataTable数据表的实现方法,其中GetTableAsCSVString()就是仿照源代码UDataTable::GetTableAsString()函数,可以轻而易举的实现该函数。但是上一期内容还缺失了一个蓝图函数GetTableAsJsonString(),完成将DataTable导出成Json字符串功能。GetTableAsJsonFile()只需要在获得DataTable相应的JsonString后,将其保存为Json文件即可。本期内容以实现自定义蓝图函数GetTableAsJsonString()为例,讲解如何将ue4引擎源代码中的功能化为己用。
首先,如上图所示,在UE4源代码UDataTable类中包含了GetTableAsJSON()函数,已经可以将DataTable数据表导出成Json字符串,但是该函数被WITH_EDITOR宏包裹着,并不能在项目打包之后使用。
继续查看UDataTable::GetTableAsJSON()函数体,可以看出,在构造FDataTableExporterJSON类的对象之后,调用FDataTableExporterJSON类的成员函数WriteTable(),从而获得DataTable导出的Json字符串;
进一步查看FDataTableExporterJSON类,该类所有代码也同样被WITH_EDITOR宏包裹着,从而可以得出结论,并不能简单的UDataTable::GetTableAsJSON()函数体代码放在WITH_EDITOR宏外调用,而是应该改写源代码中FDataTableExporterJSON类的成员函数WriteTable()。
3. Source Code
以下为改写后的源代码
.h文件,如下所示
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "DataTableUtils.h" // enum class EDataTableExportFlags : uint8
#include "PrettyJsonPrintPolicy.h" // TPrettyJsonPrintPolicy<TCHAR>
#include "DataTableLibrary.generated.h"
// Forward declarations
class UDataTable;
/** Based on FDataTableExporterJSON::FDataTableJsonWriter */
typedef TJsonWriter<TCHAR, TPrettyJsonPrintPolicy<TCHAR>> FDataTableJsonWriter;
UCLASS()
class FILESHELPER_API UDataTableLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public://
/** Output entire contents of table as JSON string */
UFUNCTION(BlueprintCallable, DisplayName = "Get Table As JSON String", Category = "DataTable")
static void GetDataTableAsJSONString(UDataTable* DataTable, FString& JSONString);
public: // Based on FDataTableExporterJSON
/** Writes the data table out as an array of objects */
static bool WriteTable(TSharedRef<FDataTableJsonWriter> JsonWriter, const UDataTable& InDataTable);
/** Writes out a single row */
static bool WriteRow(TSharedRef<FDataTableJsonWriter> JsonWriter, const UScriptStruct* InRowStruct, const void* InRowData, const FString* FieldToSkip = nullptr);
/** Writes the contents of a single row */
static bool WriteStruct(TSharedRef<FDataTableJsonWriter> JsonWriter, const UScriptStruct* InStruct, const void* InStructData, const FString* FieldToSkip = nullptr, const EDataTableExportFlags DTExportFlags = EDataTableExportFlags::None);
/** Writes the contents of a struct entry */
static bool WriteStructEntry(TSharedRef<FDataTableJsonWriter> JsonWriter, const void* InRowData, const UProperty* InPropert