【UE5】UDeveloperSettingsでデバッグ機能を実装する方法

プログラマーの尾関です。

今回は UDeveloperSettingsを使ってデバッグ機能を作る方法について紹介したいと思います。

  • 動作確認バージョン: UE5.5.4

UDeveloperSettingsとは

UDeveloperSettingsは、プロジェクトやエディタの設定項目を簡単に追加・管理できるC++クラスです。これを継承したクラスを作成し、UPROPERTYで設定したい変数を宣言するだけで、Unreal Editorの「プロジェクト設定」や「エディタ設定」に自作の設定項目が自動的に追加されます。

特徴とメリット

UDeveloperSettings の特徴と、使用するメリットについては以下のとおりです。

  • UDeveloperSettingsを継承したクラスを作るだけで、設定項目がエディタの設定画面に自動で表示される
  • 設定値はiniファイル(例:DefaultGame.iniやDefaultEngine.ini、プラグイン固有のiniなど)に保存され、エディタや実行時に参照・変更できる
  • GetDefault<>()関数でどこからでも設定値にアクセスできるため、C++やBlueprintから簡単に利用可能
  • カテゴリやセクション名、説明文などもオーバーライドで細かく指定できる
  • プラグイン単位で独自の設定ファイルを持たせることもでき、設定の分離や管理が容易

開発中のデバッグ機能を DataAsset や DataTable に実装すると、複数人開発の場合にファイルロックがされたり、対象のアセットを探すのが少し手間です。それに対して、UDeveloperSettingsを使うと「プロジェクト設定から簡単に探せる」「iniファイルなので変更差分がわかりやすい」「場合によってファイルロックを無効にして管理しても良い」「実装が楽 」というのが個人的に考えるメリットです。

Information

ただ UDeveloperSettingsでも iniファイルが競合する問題があるため、本格的にデバッグ機能として実装するのであればユーザーごとに設定を管理できるセーブデータに保存するのが良いかもしれません。

またUDeveloperSettingsは「設定情報」であり、ゲーム実行中は基本的に値を書き換えられません。一応、CVar (コンソール変数) を使って書き換えることはできますが、UDeveloperSettingsの仕様上は非推奨のようです。

作成手順

C++コードの追加

UDeveloperSettingsは C++ での実装が必要なため、メニューから「ツール > 新規C++クラス」でコードを追加します。

親クラスには「すべてのクラス」から "UDeveloperSettings" を選んで作成します。

クラスのファイル名は「CPP_DebugSettings」としました。

なお、Unreal Engineのエディターを使わずに C++ コードを追加する場合には *.uproject や Build.cs にモジュールの定義を追加する必要があります。

今回の手順では *.uproject に "DeveloperSettings" の定義が追加されていて問題なくビルドできました。

{
	"FileVersion": 3,
	"EngineAssociation": "5.5",
	"Category": "",
	"Description": "",
	"Modules": [
		{
			"Name": "Test_003",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"AdditionalDependencies": [
				"DeveloperSettings" // ←DeveloperSettingsを使用する
			]
		}
	],
	"Plugins": [
		{
			"Name": "ModelingToolsEditorMode",
			"Enabled": true,
			"TargetAllowList": [
				"Editor"
			]
		}
	]
}

C++ (UDeveloperSettings) コードの実装

まずはデバッグ設定の保存先の指定をします。

/**
 * デバッグ設定.
 */
UCLASS(Config=MyConfig, DefaultConfig, meta=(DisplayName="デバッグ設定"))
class TEST_003_API UCPP_DebugSettings : public UDeveloperSettings
{
	GENERATED_BODY()
	
public:
	// カテゴリ名.
	virtual FName GetCategoryName() const override { return "My Debug Settings"; }

};
  • "Config=MyConfig" は保存する iniファイルの名前です。この指定により "MyConfig.ini" として設定が保存されます
  • "DefaultConfig" はデフォルト設定を "DefaultMyConfing.ini" に保存するという指定です
  • "meta=(DisplayName=" はプロジェクト設定の項目として表示される名称です
  • "FName GetCategoryName()" はプロジェクト設定のカテゴリとして表示される名称です

まだ何も実装されていませんが、この状態でビルドして動作を確認してみます。

実行して「プロジェクト設定」を確認すると「My Debug Settings > デバッグ設定」という項目が追加できていることを確認できます。

Information

この表示が文字化けする場合には、C++コードの文字コードが「Shift-JIS」になっている可能性があります。文字化けを回避して日本語を表示するにはソースコードを「UTF-8」で保存する必要があります。

保存する項目の追加方法

保存する設定項目の追加は、UPROPERTY() でメンバ変数を定義するだけです。

/**
 * デバッグ設定.
 */
UCLASS(Config=MyConfig, DefaultConfig, meta=(DisplayName="デバッグ設定"))
class TEST_003_API UCPP_DebugSettings : public UDeveloperSettings
{
	GENERATED_BODY()

public:
	// カテゴリ名.
	virtual FName GetCategoryName() const override { return "My Debug Settings"; }
	
	// デバッグフラグ.
	UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, DisplayName="デバッグフラグ");
	bool bDebugFlag = false;
};

ただ注意点として「Config」をつけないと iniファイルには保存されないので、その点は気をつけます。

Information

繰り返しになりますが、UDeveloperSettingsの値は、ゲーム実行中は基本的に書き換えられないので "ReadOnly" となります。

それと Blueprintから UDeveloperSettings を取得するための Blueprint Function Libraryを定義しておくと便利です。

/**
 * デバッグ設定の Buleprint Function Library.
 */
UCLASS()
class TEST_003_API UCPP_DebugSettingsFunction: public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:
	// デバッグ設定を取得する.
	UFUNCTION(BlueprintCallable, Category = "Debug Settings", meta = (DisplayName = "Get Debug Settings"))
	static const UCPP_DebugSettings* GetDebugSettings();
};

CPP側の実装です。

#include "CPP_DebugSettings.h"

// デバッグ設定を取得する.
const UCPP_DebugSettings* UCPP_DebugSettingsFunction::GetDebugSettings()
{
	// デバッグ設定を取得する.
	const UCPP_DebugSettings* DebugSettings = GetDefault<UCPP_DebugSettings>();
	return DebugSettings;
}

では実行して確認します。

ビルドするとエディタのプロジェクト設定から「デバッグフラグ」の設定ができるようになりました。

そして Config フォルダには "DefaultMyConfig.ini" が追加されて、設定情報が保存されます。

レベルブループリントなどで動作確認をします。

問題なく判定できていることを確認しました。

フラグのTMapと数値のTMapを作る

あとは必要なデバッグ設定の項目を作っていくだけですが、個人的におすすめの設定があります。

それが「フラグのTMap」と「数値のTMap」を定義することです。これは "RPGツクール" における「スイッチ」と「変数」のようなものです。

CPP_DebugSettings.hは以下のように記述します。

#pragma once

#include "CoreMinimal.h"
#include "Engine/DeveloperSettings.h"
#include "CPP_DebugSettings.generated.h"

// デバッグフラグの種別.
UENUM(BlueprintType)
enum class EDbgFlag : uint8 {
	Invincible = 0 UMETA(DisplayName = "無敵"),
	NoLimit    = 1 UMETA(DisplayName = "時間無制限"),
	NoHunger   = 2 UMETA(DisplayName = "空腹にならない"),
};

// デバッグ数値の種別.
UENUM(BlueprintType)
enum class EDbgInt : uint8 {
	// 経験値倍率.
	ExpMultiplier = 0 UMETA(DisplayName = "経験値倍率"),
	// 獲得ゴールド倍率.
	GoldMultiplier = 1 UMETA(DisplayName = "獲得ゴールド倍率"),
};

/**
 * デバッグ設定.
 */
UCLASS(Config=MyConfig, DefaultConfig, meta=(DisplayName="デバッグ設定"))
class TEST_003_API UCPP_DebugSettings : public UDeveloperSettings
{
	GENERATED_BODY()

public:
	// カテゴリ名.
	virtual FName GetCategoryName() const override { return "My Debug Settings"; }
	// デバッグフラグの値を取得します.
	bool IsDebugFlag(const EDbgFlag Type) const;
	// デバッグ数値の値を取得します.
	int GetDebugInt(const EDbgInt Type) const;

public: // ------------------------------------------------------ EditAnywhere
	// デバッグフラグ設定.
	UPROPERTY(EditAnywhere,Config,Category = "Debug|Settings",DisplayName="デバッグフラグ設定")
	TMap<EDbgFlag, bool> DebugFlagSettingsMap;

	// デバッグ数値の設定.
	UPROPERTY(EditAnywhere,Config,Category = "Debug|Settings",DisplayName="デバッグ数値設定")
	TMap<EDbgInt, int> DebugIntSettingsMap;
};

/**
 * デバッグ設定の Buleprint Function Library.
 */
UCLASS()
class TEST_003_API UCPP_DebugSettingsFunction: public UBlueprintFunctionLibrary
{
	GENERATED_BODY()
public:
	// デバッグ設定を取得する.
	static const UCPP_DebugSettings* GetDebugSettings();

	// デバッグフラグの値を取得します.
	UFUNCTION(BlueprintPure,Category = "Debug Settings",meta = (WorldContext = "Is Debug Flag"))
	static bool IsDebugFlag(const EDbgFlag Type);
	// デバッグ数値の値を取得します.
	UFUNCTION(BlueprintPure,Category = "Debug Settings",meta = (WorldContext = "Get Debug Int"))
	static int GetDebugInt(const EDbgInt Type);
};

続けて CPP_DebugSettings.cpp は以下のように実装します。

#include "CPP_DebugSettings.h"

// デバッグフラグの値を取得します.
bool UCPP_DebugSettings::IsDebugFlag(const EDbgFlag Type) const
{
	// デバッグフラグの値を取得する.
	if(auto* value = DebugFlagSettingsMap.Find(Type)) {
		return *value;
	}
	// 未定義.
	UE_LOG(LogTemp, Warning, TEXT("DebugFlagSettingsMap: %s is not defined."), *UEnum::GetValueAsString(Type));
	return false;
}
// デバッグ数値の値を取得します.
int UCPP_DebugSettings::GetDebugInt(const EDbgInt Type) const
{
	// デバッグ数値の値を取得する.
	if(auto* value = DebugIntSettingsMap.Find(Type)) {
		return *value;
	}
	// 未定義.
	UE_LOG(LogTemp, Warning, TEXT("DebugIntSettingsMap: %s is not defined."), *UEnum::GetValueAsString(Type));
	return 0;
}

// ----------------------------------------------------------------------
// デバッグ設定の Buleprint Function Library.
// ----------------------------------------------------------------------

// デバッグ設定を取得する.
const UCPP_DebugSettings* UCPP_DebugSettingsFunction::GetDebugSettings()
{
	// デバッグ設定を取得する.
	const UCPP_DebugSettings* DebugSettings = GetDefault<UCPP_DebugSettings>();
	return DebugSettings;
}

// デバッグフラグの値を取得します.
bool UCPP_DebugSettingsFunction::IsDebugFlag(const EDbgFlag Type)
{
	// デバッグ設定を取得する.
	if(const auto* DebugSettings = GetDebugSettings()) {
		return DebugSettings->IsDebugFlag(Type);
	}
	return false;
}

// デバッグ数値の値を取得します.
int UCPP_DebugSettingsFunction::GetDebugInt(const EDbgInt Type)
{
	// デバッグ設定を取得する.
	if(const auto* DebugSettings = GetDebugSettings()) {
		return DebugSettings->GetDebugInt(Type);
	}
	return 0;

}

このように記述して実行すると、プロジェクト設定のデバッグ設定は以下のようになります。

デバッグ用のフラグとデバッグ用の数値の定義が追加されました。

後はブループリントなどで動作確認…。

実行すると設定値が反映できていることを確認できました!

おしまい

UDevelperSettings を使ってデバッグ機能を実装する方法でした。

以上、Unreal Engineでデバッグ機能を実装するのに役立てれば幸いです。

\ 最新情報をチェック /