【UE5】Commandletを用いて指定したクラスのアセット名に特定のサフィックスがついてないか調べる
概要
アセットデータが多くなってくると、特定のアセットの命名規則が正しくついてるか調べるのが大変なのではないか?と思いました。
便利になる機能がないか調べたところ、今回Commandletがエディター自体を起動しなくても確認でき、アセットの一覧も取得できることがわかったので、調べながら作った機能について記事にしました。
Commandlet自体の情報が少なかったため、参考になれば幸いです。
環境
UE5.4
手順
以下の手順で作成していきました。
- コマンドレットを実行させるクラスUCommandletを継承させたクラスをC++で作成する
- 作成したCommandletを実行させるためにコマンドプロンプトからコマンドを叩く
コマンドレットを実行させるクラスをC++で作成する
今回は指定したクラスのアセット名に指定したサフィックスがないか調べるクラスはこういう形になっています。
#pragma once
#include "CoreMinimal.h"
#include "Commandlets/Commandlet.h"
#include "NamingRuleCommandlet.generated.h"
UCLASS()
class UNamingRuleCommandlet : public UCommandlet
{
GENERATED_UCLASS_BODY()
public:
virtual int32 Main(const FString& CmdLineParams) override;
void GetAssetList(TArray<FAssetData>& AssetList, FString FilterClassName) const;
};
#include "NamingRuleCommandlet.h"
#include "AssetRegistry/AssetRegistryModule.h"
#include "AssetRegistry/IAssetRegistry.h"
DEFINE_LOG_CATEGORY_STATIC(LogNamingRuleCommandlet, Log, All);
UNamingRuleCommandlet::UNamingRuleCommandlet(const FObjectInitializer& ObjectInitializer):Super(ObjectInitializer)
{
}
int32 UNamingRuleCommandlet::Main(const FString& CmdLineParams)
{
int32 Success = 0;
FString ClassName;
if(FParse::Value(*CmdLineParams, TEXT("className="), ClassName))
{
//指定したクラスのアセットを撮ってくる
TArray<FAssetData> AssetList;
GetAssetList(AssetList,ClassName);
FString SuffixName;
if(FParse::Value(*CmdLineParams, TEXT("suffixName="), SuffixName))
{
for (auto Asset : AssetList)
{
//TODO 様々なログが出て見にくいため、確認用にWarningにしてます。
UE_LOG(LogNamingRuleCommandlet,Type::Warning,TEXT("Asset Name=%s"),*Asset.AssetName.ToString());
//アセット名の先頭にサフィックスがついているか確認し、ついてなければ対象のアセット名を表示する
if(!Asset.AssetName.ToString().StartsWith(SuffixName))
{
Success = 1;
UE_LOG(LogNamingRuleCommandlet,Type::Error,TEXT("Naming Suffix Failed Asset Name=%s"),*Asset.AssetName.ToString());
}
}
}
}
return Success;
}
void UNamingRuleCommandlet::GetAssetList(TArray<FAssetData>& AssetList, FString ClassName) const
{
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
IAssetRegistry& AssetRegistry = AssetRegistryModule.Get();
IFileManager& FileMgr = IFileManager::Get();
//対象ディレクトリを探す
FARFilter Filter;
Filter.bRecursivePaths = true;
//対象パス(Contentフォルダ全体を対象にするなら "/Game/" を指定)
Filter.PackagePaths.Add(TEXT("/Game/"));
//リフレクションで名前からクラスを生成する
UClass* AssetClass = FindFirstObjectSafe<UClass>(*ClassName);
const FName AssetPackage = *AssetClass->GetPackage()->GetName();
//対象クラス指定
//元々はFilter.ClassNames.Addだったが、ClassNamesは非推奨になっていたのでClassPathsを使用
Filter.ClassPaths.Add(FTopLevelAssetPath(AssetPackage,*ClassName));
AssetRegistry.GetAssets(Filter, AssetList);
}
主要な部分を解説します。
コマンドライン引数からパラメーターを受け取る
Commandletの特徴は実行引数を渡すことで、文字列の情報を受け取れます。
それをParseしてC++で使える文字列にすることができます。
FString tmpParse;
if(FParse::Value(*CmdLineParams, TEXT("tmpParse="), tmpParse))
{
//パースした結果を用いて処理する
}
今回はクラス名とサフィックスをParseしています。
アセットの取得
アセットの取得方法はこちらの記事を参考にさせていただきました。
その中で、変えた部分はフィルタ対象のクラス指定方法です。
今回は文字列から受け取ったクラス名でフィルタリングしたかったので、リフレクションを用いました。
//リフレクションで名前からクラスを生成する
UClass* AssetClass = FindFirstObjectSafe<UClass>(*ClassName);
const FName AssetPackage = *AssetClass->GetPackage()->GetName();
//対象クラス指定。
//元々はFilter.ClassNames.Addだったが、ClassNamesは非推奨になっていたのでClassPathsを使用
Filter.ClassPaths.Add(FTopLevelAssetPath(AssetPackage,*ClassName));
AssetRegistry.GetAssets(Filter, AssetList);
アセットの検査
取得したアセットを用いて検査してるのはこの部分になります
for (auto Asset : AssetList)
{
//TODO 様々なログが出て見にくいため、確認用にWarningにしてます。
UE_LOG(LogNamingRuleCommandlet,Type::Warning,TEXT("Asset Name=%s"),*Asset.AssetName.ToString());
//アセット名の先頭にサフィックスがついているか確認し、ついてなければ対象のアセット名を表示する
if(!Asset.AssetName.ToString().StartsWith(SuffixName))
{
Success = 1;
UE_LOG(LogNamingRuleCommandlet,Type::Error,TEXT("Naming Suffix Failed Asset Name=%s"),*Asset.AssetName.ToString());
}
}
やっていることはアセット名を取得して、StartsWith
関数で先頭文字にサフィックスが含まれているのかチェックをしています。
作成したCommandletを実行させるためにコマンドプロンプトからコマンドを叩く
Commandlet自体の実行方法は以下になります
実行したいエンジンバージョンのcmdのパス 実行したいuprojectのパス コマンドラインに渡す引数
5.4で実行する場合、デフォルトだと以下のパスになっていると思われますのでそれを使います。
C:\Program Files\Epic Games\UE_5.4\Engine\Binaries\Win64\UnrealEditor-Cmd.exe
例として、GameplayAbilityBlueprint
にGA_
というサフィックスがついてないか調べるようにしたのがこちらになります。
"C:\Program Files\Epic Games\UE_5.4\Engine\Binaries\Win64\UnrealEditor-Cmd.exe" "プロジェクトパス.uproject" -run=NamingRule -className=GameplayAbilityBlueprint -suffixName=GA_ -log
-runに今回作ったCommandletNamingRule
を指定します。
-classNameにはGameplayAbilityBlueprint
を入れます。
-suffixにはGA_
を入れます。
-logはつけるとWarningやErrorに色がつくので見やすいためそうしてます
結果
実際の結果がこちらになります
サフィックスなどはプロジェクトやチームごとに違うと思いますので、よしなに使っていただければと思います。
ここまで読んでいただきありがとうございました。
参考
Discussion