【UE4】ConsoleCommand「CE,KE」について【★★☆】

※この記事で使用しているUnrealのVersionは04.24.0 Preview3です。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト

今回は、Console Command 「CE(Custom Event)」と「KE(Kismet Event)」 についてのお話です。

機能実装時のデバッグなんかでみなさんお世話になっていると思います。

CE(CustomEvent)コマンドについて レベル【★★☆】

CEは、Level Blueprint上にあるCustom Eventを呼び出すことが出来ます。
→”CE EventName”の形で入力します。

↓適当なLevelBlueprint上に処理を書いたもの。

↓実行中にConsole Command「CE TestEvent」と入力して実行したもの。
※Console Commandはプレイ中に「@」キーを押すと入力できるようになります。

https://kinnaji.com/wp-content/uploads/2019/11/KA_KismetEvernt1.mp4

※ちなみに、ConsoleCommandは「OutputLog」ウィンドウの「Cmd」部分でも実行できます。

※また、「Execute Console Command」というBlueprint関数でも実行できます。

また、CustomEvent側に引数がある場合は、Spaceで区切ることで、引数も指定できます。
※指定しないと、その引数の型のDefault値がそのまま入ります。

Stringの引数を追加した場合。

https://kinnaji.com/wp-content/uploads/2019/11/Event03.mp4

また、ConsoleCommandの性質上、引数の指定は文字列で行いますが、IntegerやENUM,Vector,Transformなども文字列で入力できます。

Vectorの例:
CE TestEvent (X=1.000000,Y=2.000000,Z=3.000000)

Transform型の例:
CE TestEvent (Rotation=(X=1.000000,Y=2.000000,Z=3.000000,W=4.000000),Translation=(X=5.000000,Y=6.000000,Z=7.000000),Scale3D=(X=8.000000,Y=9.000000,Z=10.000000))

※型ごとの入力規則を知るには、任意の型を含んだDataTableを作成し、それをCSV出力すると大体わかります。

またObject型などの参照も文字列で入力できます。
参照の場合は基本的にObjectPathを入力します。

Assetの参照を指定する例:
CE TestEvent /Game/NewMap.NewMap

※指定するAssetObjectは、/Game直下にある「NewMap」というレベルアセット

https://kinnaji.com/wp-content/uploads/2019/11/CCEvent_10.mp4

ちなみに、今までの説明の動画でもやりましたが、CEコマンドは、ConsoleCamannd上でCEと入力するだけで、実行できるイベント一覧が入力ボックスの上に出てきます。
そして、キーボードの↑↓で入力せずにイベントを選択することも出来ます。

と少し余談ですが、記事を書いていて気になったのが、「ExecuteUbergraph_~~~~」というイベントが候補として出てきました。
ん? そんなイベントを追加した覚えはないぞ…

しかもどうやら引数に「Entry Point」なるIntegerを添えて発行するようです。

試しに引数に「1」を指定すると、普通に先ほど作成したイベントが発行されました(引数「10」や「11」 でも同じイベントが発行された )
さらに「2」や「3」とかを指定するとクラッシュ、「0」だとPIEErrorで強制的にプレイがストップしました…。

一応このイベントは、どうやらLevel Blueprintに何かしらの処理を書くと使えるようになるようです。

また面白いのが、引数関係なくBlueprint Editorで「最後に書いた処理」の部分を起点にして実行してくれるということです。
どういうことかというと、

上記の順番でBlueprintを書き、 「ExecuteUbergraph_NewMap 1」と実行すると…

https://kinnaji.com/wp-content/uploads/2019/11/Event02.mp4

お判りいただけましたでしょうか?

5番目に書いた「Print String」から処理が開始していき、次にある4番目に書いたPrint Stringを実行して終わりました。

まあわかったのはこの程度で、いろいろ調べようとしましたがよくわかりませんでした。誰か教えて…。

KE(KismetEvent)について レベル【★★☆】

KEコマンドは、CEコマンドよりも範囲が広く、レベルBP以外にもレベル内にあるアクターなどのBPにイベントを飛ばすことができます。

また、CustomEventだけではなく、関数名を指定することで、関数を直接呼び出せます。
→”KE * EventName”の形で呼び出せます。
尚、CEイベント同様スペース区切りで引数も指定できます。

試しに適当にActorクラスを継承したクラスを作成します。

これを、適当なレベル上に置いてみましょう。

そして、作成したBPをダブルクリックで開いて、新しく関数を追加します。
中身はとりあえずPrintStringのみ。

そしたらプレイインして、「KE * TestFunction」と入力してみましょう。

https://kinnaji.com/wp-content/uploads/2019/11/CCEvent_01-1.mp4

※KEコマンドは、CEコマンドのように実行できるコマンドの候補は出ません。

ちなみに「*」の部分は、対象のClassNameを指定することで、イベントを発行する先を限定することができます。

例えば、BP_Testというアクタークラスのみにイベントを発行したいなら、「KE BP_TestEvent_C TestFunction」のような形になります。
(クラス名 + “_C”で指定)
一部の記事にはObjectName指定と書いてありますが、ObjectNameを指定すると以下のようなWarningが出て実行できないようでした(過去ではObjectName指定でできた?)

LogUObjectHash: Warning: Ambiguous search, could be BP_Test_C /Game/NewMap.NewMap:PersistentLevel.BP_Test_2 or BP_Test_C /Game/UEDPIE_0_NewMap.NewMap:PersistentLevel.BP_Test_2

また、ObjectPathやDisplayNameでも試しましたが、成功はしませんでした。

ちなみに、MultiPlay(複数人プレイ) 時( CE KEのどちらも )
・@からの実行の場合&ExecuteConsoleCommandからの実行の場合
→実行したウィンドウのやOutputLogからの実行だと、実行したClient側またはServer側で処理が実行されます。

https://kinnaji.com/wp-content/uploads/2019/11/CCEvent_05.mp4

・OutputLogからの実行の場合
→Listen ServerならばServer上で、Dedicate Serverならば一番下位のClientで実行されるようです。

ListenServerの場合

https://kinnaji.com/wp-content/uploads/2019/11/AGDRec_20191120_205641.mp4

DedicateServerの場合

https://kinnaji.com/wp-content/uploads/2019/11/AGDRec_20191120_205754.mp4

Server側でCommandを実行したい場合は、一度Server側にRPCしてからServer側でExecuteConsoleCommandを実行したりするといいでしょう。

また、もしC++を使うなら、Object指定でEventNameで関数を実行したい場合は、ScriptCore.cppにある「CallFunctionByNameWithArguments」という関数を使えば、UObjectを対象にEventNameを指定することでイベントを実行してくれます。
FLIBなどから呼び出せるようにしておくと便利です。
(ちなみにKEコマンドの中でもCallFunctionByNameWithArgumentsを実行しています)

UObjectを対象にEventNameを指定することでイベントを実行してくれます。
FLIBなどから呼び出せるようにしておくと便利です。
(ちなみにKEコマンドの中でもCallFunctionByNameWithArgumentsを実行しています)

↓例

FLIB_Utility.h

#pragma once

#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "FLIB_Utility.generated.h"

/**
 * 
 */
UCLASS()
class UFLIB_Utility : public UBlueprintFunctionLibrary
{
	GENERATED_UCLASS_BODY()
public:
		UFUNCTION(BlueprintCallable, Category = "MyBPLibrary")
		static void CallEventByEventName(UObject* Target, FString Name);

};

FLIB_Utility.cpp

#include "FLIB/FLIB_Utility.h"

void UFLIB_Utility::CallEventByEventName(UObject* Target, FString Name)
{
	const TCHAR* Cmd = *Name;

	if (Target)
	{
		Target->CallFunctionByNameWithArguments(Cmd, *GLog, Target, true);
	}
}

かなり雑な説明ですが以上です。

※この記事のサンプルプロジェクトは以下URLにアップされています。
サンプルプロジェクト