4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

UE4のAdvancedSearchを活用しよう

Posted at

#はじめに
UE4にはAdvancedSearch(詳細検索)というものがあります。
2.png
コンテンツブラウザでアセット名ではなくそのアセットが持つメタデータで検索をかけることができる機能です。
メタデータというのはコンテンツブラウザでアセットにオンカーソルしたときに見られる情報のことです。
1.PNG
こちらのドキュメントにも書いてある通り、デフォルトで様々なメタデータがありANDやORなどを使うことでより自由度の高い検索を行うことができます。
エディタ上での検索方法などはこちらのドキュメントで詳しく解説されているため、この記事では独自のメタデータを追加する方法をご紹介します。

#つくってみる
今回はUDataAssetを継承した独自のデータアセットでメタデータを追加してみます。
UObjectを継承しているクラスであれば同様の方法で追加できます。

TestDataAsset.h

TestDataAsset.h
UCLASS()
class ADVANCEDSEARCHTEST_API UTestDataAsset : public UDataAsset
{
	GENERATED_BODY()

public:
	// UObject interface.
	virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
	// End of UObject interface.
	
protected:
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	FName CharacterName;

	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	int32 TeamId;
};

一先ず、ゲームに登場するキャラクターのデータアセットだと想定してキャラクター名前とチームのIDを定義してみます。
次に、UObject::GetAssetRegistryTagsをオーバーライドします。この関数のOutTagsに追加されたデータがメタデータになります。

TestDataAsset.cpp

TestDataAsset.cpp
void UTestDataAsset::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
{
	Super::GetAssetRegistryTags(OutTags);

	// キャラの名前を追加.
	OutTags.Add(FAssetRegistryTag(
		GET_MEMBER_NAME_CHECKED(UTestDataAsset, CharacterName),
		CharacterName.ToString(),
		FAssetRegistryTag::ETagType::TT_Alphabetical,
		FAssetRegistryTag::ETagDisplay::TD_None
	));
	
	// チームIDを追加.
	OutTags.Add(FAssetRegistryTag(
		GET_MEMBER_NAME_CHECKED(UTestDataAsset, TeamId),
		FString::FromInt(TeamId),
		FAssetRegistryTag::ETagType::TT_Numerical,
		FAssetRegistryTag::ETagDisplay::TD_None
	));
}

OutTagsに追加したいデータを追加していうわけですが、この変数の型はFAssetRegistryTagの配列で、FAssetRegistryTagのコンストラクタはこのようになっており、

Object.h
	FAssetRegistryTag(FName InName, const FString& InValue, ETagType InType, uint32 InDisplayFlags = TD_None)
			: Name(InName), Value(InValue), Type(InType), DisplayFlags(InDisplayFlags) {}

それぞれの説明は以下の通りです。

パラメータ 詳細
InName メタデータの名前を指定します。オンカーソルした時に表示されるUIで:の左側に表示されます
InValue メタデータの値を指定します。オンカーソルした時に表示されるUIで:の右側に表示されます。
InType メタデータの種類を定義します。
ETagType::TT_Hidden これを指定するとオンカーソルした時のUIで表示されません。
ETagType::TT_Alphabetical これを指定するとアルファベット順でソートされます。
ETagType::TT_Numerical データが数値の場合これを指定します。
ETagType::TT_Dimensional xで区切る次元表示の場合これを指定します。(2x2のような感じ)
ETagType::TT_Chronological FDateTime::ToStringから作成した文字列の場合にこれを指定します。
InDisplayFlags オンカーソルしたUI上で特殊な表示方法を使いたい場合に指定します。
ETagDisplay::TD_None 特殊な表示方法を使わない場合はこれを指定します。(基本これ)
ETagDisplay::TD_Date TagTypeETagType::TT_Chronologicalの時に日にちを表示したい場合はこれを指定します。(30/4/21のような感じ)
ETagDisplay::TD_Time TagTypeETagType::TT_Chronologicalの時に時間を表示したい場合はこれを指定します。(3:58 AMのような感じでもしかしたらMDT 米国山岳部標準時(夏時間) UTC-0600 固定で表示されるかも?)
ETagDisplay::TD_InvariantTz TagTypeETagType::TT_Chronologicalの時にタイムスタンプを不変のタイムゾーンを使用して表示する場合はこれを指定します。(使用してみたところそもそも表示されませんでした...)
ETagDisplay::TD_Memory TagTypeETagType::TT_NumericalFText::AsMemoryから取得した場合に使用可能です。バイト数を表示するものだと思われます。

#おまけ
上記の方法でUObjectを継承したアセットに独自のメタデータを追加できることがわかりました。
しかしBlueprintアセットの場合、コンテンツブラウザ上にあるのはそのクラスのオブジェクトではなくUBlueprint型のブループリントアセットのオブジェクトなため上記の方法が使えないのではないかと思い少し調べてみました。

UBlueprint.cpp
void UBlueprint::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
{
	// We use Generated instead of Skeleton because the CDO data is more accurate on Generated
	if (GeneratedClass)
	{
		if (UObject* CDO = GeneratedClass->GetDefaultObject())
		{
			CDO->GetAssetRegistryTags(OutTags);
		}
	}

UBlueprint::GetAssetRegistryTagsでは設定されているクラスのデフォルトオブジェクトのGetAssetRegistryTagsを呼んでいるため、UObjectを継承したものと同様の方法で独自のメタデータを追加できると思い試してみたところ、オンカーソルしたUI上では確認できませんでしたが検索では指定できたため追加はできるようでした。(どこかでデフォルトオブジェクトのメタデータを明示的に非表示にしているのかもしれない...)

TestObject.h

TestObject.h
UCLASS(Blueprintable)
class ADVANCEDSEARCHTEST_API UTestObject : public UObject
{
	GENERATED_BODY()

public:
	// UObject interface.
	virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
	// End of UObject interface.
	
private:
	UPROPERTY(EditDefaultsOnly)
	TMap<FName, FString> UserDefinedTags;

	UPROPERTY(EditDefaultsOnly)
	EObjectCategory ObjectCategory;
};

TestObject.cpp

TestObject.cpp
void UTestObject::GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const
{
	Super::GetAssetRegistryTags(OutTags);

	FString ObjectCategoryString = FString(FName(NAME_None).ToString());
	{
		if (UEnum* EnumPtr = StaticEnum<EObjectCategory>())
		{
			ObjectCategoryString = EnumPtr->GetValueAsString(ObjectCategory);
		}	
	}
	
	// オブジェクトのカテゴリを追加.
	OutTags.Add(FAssetRegistryTag(
		GET_MEMBER_NAME_CHECKED(UTestObject, ObjectCategory),
		ObjectCategoryString,
		FAssetRegistryTag::ETagType::TT_Alphabetical,
		FAssetRegistryTag::ETagDisplay::TD_None
	));
	
	for (const auto& UserDefinedTag : UserDefinedTags)
	{
		const FAssetRegistryTag::ETagType TagType =
			UserDefinedTag.Value.IsNumeric() ?
			FAssetRegistryTag::ETagType::TT_Numerical :
			FAssetRegistryTag::ETagType::TT_Alphabetical;
		
		
		OutTags.Add(FAssetRegistryTag(
			UserDefinedTag.Key,
			UserDefinedTag.Value,
			TagType,
			FAssetRegistryTag::ETagDisplay::TD_None
		));
	}
}

3.PNG
4.png
また、TMapを使ってメタデータの名前と値を自由に設定することもできるようです。

#おわりに
商用タイトルの開発などでは、キャラクター名ではなく開発IDで管理されデータアセットなどの名前もファイルパスを短くする目的や解析対策として開発IDになっていることが多いと思います。
キャラクターの名前などを独自のメタデータとして追加することでAdvancedSearchを使ってキャラクターの名前などで検索できるため、アセットの検索をする効率がかなりアップするかと思います。

この記事で紹介したプロジェクトは以下でダウンロードできます。
https://github.com/Naotsun19B/AdvancedSearchTest

4
2
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
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?