はじめに
Tick ノードは便利ではありますが、多くのActor, UMG が Tick ノードを使用するとパフォーマンス面で問題が発生する可能性が出てきます。
(特にモバイル や コンソールタイトルにて)
Unreal Engine 4を使って地球を衛る方法 ( p109 より Tickの話 )
UE4におけるレベル制作事例 ( p14 より Tickの話 )
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック ( p193 より Tickの話 )
そして、プロジェクト終盤で Tick 負荷が問題になると大変なことになりがちです。なぜなら、Tickを使わないように実装を大きく変更することになるためです。そのため、日々 Tickをなるべく使わないように心がけたり、Tick警察の方が目を光らせることが重要になります。
Tick警察のお供として有名なのが、 dumpticks コマンドです。これで ゲーム中に動いている Tick を洗い出すことができます。
[CEDEC2018] UE4で多数のキャラクターを生かすためのテクニック p195より
しかし、ゲームを実際に動かす必要があるため、プロジェクトの規模が大きくなるほどチェックが大変になります。また、ログに出力されるだけなので、例えばCSVなどにまとめたい場合は抽出・整形する必要があります。
また、「Find In Blueprints」機能を使って 文字列検索から Tick ノードを抽出することもできますが、全BPが対象になるので時間がかかったり、結果をまとめづらいなどの問題があります。
そこで今回紹介したいのが、特定の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 ノードが使われているかをチェックできます。
Check Tick > BlueprintUE.com | PasteBin For Unreal Engine 4
今回は Tick ノードのみのチェックでしたが、 上記コードの TEXT 部分を別の文字列に変えることで 別のノードの有無もチェックすることができます 。是非色々試してみてください!
おまけ① 対象のノードがアクティブか非アクティブかを判定する方法について
新規作成したBPの場合、 Tickノードは以下のようにグレーアウト状態になっています。これは非アクティブ状態で処理は走りません。
そして、先程のソースコードにて対象のノードが非アクティブな場合は スルーする処理にしたい場合は 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 は実行されてしまうので注意です。
おまけ② ノードの名前( MemberName )の調べ方
今回のコードでは、判定に使うノードの名前として MemberName を使っています。
FName EventMemberName = Event->EventReference.GetMemberName();
そして、特定のノードにおける MemberName は ノードをコピーした際にクリップボードを確認することですぐ分かります。例えば Get All Actor of Class ノードの MemberNameを知りたいときは…
となります。
おまけ④ FBlueprintEditorUtils はいいぞ
今回使用した FBlueprintEditorUtils には GetAllNodesOfClass 以外にも様々な便利機能が沢山用意されています。 Engine\Source\Editor\UnrealEd\Public\Kismet2\BlueprintEditorUtils.h を眺めると色々と楽しいと思います。
おしまい