メッセージログとは?
Blueprintでのエラー発生時に出てくるウインドウの事
PIE終了時にエラーがある場合には通知ウインドウで表示してくれる為、エラーを把握し易いです
出力ログでエラーを書いても良いのですが、プログラマーは確認しますが....非プログラマー以外のセクションの方は基本的に出力ログを見ることが少ないので個人的にはこちらを採用するのが良いと思っています(というか流行れ!
実装例
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddText(LOCTEXT("Error1", "エラーメッセージ1"))
->AddToken(FUObjectToken::Create(InAsset))
->AddToken(FSeverityToken::Create(EMessageSeverity::CriticalError))
->AddText(LOCTEXT("Error2", "エラーメッセージ2"))
->AddToken(FDocumentationToken::Create(TEXT("https://www.unrealengine.com/ja/unreal-engine-5")))
->AddToken(FImageToken::Create(TEXT("LevelEditor.Tabs.Details")))
->AddText(LOCTEXT("Error3", "エラーメッセージ3"))
);
上記のようにAddTokenを組み合わせることで上記のようなメッセージを作成することができます。
クリックした時の挙動をカスタムする方法
FUObjectToken::Create(InAsset)->OnMessageTokenActivated(FOnMessageTokenActivated::CreateLambda(
[](const TSharedRef<IMessageToken>& Token)
{
if (Token->GetType() == EMessageToken::Object)
{
TSharedRef<FUObjectToken> ObjectToken = StaticCastSharedRef<FUObjectToken>(Token);
UDataAsset* DataAsset = Cast<UDataAsset>( ObjectToken->GetObject().Get());
// 個別の実装
}
})
)
上記のようにOnMessageTokenActivatedを指定する事で独自のカスタムをする事ができます。
Engine\Source\Editor\UnrealEd\Private\Kismet2\KismetDebugUtilities.cpp
void FKismetDebugUtilities::OnScriptException(const UObject* ActiveObject, const FFrame& StackFrame, const FBlueprintExceptionInfo& Info)
個人的に参照したのはココ。
ブループリントでエラーが起きた時にBlueprintエディターを開いて該当のノードをフォーカスするなどの実装が書かれています
個別のTokenの使用例
Action
クリックすると指定したアクションを実行するボタンを用意します
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FActionToken::Create(LOCTEXT("Test", "てすと"), LOCTEXT("Test", "てすと"),
FOnActionTokenExecuted::CreateLambda([]()
{
// コールバック
})))
);
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FActionToken::Create(LOCTEXT("Test", "てすと"), LOCTEXT("Test", "てすと"),
FOnActionTokenExecuted::CreateLambda([]()
{
// コールバック
}),
FCanExecuteActionToken::CreateLambda([]()-> bool
{
// 戻り値がtrueの時だけクリックできる
return true;
})))
);
Actor
クリックするとアウトライナーで選択してくれます
FWorldContext* WorldContext = GEngine->GetWorldContextFromWorld(InActor->GetWorld());
FString ActorPath = InActor->GetPathName();
// UEDPIE_0_Lvl_ThirdPersonみたいな感じでUEDPIE_0がPIE中は付くので外す必要がある
ActorPath = ActorPath.Replace(*WorldContext->PIEPrefix, TEXT(""));
#if WITH_EDITOR
FText ActorLabel = FText::FromString(InActor->GetActorLabel());
#else
FText ActorLabel = FText::FromString(Actor->GetName());
#endif
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FActorToken::Create(ActorPath, InActor->GetActorGuid(), ActorLabel))
);
AssetName
クリックするとコンテンツブラウザでフォーカスを合わせてくれます
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FAssetNameToken::Create(InAsset->GetPackage()->GetName(), FText::FromString(InAsset->GetName())))
);
AssetData
クリックするとコンテンツブラウザでフォーカスを合わせてくれます
#include "AssetRegistry/AssetDataToken.h"
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FAssetDataToken::Create(InAsset))
);
Documentation
const FString URL = TEXT("https://www.unrealengine.com/ja/unreal-engine-5");
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FDocumentationToken::Create(URL))
);
Image
SMessageLogMessageListRow.cpp
Image(FAppStyle::Get().GetBrush(ImageToken->GetImageName()))
使われるのがコレなのでAppStyleのImageNameを使う必要がある
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FImageToken::Create(TEXT("LevelEditor.Tabs.Details")))
);
Object
#include "Misc/UObjectToken.h"
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FUObjectToken::Create(InAsset, FText::FromString(InAsset->GetName())))
);
Severity
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FSeverityToken::Create(EMessageSeverity::CriticalError))
->AddToken(FSeverityToken::Create(EMessageSeverity::Error))
->AddToken(FSeverityToken::Create(EMessageSeverity::Info))
->AddToken(FSeverityToken::Create(EMessageSeverity::PerformanceWarning))
->AddToken(FSeverityToken::Create(EMessageSeverity::Warning))
);
Text
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FTextToken::Create(LOCTEXT("FTextToken", "FTextToken")))
);
// FTextTokenの省略系
// 基本的にこちらを使うべき
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddText(LOCTEXT("FTextToken", "FTextToken"))
);
Tutorial
汎用的に使っている例が見当たらなかったのでサンプルの記述はできません。
情報を求めます
URL
const FString URL = TEXT("https://www.unrealengine.com/ja/unreal-engine-5");
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FURLToken::Create(URL, LOCTEXT("FURLToken", "FURLToken")))
);
EdGraph
汎用的に使っている例が見当たらなかったのでサンプルの記述はできません。
情報を求めます
DynamicText
TAttribute<FText>経由で表示するので動的に表示する文字列を変える場合に使われます
TAttribute<FText> DynamicText = TAttribute<FText>::CreateLambda([]() -> FText
{
return LOCTEXT("FDynamicTextToken", "FDynamicTextToken");
});
MessageLog.AddMessage(
FTokenizedMessage::Create(EMessageSeverity::Error)
->AddToken(FDynamicTextToken::Create(DynamicText))
);
Fix
Misc\DataValidation\Fixer.h
Engine\Plugins\Editor\DataValidation\Source\DataValidation\Public\DataValidationFixers.h
IFixerを継承した物を使って実装する模様
実際に使われているのはTLambdaFixerなどを参照すること













