C++でData Validationを行うまでの道のり
Data Validationとは
「ゲーム開発してるとこういうの欲しくなるよね」という機能が、
UEでは、あれもこれも公式プラグインとして公開されています。
Data Validationもまさにそれ。
プロジェクト内のアセットがルールに従っているか自動でチェックするための機能です。
エディター上での作業時にチェックしてくれるのはもちろん、コマンドラインからの実行も可能です。
docs.unrealengine.com5.3/ja/data-validation-in-unreal-engine概要の把握やBPで行う場合は、おかずさんのブログ記事を参考にするのがオススメです。
今回は、C++で行う場合にいくつか戸惑う箇所があったので紹介します。
UE初心者なので、もっと簡単な方法があればコメントください。
何はともあれValidation用のコードを書く
ドキュメントに沿ってコードを書きます。
UEditorValidatorBaseを継承したC++クラスを作って素直に書くだけ。
#include "DataValidator/SampleValidator.h"
bool USampleValidator::CanValidateAsset_Implementation(UObject* InAsset) const
{
// /Game/Path以下のアセットを対象にする
return InAsset->GetPathName().StartsWith(TEXT("/Game/Path/"));
}
EDataValidationResult USampleValidator::ValidateLoadedAsset_Implementation(UObject* InAsset, TArray<FText>& ValidationErrors)
{
EDataValidationResult Result = EDataValidationResult::Valid;
// 名前がSM_から始まってるか?
FString Name = InAsset->GetName();
if (!Name.StartsWith("SM_"))
{
Result = EDataValidationResult::Invalid;
AssetFails(InAsset, FText::FromString("!Name.StartsWith(\"SM_\")"), ValidationErrors);
}
// StaticMeshか?
UStaticMesh* StaticMesh = Cast<UStaticMesh>(InAsset);
if (StaticMesh == nullptr)
{
Result = EDataValidationResult::Invalid;
AssetFails(InAsset, FText::FromString("StaticMesh == nullptr"), ValidationErrors);
}
// AssetFailsでreturnせず、このように最後に判定することで複数のエラーをまとめて表示できる。オススメ。
if (Result == EDataValidationResult::Valid)
{
AssetPasses(InAsset);
}
return Result;
}#pragma once
#include "CoreMinimal.h"
#include "EditorValidatorBase.h"
#include "SampleValidator.generated.h"
UCLASS()
class PROJECT_API USampleValidator : public UEditorValidatorBase
{
GENERATED_BODY()
public:
virtual bool CanValidateAsset_Implementation(UObject* InAsset) const override;
virtual EDataValidationResult ValidateLoadedAsset_Implementation(UObject* InAsset, TArray<FText>& ValidationErrors) override;
};Editor上ではこれだけで動きます!!めっちゃ簡単!!
と感動したのも束の間、ゲームのビルドがコケるようになります。
ビルドエラーの原因を探る
エラー内容は以下の通り。Unable to instantiate module 'UnrealEd': Unable to instantiate UnrealEd module for non-editor targets.
どうやら、DataValidationが依存しているUnrealEdというエディター専用のモジュールが、
Gameビルド時にも参照されてしまっているようです。
自動的にuproject内のAdditionalDependenciesに"DataValidator" が追加されているのが原因なのですが、
もちろんこれを消すだけではEditor上でもビルドエラーに逆戻り。
Lyraのコードを参考にしたところ、Editor専用のモジュールを新しく作ってしまうのが
(面倒だけど)一番シンプルに落ち着きそうなので、モジュールを分けることにします。
モジュールを分ける
Unityでいうところのasmdefを置いてプロジェクトを分けるみたいなことですね。
モジュールの作り方はドキュメントに従っていけば簡単です。
uprojectに書くTypeをEditorにすれば、Editorビルド時にだけ参照されるモジュールの完成!
先ほど書いたValidatorのコードも新しく作ったモジュールに移動させます。
これでエディター上ではValidationを走らせられ、ゲームビルドも正常に通るようになりました!
次はCI上で実行してみる
さて、手動で実行できるようになったら次は自動化。
コマンドラインから実行してみます。
この1行を実行するだけ。UnrealEditor-Cmd.exe <PROJECT_NAME>.uproject -run=DataValidation
(さらに -stdout をつけるとGUIでダイアログ出たりしなくなるのでオススメ。)
このコマンド、手元では動くのですが別マシンではIncompatible or missing module: (さっき作ったモジュール名)
というエラーが出ました。
そのモジュールがビルドされてないから読めないってことですね。
DataValidationを実行する前にこんな感じでEditorをビルドしてやりましょう。Build/BatchFiles/Build.bat ProjectName Win64 Development -Project=MyProject.uproject' -TargetType=Editor
最後の -TargetType=Editor が重要。
おしまい
アセットのバリデーションなんてなんぼやっても良いですからね。