ぼっちプログラマのメモ

UE4とかVRとかについて書いたり書かなかったり。

特定のBlueprint , UMG にて Tickノードが使われているかをチェックする方法について

はじめに

Tick ノードは便利ではありますが、多くのActor, UMG が Tick ノードを使用するとパフォーマンス面で問題が発生する可能性が出てきます。
(特にモバイル や コンソールタイトルにて)

Unreal Engine 4を使って地球を衛る方法 ( p109 より Tickの話 )
UE4におけるレベル制作事例 ( p14 より Tickの話 )
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック ( p193 より Tickの話 )

そして、プロジェクト終盤で Tick 負荷が問題になると大変なことになりがちです。なぜなら、Tickを使わないように実装を大きく変更することになるためです。そのため、日々 Tickをなるべく使わないように心がけたり、Tick警察の方が目を光らせることが重要になります。

Tick警察のお供として有名なのが、 dumpticks コマンドです。これで ゲーム中に動いている Tick を洗い出すことができます。

f:id:pafuhana1213:20200626184626p:plain
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック p195より

しかし、ゲームを実際に動かす必要があるため、プロジェクトの規模が大きくなるほどチェックが大変になります。また、ログに出力されるだけなので、例えばCSVなどにまとめたい場合は抽出・整形する必要があります。

また、「Find In Blueprints」機能を使って 文字列検索から Tick ノードを抽出することもできますが、全BPが対象になるので時間がかかったり、結果をまとめづらいなどの問題があります。

f:id:pafuhana1213:20200626191716p:plain

そこで今回紹介したいのが、特定のBP・UMG アセットのEvent Graph にて Tick ノード が存在するか否かを自動的にチェックする方法です。こちらであればゲームを実際にプレイする必要はありませんし、その結果をCSV などに自動的にまとめることができます。


Tick ノード が存在するかをチェックする方法について

C++を使いますが、やってることとは簡単で「特定のBP・UMGが持つ全イベントノードの中に Tick ノードが含まれているかをチェックする」だけです

// UnrealEd, BlueprintGraph を Build.cs に追加する必要あり

#include "Kismet2/BlueprintEditorUtils.h"
#include "K2Node_Event.h"

bool UMyBlueprintFunctionLibrary::CheckHasTickNode(const UObject* InObject)
{
	if (const UBlueprint* Blueprint = Cast<UBlueprint>(InObject))
	{
		TArray<UK2Node_Event*> Events;
		FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Event>(Blueprint, Events);
		for (UK2Node_Event const* const Event : Events)
		{
			FName EventMemberName = Event->EventReference.GetMemberName();
			if (EventMemberName == FName(TEXT("Tick")) || EventMemberName == FName(TEXT("ReceiveTick")))
			{
				return true;
			}
		}
	}
	return false;
}

ここで重要なのが、

FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Event>(Blueprint, Events);

です。このノードを使うことでそのBPが持つイベントノードの名前を配列で取得できます。ちなみに、 例えば以下のようにすると Timeline ノードの名前だけ取ってこれます。

FBlueprintEditorUtils::GetAllNodesOfClass<UK2Node_Timeline>(BlueprintObj, AllTimelines);


そして、以下のようにノードを組むことで、自身のプロジェクトにおける全BP・UMG に対して Tick ノードが使われているかをチェックできます。
f:id:pafuhana1213:20200626191230p:plain
Check Tick > BlueprintUE.com | PasteBin For Unreal Engine 4

今回は Tick ノードのみのチェックでしたが、 上記コードの TEXT 部分を別の文字列に変えることで 別のノードの有無もチェックすることができます 。是非色々試してみてください!

おまけ① 対象のノードがアクティブか非アクティブかを判定する方法について

新規作成したBPの場合、 Tickノードは以下のようにグレーアウト状態になっています。これは非アクティブ状態で処理は走りません。
f:id:pafuhana1213:20200626192025p:plain

そして、先程のソースコードにて対象のノードが非アクティブな場合は スルーする処理にしたい場合は IsNodeEnabled 関数を使用します。

if (EventMemberName == FName(TEXT("Tick")) || EventMemberName == FName(TEXT("ReceiveTick")))
{
	if (!Event->IsNodeEnabled())
	{
		return false;
	}

	return true;
}

IsNodeEnabled の中身は以下の通り

bool IsNodeEnabled() const
{
	return (EnabledState == ENodeEnabledState::Enabled)	|| ((EnabledState == ENodeEnabledState::DevelopmentOnly) && IsInDevelopmentMode());
}

ただし、ノードが非アクティブな状態でも 基底側の Tick は実行されてしまうので注意です。

f:id:pafuhana1213:20200626192445p:plain
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック p194 より

おまけ② ノードの名前( MemberName )の調べ方

今回のコードでは、判定に使うノードの名前として MemberName を使っています。

 FName EventMemberName = Event->EventReference.GetMemberName();

そして、特定のノードにおける MemberName は ノードをコピーした際にクリップボードを確認することですぐ分かります。例えば Get All Actor of Class ノードの MemberNameを知りたいときは…

f:id:pafuhana1213:20200626193439g:plain

となります。

おまけ③ UMGにおけるTickについて

少しややこしいです。先日神資料が公開されたのでぜひご確認くださいまし。

www.slideshare.net
p112より

おまけ④ FBlueprintEditorUtils はいいぞ

今回使用した FBlueprintEditorUtils には GetAllNodesOfClass 以外にも様々な便利機能が沢山用意されています。 Engine\Source\Editor\UnrealEd\Public\Kismet2\BlueprintEditorUtils.h を眺めると色々と楽しいと思います。




おしまい