UE4 DataTableからのパラメータ取得とJSONインポートについて

# 概要
UnrealEngine のデータテーブルについてのメモです。
また、運用方法についてもExcelからのDataTableにインポートする方法を試してみます。


## 更新履歴
| 日付 | 内容 |
|:----|:-----|
|2020/09/17| JSONデータ再インポートが反映されない場合の備考を追記 |


## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.22, 4.25

## 参考
以下を参考にさせて頂きました、ありがとうございます。

[UnrealEngine - データ駆動型のゲームプレイエレメント](https://docs.unrealengine.com/ja/Gameplay/DataDriven/index.html)
[[UE4][C++] ユーザー定義オブジェクトのアセット化で楽をする](http://historia.co.jp/archives/7564/)



# データテーブル作成
コンテンツブラウザから右クリック [その他] -> [データテーブル] で作成できます。

## データテーブル型定義
定義するにはFTableRowBaseを継承した構造体の定義が必要です。BPでもC++でも可能のようです。

以下、C++でのテストコードです。

```cpp
USTRUCT(BlueprintType, DisplayName = "パラメータ")
struct FMyDataTable : public FTableRowBase
{
	GENERATED_USTRUCT_BODY()

public:
	// コンストラクタ
	FMyDataTable():
		Id(-1),
		Param(0.0f)
	{}

public:
	// ID
	UPROPERTY(Category = "FMyDataTable", EditAnywhere, DisplayName = "Id")
	int32	Id;
	// パラメータ
	UPROPERTY(Category = "FMyDataTable", EditAnywhere, meta = (ClampMin="0.0", ClampMax="1.0"), DisplayName = "Param")
	float		Param;
};
```

[新規追加] -> [その他] -> [データテーブル]で新規作成する際に定義したDisplayNameで構造体を選択できます。
![CreateDataTable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/ebb140c4-0400-e9fa-d10a-77a26b7c8db8.png)

作成したデータテーブルを開くと定義したメンバが確認できます。
![MyDataTable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/800a5585-8e76-3729-5c2b-6c9bce8ecc67.png)


## データテーブルアクション
CSVやJSONでエクスポートができます。エクスポートしたデータに変更があれば再インポートするように通知設定すると便利です。

![DataTableAction.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/938c5733-e539-3bbf-d065-5988d07a2f5f.jpeg)


[編集] -> [エディタの環境設定] -> [一般 - ロード＆保存中] -> [Directories to Monitor] の設定で監視するディレクトリ設定ができます。
![EditorSetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/8de44d93-8d01-b301-f8e1-d451fa2a4d58.png)

再インポートが検出されると確認ダイアログがでます。
![import_dialog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/4ab4caa5-854e-cb35-7e8b-4868a29b5f50.jpeg)



# データテーブルからデータの取得
MyDataTableに保持されたデータテーブルからパラメータを取得する例です。

```cpp:.h
// データテーブル
UPROPERTY(Category = "Test", EditAnywhere, BlueprintReadWrite)
class UDataTable*	MyDataTable;

```

```cpp:.cpp
// データテーブルからパラメータを取り出す
if (MyDataTable != nullptr) {
	// データテーブル取得
	auto _Names = MyDataTable->GetRowNames();
	for (int _Lp = 0; _Lp < _Names.Num(); _Lp++)
	{
		auto _Record = MyDataTable->FindRow<FMyDataTable>(_Names[_Lp], FString());
		// 表示
		UE_LOG(LogTemp, Log, TEXT("%d, %f"), _Record->Id, _Record->Param);
	}
}
```


# パラメータ用のデータテーブル運用について
データテーブルをエディタで編集することが可能ですが、別途外部データからの運用を考えてみます。公式にはcsvからのインポートする方法が紹介されています。

## Excel -> JSONでの運用例
以下の様なパラメータテーブルを作り、マクロを有効にして[JSON出力]ボタンを押したらJSONデータで出力できるようにします。
JSONへの出力方法は外部ツールを別途つくるなり方法はいろいろ考えられます。

![excel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/bf4f72c2-bf05-af9d-11f3-0031da6b6fd8.png)

別途JSONへの出力する方法を用意してバッチ等で呼び出す方法を取る場合はボタンに割り振るマクロは以下の様になります。VBに慣れているのであれば直接書けると思います。

```vb:VBAマクロから外部バッチ実行
Sub CommandExec()
    Dim processId  As Double
    Dim batPath
    
    ' 現在のマクロ実行パスからバッチ実行
    batPath = ThisWorkbook.Path & "\myparam_conv.bat"
    
    processId = Shell(batPath)
End Sub
```

JSON出力すると以下の様になります。

```json:_test.json
[
	{
		"Name": "01",
		"Kind": "りんご",
		"Param": 500,
		"Num": 3,

	},
	{
		"Name": "02",
		"Kind": "みかん",
		"Param": 700,
		"Num": 2,
	},
	{
		"Name": "03",
		"Kind": "ぶどう",
		"Param": 700,
		"Num": 1,
	}
]
```

このJSONを自動インポートして、DataTableに再インポートするように UEエディタ設定を行うと、余計な操作が減るためパラメータ調整のイテレーションが減ると思います。

JSONからDataTableへインポートする時、DataTableを定義している構造体のメンバ名とJSONメンバ名が一致しているものだけ取り込まれます。
上記で定義した FMyDataTable の場合は一致するメンバ名が[Param]だけなので以下のJSONからそこだけ取得されるので注意が必要です。
（ExcelからJSONに出力する際にチェック機能などがあると良いと思います。）


# 備考
## JSONを変更して再インポートをしても反映されない場合
データテーブルを右クリックして `インポートアセット` のメニューがグレーアウトしている状態だと思われます。

![example00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/082e2117-5d63-a154-2723-5bcdf6fcb429.jpeg)

この場合は、データテーブルを開いてエディタ上から
[アセット] → [〇〇を再インポート] を選択して再インポートをします。

![example01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/fcbaaf53-02e1-fe26-078d-ee921a59d2fe.jpeg)

これで `インポートアセット` のメニューが選択できるようになり、JSONの変更を再インポートしても反映されるようになります。


# まとめ
パラメータなどは独自のアセットを作成するより、DataTableで間に合う場合が多いと思いますが、そのままではやや扱いにくいです。
公式にはcsvへエクスポートをするエクセルマクロファイルのサンプルがありますが、データ整合性なども考えJSONでの運用をしてみました。
Pluginなどにすでにありそうな気もしますが。:grinning: