|
執筆バージョン: Unreal Engine 5.8
|
こんにちは!エンジニアの片平です!
今回は UPROPERTY のメタデータである AllowedCharacters と PropertyValidator を使用して、
Detailsパネルの文字列入力をその場でチェックする方法をご紹介します。
IDや外部データとの連携キーなど、入力ルールを守ってほしいプロパティで便利な機能です!
AllowedCharacters と PropertyValidatorとは
AllowedCharactersとは
AllowedCharacters は、プロパティに使用できる文字を指定するメタデータです。
例えば a-zA-Z0-9_ と指定すると、次の文字だけを入力できるようになります。
・a-z:半角英小文字
・A-Z:半角英大文字
・0-9:半角数字
・_:アンダースコア
指定していない文字を入力すると、
DetailsパネルにEngine標準のエラーメッセージが表示されます。
エラー中の文字列はプロパティの値として確定できないため、
間違った文字がデータに入ることを防げます。
PropertyValidator とは
PropertyValidator は、入力された文字列を任意のC++関数で検証するメタデータです。
AllowedCharacters では「どの文字を使えるか」を指定できますが、
「先頭は英字にする」「アンダースコアを連続させない」といった文字列全体のルールまでは指定できません。
そのようなプロジェクト固有のルールを追加できるのが PropertyValidator です。
なお、今回ご紹介する2つのメタデータはUE5.8.1のEngineソースで実装を確認していますが、
公式のメタデータ一覧 には記載されていません。
今後のアップデートによっては仕様が変更される可能性があります。ご留意ください。
作るもの
UDataAsset にプレイヤーIDを持たせて、次のルールを入力中にチェックします。
・半角英数字とアンダースコアだけ使用できる
・空文字にはしない
・先頭は半角英字にする
・アンダースコアを連続させない
Player_01 は確定できますが、空文字や Player-01、01Player、Player__01 は入力エラーとなります。


作成手順
C++クラスの作成
まずは UDataAsset を継承したC++クラスを作成します。
Tools → New C++ Class を選択し、All Classes から DataAsset を検索します。
クラス名は PlayerProfileData とします。

Data Assetを作成する
コードをコンパイルしたら、確認用のData Assetを作成します。
Content Browserの追加メニューから Miscellaneous → Data Asset を選択し、
Data Asset Classに PlayerProfileData を指定します。
名前は DA_PlayerProfile とします。
AllowedCharactersを設定する
最初に AllowedCharacters だけを使ってみましょう。
PlayerProfileData.h に PlayerId プロパティを追加し、
メタデータへ AllowedCharacters = “a-zA-Z0-9_” を指定します。
|
|
/** プレイヤーを識別するID */ UPROPERTY(EditAnywhere, Category = "Player ID", meta = (AllowedCharacters = "a-zA-Z0-9_")) FString PlayerId; |
文字の範囲は区切り文字を入れず、そのまま続けて記述します。
正規表現ではなく、文字と文字範囲を並べる独自の書式です。
今回は半角英数字に加えて、IDでよく使用するアンダースコアも許可しています。
コンパイル後に DA_PlayerProfile の Details パネルで入力してみます。
Player_01 は問題なく入力できます。

一方、Player-01 と入力しようとすると、
ハイフンは AllowedCharacters に含まれていないためエラーが表示されます。

入力欄には一時的に Player-01 と表示されますが、
エラーが解消されるまでプロパティの値として確定することはできません。
これで使用できない文字を含む値の確定を防げるようになりました!
AllowedCharactersだけでは防げない入力
AllowedCharacters は使用できる文字の種類を制限する機能です。
そのため、01Player や Player__01 のように、
文字の種類は正しくても命名ルールに合っていない値までは判断できません。
ここから PropertyValidator を追加して、文字列全体をチェックしてみましょう。
PropertyValidatorを設定する
PlayerId のメタデータに PropertyValidator = “ValidatePlayerId” を追加します。
PropertyValidator に指定するのは、検証に使用する UFUNCTION の名前です。
PlayerProfileData.h の全体は次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#pragma once #include "CoreMinimal.h" #include "Engine/DataAsset.h" #include "PlayerProfileData.generated.h" UCLASS(BlueprintType) class UPlayerProfileData final : public UDataAsset { GENERATED_BODY() public: /** プレイヤーを識別するID */ UPROPERTY(EditAnywhere, Category = "Player ID", meta = (AllowedCharacters = "a-zA-Z0-9_", PropertyValidator = "ValidatePlayerId")) FString PlayerId; private: /** プレイヤーIDの入力内容を検証 */ UFUNCTION() static FText ValidatePlayerId(const FString& PlayerIdCandidate); }; |
検証関数には、次の決まった形を使用します。
・UFUNCTION として宣言する
・static 関数にする
・const FString& で入力中の文字列を受け取る
・検証結果を FText で返す
特に static の付け忘れにご注意ください。
関数が見つからない場合や static でない場合は、Output Logに警告が表示されます。
検証処理を実装する
続いて PlayerProfileData.cpp に検証処理を実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
#include "PlayerProfileData.h" #define LOCTEXT_NAMESPACE "PlayerProfileData" FText UPlayerProfileData::ValidatePlayerId(const FString&; PlayerIdCandidate) { if (PlayerIdCandidate.IsEmpty()) { return LOCTEXT("PlayerIdIsEmpty", "Player IDを入力してください"); } const bool bStartsWithAlphabet = FChar::IsAlpha(PlayerIdCandidate[0]); if (!bStartsWithAlphabet) { return LOCTEXT( "PlayerIdMustStartWithAlphabet", "Player IDの先頭には半角英字を使用してください"); } const bool bHasConsecutiveUnderscores = PlayerIdCandidate.Contains(TEXT("__")); if (bHasConsecutiveUnderscores) { return LOCTEXT( "PlayerIdHasConsecutiveUnderscores", "Player IDでアンダースコアを連続して使用することはできません"); } return FText::GetEmpty(); } #undef LOCTEXT_NAMESPACE |
AllowedCharacters の検証が先に行われるため、
FChar::IsAlpha を呼び出す時点では半角英数字とアンダースコアだけに絞られています。
PropertyValidator は入力内容が変わるたびに呼び出されます。
検証に失敗した場合は、Detailsパネルへ表示したいエラーメッセージを返します。
問題がない場合は空の FText を返します。
今回の処理では、次の内容をチェックしています。
・空文字ではないか
・先頭文字が半角英字か
・__ が含まれていないか
どれかの条件に違反している間はエラーが表示され、
プロパティの値として確定されません。
使用できない文字を入力してみる
まずは Player-01 と入力してみます。
ハイフンは AllowedCharacters に含まれていないため、
Engine標準のエラーメッセージが表示されます。
先頭に数字を入力してみる
次に、空の入力欄へ 01Player を入力してみます。
数字自体は AllowedCharacters で許可されていますが、
先頭文字が英字ではないため PropertyValidator のエラーが表示されます。
アンダースコアを連続して入力してみる
Player_01 のアンダースコアを2つにしてみます。
2つ目のアンダースコアを入力した時点で、
PropertyValidator が __ を検出してエラーを表示します。
空文字にしてみる
入力中のIDをすべて削除すると、
PropertyValidator から「Player IDを入力してください」と表示されます。
正しいIDを入力する
最後に Player_01 と入力します。
すべてのルールを満たしているためエラーは表示されず、
値を設定できるようになりました!
2つのメタデータの役割
今回使用したメタデータの役割をまとめると、次のようになります。
・AllowedCharacters:入力に使用できる文字を制限する
・PropertyValidator:入力された文字列全体をC++のルールで検証する
検証は AllowedCharacters、PropertyValidator の順番で行われます。
使用できない文字が含まれている場合は PropertyValidator まで処理が進まず、
Engine標準の文字エラーが優先して表示されます。
単純なタイプミスとプロジェクト固有の命名ルールをそれぞれ別の仕組みでチェックできるのが嬉しいですね!
まとめ
今回は AllowedCharacters と PropertyValidator を組み合わせて、
プレイヤーIDの入力内容をチェックしてみました。
実行時にエラーを出すのではなく、
データを入力した時点で間違いに気付けるのが嬉しいですね!
プレイヤーID以外にも、アイテムID、セーブデータのキー、
外部ツールと連携する名前など、文字列のルールを統一したい場面で活用できると思います。
入力ミスを減らしたいプロパティがあれば、ぜひ試してみてください!