8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Unreal Engine (UE)Advent Calendar 2024

Day 2

[UE5] ブループリントをスマートに!役立つ自作ノードアイデア集

Last updated at Posted at 2024-12-01

BP関数ライブラリで簡単に作れる、便利な自作ノードを紹介します!

AC2024FunctionLibrary.h
UCLASS()
class UAC2024FunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
}

BlueprintFunctionLibrary は、静的関数を追加するだけで簡単にブループリント公開ができるクラスです。今回は UE5 と C++ の機能を利用して、いくつか便利なノード作成を解説します。

Merge

image.png
2つの実行ピンを統合し、結果を bool で返すノードです。
ブループリントでは、返り値を実行ピンで分離することが多いですが、その後に共通処理を行いたい場合がよくあります。このノードを使えば、複雑な処理をシンプルにまとめることが可能です。
image.png
例えば入力イベントを取得する場合。
PressRelease を統合して、ひとつの結果として扱えます。

UAC2024FunctionLibrary.h
UENUM()
enum class EAC02024Bool : uint8
{
	A UMETA( DisplayName = "True" ),
	B UMETA( DisplayName = "False" ),
};

class UAC2024FunctionLibrary : public UBlueprintFunctionLibrary
{
    // 略...

	UFUNCTION( BlueprintCallable, Category = "Utilities|FlowControl",
		meta = ( ExpandEnumAsExecs = "InputPin", KeyWords = "branch" ) )
	static bool Merge( EAC02024Bool InputPin );
};
UAC2024FunctionLibrary.cpp
bool UAC2024FunctionLibrary::Merge( const EAC02024Bool InputPin )
{
	return InputPin == EAC02024Bool::A;
}

とってもカンタン!

一時変数を作りたくない

image.png
これでも結果は変わらないんですが、イベントグラフだとクラスのメンバー変数を使用する必要がありますから。変数リストが汚れるのは気になりますしね。

Has Any Chance

image.png
ランダムな結果や、再現性が難しい実装をテストする際に役立つノードです。フラグの切り替えは後述のコンソールコマンドで実行します。
image.png
このノードでは、フラグの切り替えによってどんな結果も 成功 失敗 で上書きできるため、デバッグが非常に簡単になります。パリィのようなジャスト入力も目押しに頼らなくていいんです。

UAC2024FunctionLibrary.h
class UAC2024FunctionLibrary : public UBlueprintFunctionLibrary
{
    // 略...
    UFUNCTION( BlueprintCallable, meta = ( CompactNodeTitle = "Any Chance" ) )
	static bool HasAnyChance( bool bDefaultValue );
};
UAC2024FunctionLibrary.cpp
namespace
{
TOptional<bool> AnyChance;
}	 // namespace

static FAutoConsoleCommand AnyChanceCommand( TEXT( "AnyChance" ), TEXT( "enable/disable any condition" ),
	FConsoleCommandWithWorldArgsAndOutputDeviceDelegate::CreateLambda(
		[]( const TArray<FString>& Args, UWorld* World, FOutputDevice& Output )
		{
			if ( Args.IsValidIndex( 0 ) )
			{
				int32 Flag = 0;
				FDefaultValueHelper::ParseInt( Args[0], Flag );

				AnyChance = static_cast<bool>( Flag );
			}
			else
			{
				AnyChance.Reset();
			}
		} ),
	ECVF_Cheat );

bool UAC2024FunctionLibrary::HasAnyChance( const bool bDefaultValue )
{
	// 値が存在しない(NullOptである)場合はDefaultValueを返す
	return AnyChance.Get( bDefaultValue );
}

コンソールからフラグを切り替える

コンソールコマンドは開発者がエンジンのさまざまな機能や設定にアクセスし、ゲームの挙動を調整したりデバッグしたりするための強力なツールです。ゲームまたはエディタ内のコンソールウィンドウにコマンドを入力することで動作します。

image.png
ゲーム内では @ キーを押すことで、画面下部にコンソールウィンドウを表示します。

  • AnyChance 1 すべてのフラグを強制的に ON
  • AnyChance 0 すべてのフラグを強制的に OFF
  • AnyChance フラグの上書きをリセット

FAutoConsoleCommand

UE5 でコンソールコマンドを簡単に定義するためのテンプレートクラスです。これを使えば、デバッグや設定変更用のカスタムコマンドを手軽に追加できます。さらに TAutoConsoleVariable を活用すれば、値を設定するコマンドも簡単に作成可能です。

TOptional とは?

TOptional は、UE5 標準のテンプレートクラスで、「値が存在するか」を表現するためのクラスです。C++ 標準の std::optional に似ており、値が存在しない場合にも一つの変数で対応できる便利な仕組みです。

// OLD
bool bAnyChance = false;
bool bValidAnyChance = false;

// NEW
TOptional<bool> AnyChance;

これら 2 つの状態を、ひとつの変数として管理できます。

BlueprintCallable にする理由

Break BasicParticleData から繋いだ Position Velocity が、それぞれ別々の配列要素を指す場合がある、ってやつですね。

  • BlueprintPure 関数は、副作用を持たない計算用の関数として設計されています
  • この特性から、エンジンは必要に応じて関数を再評価することがあります
  • たとえば同じピンから複数回使用される場合、関数の呼び出しも複数回実行される可能性があります

乱数を扱う場合は BlueprintCallable を使い、結果をキャッシュすることで安全性を確保できます。

DrawDebugName

image.png
トレースなどのデバッグ表示を可視化するノードです。
image.png
デバッグ情報は常に表示されると邪魔になる一方で、確認作業には欠かせないものです。
image.png

UAC2024FunctionLibrary.h
class UAC2024FunctionLibrary : public UBlueprintFunctionLibrary
{
	// 略...
	UFUNCTION( BlueprintPure )
	static EDrawDebugTrace::Type DrawDebugName( FName DebugName, float& OutDuration );
};
UAC2024FunctionLibrary.cpp
namespace
{
TMap<FName, float> DebugDrawNames;
}	 // namespace

static FAutoConsoleCommand DebugDrawNameCommand( TEXT( "DebugDrawName" ), TEXT( "visualize debug drawings" ),
	FConsoleCommandWithWorldArgsAndOutputDeviceDelegate::CreateLambda(
		[]( const TArray<FString>& Args, UWorld* World, FOutputDevice& Output )
		{
			if ( Args.IsValidIndex( 0 ) )
			{
				const FName DebugName = *Args[0];

				if ( Args.IsValidIndex( 1 ) )
				{
					float Duration = 0.f;
					FDefaultValueHelper::ParseFloat( Args[1], Duration );

					DebugDrawNames.FindOrAdd( DebugName ) = Duration;
				}
				else
				{
					DebugDrawNames.Remove( DebugName );
				}
			}
		} ),
	ECVF_Cheat );

EDrawDebugTrace::Type UAC2024FunctionLibrary::DrawDebugName( const FName DebugName, float& OutDuration )
{
	if ( const float* Duration = DebugDrawNames.Find( DebugName ) )
	{
		OutDuration = *Duration;
		return OutDuration > 0.f ? EDrawDebugTrace::Type::ForDuration : EDrawDebugTrace::Type::ForOneFrame;
	}

	return EDrawDebugTrace::None;
}

image.png
名前ごとにフィルタをかけて、表示のオン/オフを切り替えることが可能です。

GameplayTag を使用して階層ごとに管理すれば、さらに便利になるかもしれません。

まとめ

自分の中の\あったらいいな/をカタチにしてみました。
「こんなノードも便利だよ」「こういう作り方もある」など、ぜひ教えてしていただけると嬉しいです!

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?