【UE5】 DataTableの選択肢をフィルタリングする

以前書いた記事では
データテーブルの要素を取り出す事はできましたが
データテーブルが必要であるときにはフィルタリングできていませんでした。

こちらでフィルタリング機能についての議論がなされており
使用にあたって若干曲があることが伺えます.

UPROPERTY(EditDefaultsOnly,meta=(RowType="/Script/TESTProject.MyDataTable"))
UDataTable* DT_Test;
UPROPERTY(EditDefaultsOnly, Meta=(RequiredAssetDataTags="/Script/TESTProject.MyDataTable"))
TObjectPtr<UDataTable> DT_Test2;

これらは手元のUE5.3.2環境では動作しませんでした。
(コードに誤りがあるかもしれません)
上記のリンク内では動作していたような記述もあるので以前のバージョンでは使用できていたのかもしれません。

対応方法

UPROPERTY(EditDefaultsOnly, meta = (RequiredAssetDataTags = "RowStructure=/Script/TESTProject.MyDataTable"))
UDataTable* DT_Test;

こちらのコードでは動作することが確認できました。

RowStructur=~がかなり冗長になっており
metaの中では文字列結合やマクロを使用する事ができないのでプロパティ毎に書かないといけないため
使い勝手はあまり良くないかもしれません。

RowTypeのほうが使えればきれいに書けるのですが
バグなら早く治ってほしいですね…

【UE5】 WidgetのNavigationを両方のスティックで移動できるようにする

UEの標準の機能であるNavigationを使用してWidgetの選択しているボタンを移動する実装を行った際に対応したことのメモ

症状

Navigation機能を使用してWidgetの移動を実装している際
GamePadを使用したときに特にconfigを設定しないと左スティックのみでしか動かない状態になっているかと思います。

まずは他のキーでも移動ができるように
ヒストリア様のこちらの記事を参考に実装しました。

記事を参考に追加したキーでの移動はできるようになったのですが
以下のようにスティックを追加しても片方のスティックの入力しか動作しないままでした。

KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Up, EUINavigation::Up);
KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Down, EUINavigation::Down);
KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Left, EUINavigation::Left);
KeyEventRules.Emplace(EKeys::Gamepad_LeftStick_Right, EUINavigation::Right);

調査

FNavigationConfig.cppのコンストラクタで以下のようにデフォルト値が定義されています。

FNavigationConfig::FNavigationConfig()
	: bTabNavigation(true)
	, bKeyNavigation(true)
	, bAnalogNavigation(true)
	, AnalogNavigationHorizontalThreshold(0.50f)
	, AnalogNavigationVerticalThreshold(0.50f)
{
	AnalogHorizontalKey = EKeys::Gamepad_LeftX;
	AnalogVerticalKey = EKeys::Gamepad_LeftY;

	KeyEventRules.Emplace(EKeys::Left, EUINavigation::Left);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Left, EUINavigation::Left);

	KeyEventRules.Emplace(EKeys::Right, EUINavigation::Right);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Right, EUINavigation::Right);

	KeyEventRules.Emplace(EKeys::Up, EUINavigation::Up);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Up, EUINavigation::Up);

	KeyEventRules.Emplace(EKeys::Down, EUINavigation::Down);
	KeyEventRules.Emplace(EKeys::Gamepad_DPad_Down, EUINavigation::Down);
}

ここでどのスティックを使用するかを設定しているようでした。

AnalogHorizontalKey = EKeys::Gamepad_LeftX;
AnalogVerticalKey = EKeys::Gamepad_LeftY;

つまり右スティックを使用したい場合には派生先で以下のように書き換えることになります。

AnalogHorizontalKey = EKeys::Gamepad_RightX;
AnalogVerticalKey = EKeys::Gamepad_RightY;

しかし今回実現したいのは両方のスティックなので少し違います。

FNavigationConfig.hに以下のようなクラスが用意されています。

/** A Navigation config that supports UI Navigation with both analog sticks + D-Pad. */
class FTwinStickNavigationConfig : public FNavigationConfig
{
public:
	SLATE_API FTwinStickNavigationConfig();
	
protected:
	SLATE_API virtual bool IsAnalogHorizontalKey(const FKey& InKey) const override;
	SLATE_API virtual bool IsAnalogVerticalKey(const FKey& InKey) const override;
};

つまり、FNavigationConfigではなくFTwinStickNavigationConfigを継承したクラスを作成して
そちらを使用することで両方のスティックを動作させる事が可能です。

対応方法

最終的には以下のようなクラスを作成して、GameInstanceで設定することで両方のスティックでの移動が実現できました。

class YOUR_GAME_API FMyCustomTwinStickNavigationConfig : public FTwinStickNavigationConfig
{
public:
	FMYCustomTwinStickNavigationConfig();
};

inline FMYCustomTwinStickNavigationConfig::FMYCustomTwinStickNavigationConfig()
{
        //WASDキーでNavigation移動できるように
	KeyEventRules.Emplace(EKeys::A, EUINavigation::Left);
	KeyEventRules.Emplace(EKeys::D, EUINavigation::Right);
	KeyEventRules.Emplace(EKeys::W, EUINavigation::Up);
	KeyEventRules.Emplace(EKeys::S, EUINavigation::Down);
}

【UE5】 UE5 Localizationがパッケージで動作しなかった問題

結論から書くと
Internationalization SupportがEnglishになっていたのが問題でした。

UEで多言語化を実装していたときに遭遇した問題の解決方法のメモ

症状

多言語化対応は英語、日本語、中国語(簡体字)、中国語(繁体字)
EditorのStandAloneでは正常に表示、言語の切り替えができていたのに
パッケージングすると英語 <-> 日本語のみしか正常に動作しなくなっていた。

対応.1

ProjectSettings -> Packaging ->Licalizations to Package
で必要な言語を選択

対応.2

ProjectSettings -> Packaging -> Internationalization Support
に適切なものを設定
どれが適切かは、対応する言語によって異なるので
こちらを確認して対応する必要があります。

その他の多言語化周りの細かい設定部分についてこちらの公式ページにまとまっているので
ここを読むのが正しい情報を得られると思います。

【UE5】 UE5 プロジェクト用のGameUserSettingsを用意する

UEにはUGameUserSettingsというものがありそちらには設定に関するものが数値が入っています。

steam対応のゲームで
Saveデータはクラウドで共有したいけど、設定はパソコン毎に持ちたい
という場合や、
設定を変えたらゲームが動かなくなった際に削除して初期値に戻す
という場合に使い分けるということですね。

UGameUserSettingsの公式のドキュメントはこちら
ここにある数値で足りない場合にはプロジェクトごとに用意する必要があります。

そこでハマったポイントをメモしておきます。

1. UGameUserSettingsを継承したクラスを作成

UCLASS()
class GAME_API UMYGameUserSettings : public UGameUserSettings
{
};

2. ProjectSettingから作成したSettingクラスを指定

Engine -> GeneralSettingsのなかにGameUserSettingsClassの項目があるので
そこに1で作成したクラスを指定します。

これで作成したクラスがUEの関数でGetできます。

3.任意のプロパティを追加

UCLASS()
class GAME_API UMYGameUserSettings : public UGameUserSettings
{
    GENERATED_BODY()
public:
    UPROPERTY(Config) float BGMVolume;
    UPROPERTY(Config) float SEVolume;
};

任意のプロパティを追加します。
(上記コードにはないですがコンストラクタで初期化してください)

ここでUPROPERTY(Config)
をつけないと保存されないので注意が必要です。

これで保存ができていると
GameUserSettings.ini
に追加したプロパティが保存されているのがわかると思います
(GameUserSettings.iniは実行環境によって参照するものが異なります)

当然ですがGameUserSettings.iniは暗号化されていないので
ユーザーにみられても良いものだけを保存しましょう

【UE5】 UE5 DataTableの行のみをEditorで指定して取り出す

2025/2/10追記

DataTableの指定の行を取り出したいときに

通常
DataTatbleを指定 -> RowNameを検索 -> 要素を取り出す
という流れになりますが
その際の設定ミスを減らしたいと思い調べたものをまとめました。

DataTableをフィルタリング

EditorでDataTableを指定する際に以下のように書くとプロジェクト内すべてのDataTableが候補に出てきます。

UPROPERTY(EditDefaultsOnly)
UDataTable* PlayerStatusDataTable;

指定の行のみを取り出すには
Unreal側に用意されているFDataTableRowHandleを使用すると以下のようになります。

UPROPERTY(EditDefaultsOnly, meta = (RowType ="/Script/TESTProject.MyDataTable"))
FDataTableRowHandle PlayerStatusData;


あとは以下のように書くと指定のRowの要素を取得することができます。

		if(PlayerStatusData.IsNull())
		{
			UE_LOG(LogTemp, Warning, TEXT("DataTableRowHandle is valid"));
			return;
		}
		FMyDataTable* MyDataTable = PlayerStatusData.GetRow<FMyDataTable>(FString("ContextText"));
		UE_LOG(LogTemp, Warning, TEXT("Name: %s"), *MyDataTable->Name);

これでデータを作成してもらう人に設定する際に
Rowの名前を文字列で指定する事がなくなるのでデータの設定ミスなどが防げるかと思います。

余談ですが
以下のような記述でDataTableを指定する部分のフィルタリングができないかと思いましたが
動作しないようでした.
DataTableはRowTypeを指定しているので記述方法はあっていると思うのですがなにか別の書き方があるのか…

UPROPERTY(EditDefaultsOnly, meta = (RowType = "/Script/TESTProject.MyDataTable"))
UDataTable* EnemyAsset;

追記

以下のように記述することでDataTableを選択する項目のフィルタリングが可能でした。

UPROPERTY(EditDefaultsOnly, meta = (RequiredAssetDataTags = "RowStructure=/Script/YOUR_PROJECT.DataTableStructName"))
UDataTable* HogeDataTable= nullptr;

こちらの記事に詳しくまとめました。
【UE5】 DataTableの選択肢をフィルタリングする