UE4 コンソールコマンドとコンソール変数についてのメモ

# 概要
UnrealEngineでのコンソールコマンドとコンソール変数のメモ書きです。
自前で定義するコンソールコマンドとコンソール変数の追加方法を記載しています。


## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.25


## 参考
[UE4公式 : IConsoleManager](https://docs.unrealengine.com/en-US/API/Runtime/Core/HAL/IConsoleManager/index.html)
[UE4公式 : C++ のコンソール変数](https://docs.unrealengine.com/ja/Programming/Development/Tools/ConsoleManager/index.html)
[UE4公式 : EConsoleVariableFlags](https://docs.unrealengine.com/en-US/API/Runtime/Core/HAL/EConsoleVariableFlags/index.html)
[UE4 のコンソールにユーザー定義のコマンドを追加する方法](https://usagi.hatenablog.jp/entry/2017/06/06/141700)
[[UE4] コンソールコマンドを追加する方法](https://historia.co.jp/archives/839/)


# コンソールコマンド
UEにはコンソールにてテキスト入力でコマンドを実行する機能があります。
アウトプットログに入力ボックスがあります。

![ConsoleCommand_OutputLog.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/afbdd778-b553-0737-f6e1-8e1ff4cbdf19.jpeg)


あるいはエディタにて `@` にて入力コマンドラインが表示されます。

![ConsoleCommand.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/b2fa662c-e735-1662-dd03-cf3165fc287a.jpeg)

コンソールコマンドはデバッグ機能を別途仕込むことができ、デフォルトで用意されているものでよく使われるものはパフォーマンス表示の `stat unit` や デバッグカメラ機能の `ToggleDebugCamera` やカルチャ変更の `culture=ja` 等など色々あります。

### ヘルプテキスト（説明文）
コンソールコマンドに引数`?`を入れるとヘルプテキスト（説明文）が表示されます。自作コマンドの場合は表示したいテキストを登録時に設定ができます。



## 自作コンソールコマンドの追加
### コマンド作成と登録
コンソールマネージャ `IConsoleManager` に対して登録ができます。
メソッド指定とラムダ式指定をそれぞれ引数あり、なしで４つ登録してみます。
以下コード例。

```cpp:.h
UCLASS()
class TEST_API AMyActor
{
	GENERATED_BODY()

// ..省略..

	// 実行されるメソッド（引数なし）
	UFUNCTION(BlueprintCallable, Category = "Test")
		void ExecCmd();
	// 実行されるメソッド（引数付き）
	UFUNCTION(BlueprintCallable, Category = "Test")
		void ExecCmd2(const TArray<FString>& Args);
};
```

`RegisterConsoleCommand` にてコマンドを登録します。
第1引数がコマンド名、第2引数が説明文、第3引数に実行関数を追加します。

```cpp:.cpp
#include "Runtime/Core/Public/HAL/IConsoleManager.h"

AMyActor::AMyActor(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	if (!IsRunningCommandlet()) {
		// コマンド登録（引数なし、ラムダ式）
		IConsoleManager::Get().RegisterConsoleCommand(
			TEXT("MyTestCmd1")
			,TEXT("説明：テストコマンド引き数なし")
			,FConsoleCommandDelegate::CreateLambda( [&](){ UE_LOG(LogTemp, Log, TEXT("MyTestCmd1!")); } )
			,ECVF_Default
		);

		// コマンド登録（引数なし）
		IConsoleManager::Get().RegisterConsoleCommand(
		TEXT("MyTestCmd2")
		,TEXT("説明：テストコマンド引き数なし")
		,FConsoleCommandDelegate::CreateUFunction(this, TEXT("ExecCmd") )
		,ECVF_Default
		);

		// コマンド登録（引数付き、ラムダ式）
		IConsoleManager::Get().RegisterConsoleCommand(
			TEXT("MyTestCmdArg1")
			,TEXT("説明：テストコマンド引き数あり")
			,FConsoleCommandWithArgsDelegate::CreateLambda( [&](const TArray<FString>& _Args){ UE_LOG(LogTemp, Log, TEXT("MyTestCmdArg1!:ArgNum=%d"), _Args.Num()); } )
			,ECVF_Default
		);

		// コマンド登録（引数付き）
		IConsoleManager::Get().RegisterConsoleCommand(
		TEXT("MyTestCmdArg2")
		,TEXT("説明：テストコマンド引き数あり")
		,FConsoleCommandWithArgsDelegate::CreateUFunction(this, TEXT("ExecCmd2") )
		,ECVF_Default
		);
	}
}

// 実行されるメソッド（引数なし）
void AMyActor::ExecCmd()
{
	UE_LOG(LogTemp, Log, TEXT("ExecCmd"));
}

// 実行されるメソッド（引数付き）
void AMyActor::ExecCmd2(const TArray<FString>& _Args)
{
	FString _Str = FString("Arg:");
	
	for (int32 _Lp=0; _Lp<_Args.Num(); _Lp++)
	{
		_Str += _Args[_Lp] + ",";
	}
	
	UE_LOG(LogTemp, Log, TEXT("ExecCmd2 %s"), *_Str);
}
```

### 実行テスト
エディタでコマンド入力ができるようになります。
![ConsoleCommand_Input.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/9ef8ca2b-7bd2-426a-fd60-89cfd64979f7.jpeg)

実行結果が以下の様になります。
![Result.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/044cbe59-fee7-09bb-46ca-57f4e6d90f82.jpeg)



## エディタのコマンドライン以外でのコンソールコマンド実行
### BPでのコンソールコマンドの実行
`ExecuteConsoleCommand` ノードで実行ができます。

![ExecConsoleCommandBP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/4d6d570c-a248-8242-b170-e00fbf33a0d2.jpeg)


### C++でのコンソールコマンドの実行
プレイヤーコントローラーに対し、`ConsoleCommand` で実行ができます。
以下コード例

```cpp:.cpp
// PlayerController に対して実行
_MyPlayerController->ConsoleCommand("MyTestCmd1");

// ワールドからプレイヤーコントローラーを取ってくる
GetWorld()->GetFirstPlayerController()->ConsoleCommand("MyTestCmd2");

```


# コンソール変数
コンソール変数はコンソールマネージャ(`IConsoleManager`)が持つ変数でエンジン全体に及ぶデータ型(int, float, string)を持つことができるようです。
この値を設定/取得することでコンソールコマンドのふるまいを変えるなどの使い方ができます。
以下はコマンドラインでの入力例です。

```text:コンソール変数入力例
// コンソール変数 MyConsoleVar の値を出力する
MyConsoleVar

// コンソール変数 MyConsoleVar の値を10に設定する
MyConsoleVar 10

// コンソール変数 MyConsoleVar のヘルプを出力する
MyConsoleVar ?
```


## 自作コンソール変数の追加
### 数定義と登録１
`TAutoConsoleVariable` 型を staticで定義します。第1引数がコンソール変数名、第2引数が初期値、第3引数がコンソール変数の説明です。

```cpp:.cpp
static TAutoConsoleVariable<int32> CVarMyConsoleVar(
TEXT("MyConsoleVar"),
1,
TEXT("My Console Var Test."));
```

### 変数定義と登録２
関数にて登録をすることもできます。

```cpp:.cpp
#include "Runtime/Core/Public/HAL/IConsoleManager.h"

AMyActor::AMyActor(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	if (!IsRunningCommandlet()) {
		// コンソール変数の登録
		IConsoleManager::Get().RegisterConsoleVariable(TEXT("MyConsoleVar2"),
			1.5f,
			TEXT("My Console Var2 Test."));	
	}
}
```

## 登録の確認
エディタでコンソール変数が登録されているのが確認できます。
![MyConsoleVar.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/673091ef-ab60-8ec3-0ab8-dc642d18ac32.jpeg)

変数の値も確認します、初期値が設定されているのが確認できます。
![MyConsoleVar_Output.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/63db2e4c-0d40-bf49-4f1e-a1b293ff635d.jpeg)



## コンソール変数の取得
定義したコンソール変数を取得します。
以下コード例。

```cpp:.cpp
// TAutoConsoleVariable型定義から取得する
int32 _MyConsoleVar = CVarMyConsoleVar.GetValueOnGameThread();

// コンソールマネージャ経由で取得する
auto _CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("MyConsoleVar2"));
float _MyConsoleVar2 = _CVar->GetFloat();

UE_LOG(LogTemp, Log, TEXT("MyConsoleVar=%d, MyConsoleVar2=%f"), _MyConsoleVar, _MyConsoleVar2);

```



# まとめ
デフォルトで用意されているコンソールコマンド以外にも機能を追加できるため、デバッグが（たぶん）捗ります。
ただデフォルトで用意されているコンソールコマンド群がたくさんあるため使いこなせていないのですが。。:expressionless: