ぼっちプログラマのメモ

UE4とかUE5とかについて書いたり書かなかったり。

【UE5】User ToolBoxのタブがエディタ起動時に表示・復元されない問題の修正方法 in UE5.3

はじめに

UE5.2からUser ToolBoxという機能が追加され、EditorUtilityWidgetを作らなくてもサクッと簡易的なエディタ拡張ができるようになりました!

User ToolBox(UTB)とは?
User ToolBox 5.2 | Tutorial

しかし、User ToolBoxで作った画面(User ToolBox Tab)がエディタ起動時に出てこない(前回の状態を再現しない)問題があります(以下はタブ復元に失敗していることを示すログ出力)。

 The tab "DefaultUserToolBox" attempted to spawn in layout 'LevelEditor_Layout_v1.8' 
but failed for some reason. It will not be displayed.

そのため、エディタ起動のたびにクリック数回してUser ToolBox Tabを出す必要があります…面倒です…面倒です!

ということで、エンジン改造して解決してみました。
以降は追加・変更したコードと補足についてです。そんなのいいから早く!という方は↓の .patch をご使用くださいまし
Snippets/Batchs/FixRestoreUserToolBoxTab.patch at main · pafuhana1213/Snippets · GitHub

なお、本記事を書いた UE5.3環境では User ToolBoxはExperimental機能なため、今後色々変わる可能性は十分にある点についてご注意ください

続きを読む

【UE5】アウトライナーの目玉アイコン(Visibility)をEditorUtilityからONOFFする方法について(SetIsTemporarilyHiddenInEditor)

本記事はUnreal Engine (UE)のカレンダー | Advent Calendar 2023 - Qiita シリーズ5の 5日目の記事です

はじめに


ホグワーツレガシーの開発者による講演「Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries(Unreal Engine 5での衝突データ: 衝突設定とクエリの管理に関する実用的なアドバイス)」にて、「Collision Presetの設定状況に応じて表示ONOFFするEditorUtilityを作ると視覚的に確認できていいぞ」という内容がありました。が、具体的にどうすればいいのかは説明がなかったので試しに作ってみました。


これを作る過程で「アウトライナーの目玉アイコン(Visibility)をEditorUtilityからONOFF処理が欲しくなったので調べた結果を記事にしました。

なお、上述の講演に関しては下記記事にて内容をまとめています。
pafuhana1213.hatenablog.com

アウトライナーの目玉アイコン(Visibility)をEditorUtilityからONOFFする方法について

AActor::SetIsTemporarilyHiddenInEditor関数・ノードを呼ぶだけ!

とだけの解説だと寂しいので、この関数・ノードだと特定した流れについて軽く説明

1. 目玉アイコンにマウスカーソルを合わせた際のツールチップ「Toggles the visibility of this object in the level editor.」でエンジンコードを検索し、下記コードがヒットする

const TSharedRef<SWidget> FSceneOutlinerGutter::ConstructRowWidget(FSceneOutlinerTreeItemRef TreeItem, const STableRow<FSceneOutlinerTreeItemPtr>& Row)
{
	if (TreeItem->ShouldShowVisibilityState())
	{
		return SNew(SHorizontalBox)
			+SHorizontalBox::Slot()
			.AutoWidth()
			.VAlign(VAlign_Center)
			[
				SNew(SVisibilityWidget, SharedThis(this), WeakOutliner, TreeItem, &Row)
				.ToolTipText(LOCTEXT("SceneOutlinerVisibilityToggleTooltip", "Toggles the visibility of this object in the level editor."))
			];
	}
	return SNullWidget::NullWidget;

2. 上記コードを見る限りだと SVisibilityWidget が使われてるようなので、SVisibilityWidgetが定義されてる SceneOutlinerGutter.cppを眺めていると、何やらVisiblityをONOFFしているコードを見つける

void SVisibilityWidget::OnSetItemVisibility(ISceneOutlinerTreeItem& Item, const bool bNewVisibility)
{
	// Apply the same visibility to the children
	Item.OnVisibilityChanged(bNewVisibility);

	if (ShouldPropagateVisibilityChangeOnChildren())
	{
		for (auto& ChildPtr : Item.GetChildren())
		{
			auto Child = ChildPtr.Pin();
			if (Child.IsValid())
			{
				OnSetItemVisibility(*Child, bNewVisibility);
			}
		}
	}
}

3. 上記コードにおけるItem.OnVisibilityChanged(bNewVisibility);がそれっぽかったので実装箇所を眺めていく。

void FActorTreeItem::OnVisibilityChanged(const bool bNewVisibility)
{
	// Save the actor to the transaction buffer to support undo/redo, but do
	// not call Modify, as we do not want to dirty the actor's package and
	// we're only editing temporary, transient values
	SaveToTransactionBuffer(Actor.Get(), false);
	Actor->SetIsTemporarilyHiddenInEditor(!bNewVisibility);
}

4. Actor->SetIsTemporarilyHiddenInEditor !これや!!!!!
docs.unrealengine.com

おしまい(酷い記事だ!)

【UE5】Collision Presetのリスト情報を取得する方法について(GetProfileNames)

本記事はUnreal Engine (UE)のカレンダー | Advent Calendar 2023 - Qiita シリーズ5の 4日目の記事です

はじめに


ホグワーツレガシーの開発者による講演「Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries(Unreal Engine 5での衝突データ: 衝突設定とクエリの管理に関する実用的なアドバイス)」にて、「Collision Presetの設定状況に応じて表示ONOFFするEditorUtilityを作ると視覚的に確認できていいぞ」という内容がありました。が、具体的にどうすればいいのかは説明がなかったので試しに作ってみました。

これを作る過程で「Collision Presetのリスト情報」を取得する処理が欲しくなったので調べた結果を記事にしました。

なお、上述の講演に関しては下記記事にて内容をまとめています。
pafuhana1213.hatenablog.com

Collision Presetのリスト情報を取得する方法

void UMyBlueprintFunctionLibrary::GetCollisionProfileNames(TArray<FName>& OutNameList)
{
    TArray<TSharedPtr<FName>> ProfileNameList;
	UCollisionProfile::Get()->GetProfileNames(ProfileNameList);

    for (TSharedPtr<FName> NamePtr : ProfileNameList)
    {
        OutNameList.Add(*NamePtr);
    }
}

上記関数 or ノードで取得したリスト情報を元にEditorUtilityの要素を自動生成する実装にすることで、Presetが増減してもEditorUtility側を更新しなくていいので便利なはずです!

なおCustomは上記処理で取得できるリストには含まれていないため、もし必要な場合は明示的に追加する必要があります。

おしまい

【UE5】Collision Presetの設定状況をReference Viewerで確認可能にする方法について(MarkSearchableName)

本記事はUnreal Engine (UE)のカレンダー | Advent Calendar 2023 - Qiita シリーズ 5の 3日目の記事です

はじめに


ホグワーツレガシーの開発者による講演「Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries(Unreal Engine 5での衝突データ: 衝突設定とクエリの管理に関する実用的なアドバイス)」にて、「Collision Presetの設定状況をReference Viewerから確認できるようにするといいぞ」という内容がありましたが、具体的にどうすればいいのかは説明がなかったので…調べて記事にしました!

動いてる様子

なぜこの対応を入れると良いのか?など講演の内容に関しては下記記事でまとめてるのでどうぞ!
(Collision Preset設定に関する設定ミス・不具合を調査する上で便利、などが理由です)
pafuhana1213.hatenablog.com

続きを読む

【UE5】Collision Presetの選択UIを検索可能版(SSearchableComboBox)にする方法について

本記事はUnreal Engine (UE)のカレンダー | Advent Calendar 2023 - Qiita シリーズ 5の 2日目の記事です

はじめに


ホグワーツレガシーの開発者による講演「Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries(Unreal Engine 5での衝突データ: 衝突設定とクエリの管理に関する実用的なアドバイス)」にて、「Collision Presetを検索可能なコンボボックスに変更するといいぞ」という内容がありましたが、具体的にどうすればいいのかは説明がなかったので…調べて記事にしました!

動いてる様子

なぜ検索可能にすると良いのか?など講演の内容に関しては下記記事でまとめてるのでどうぞ!
(Collision PresetのCustomを禁止するとPresetの数が運用上多くなるので、検索可能にしたほうが便利という理由です)
pafuhana1213.hatenablog.com

CollisonPresetのコンボボックスを検索可能版に

  • Engine/Source/Editor/DetailCustomizations/Private/BodyInstanceCustomization.h
class FBodyInstanceCustomization : public IPropertyTypeCustomization
{
...
// edit SComboBox -> SSearchableComboBox
TSharedPtr<class SSearchableComboBox> CollsionProfileComboBox;
//
...
  • Engine/Source/Editor/DetailCustomizations/Private/BodyInstanceCustomization.cpp
void FBodyInstanceCustomization::AddCollisionCategory(TSharedRef<class IPropertyHandle> StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils)
{
...
	.ValueContent()
	[
		SNew(SHorizontalBox)
		.IsEnabled(this, &FBodyInstanceCustomization::IsCollisionEnabled)
		+ SHorizontalBox::Slot()
		.VAlign(VAlign_Center)
		[
			// edit SComboBox -> SSearchableComboBox
			SAssignNew(CollsionProfileComboBox, SSearchableComboBox)
			//
			.OptionsSource(&CollisionProfileComboList)
...

検索できた方が便利だと思うので、近々プルリクしようかなと思います。
おしまい

【UE5】Collision PresetにおけるCustomを無効化する方法について

本記事はUnreal Engine (UE)のカレンダー | Advent Calendar 2023 - Qiita シリーズ 5の 1日目の記事です

はじめに


ホグワーツレガシーの開発者による講演「Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries(Unreal Engine 5での衝突データ: 衝突設定とクエリの管理に関する実用的なアドバイス)」にて、「エンジン改造してCollision PresetのCustomを禁止するのはいいぞ」という内容がありましたが、具体的にどうすればいいのかは説明がなかったので…調べて記事にしました!

動いてる様子

なぜCustomを禁止にすると良いのか?など講演の内容に関しては下記記事でまとめてるのでどうぞ!
(Customが混在してるとバグの温床になるし、調査もしづらい的な理由です)
pafuhana1213.hatenablog.com

実現方法

Customを選択不可能に

Engine\Source\Editor\DetailCustomizations\Private\BodyInstanceCustomization.cpp

void FBodyInstanceCustomization::OnCollisionProfileChanged( TSharedPtr<FString> NewSelection, ESelectInfo::Type SelectInfo, IDetailGroup* CollisionGroup )
{
	// if it's set from code, we did that on purpose
	if (SelectInfo != ESelectInfo::Direct)
	{
		// add 
		if( NewSelection == CollisionProfileComboList[GetCustomIndex()])
		{
			return;
		}
		//
...

Customをグレーアウトに

TSharedRef<SWidget> FBodyInstanceCustomization::MakeCollisionProfileComboWidget(TSharedPtr<FString> InItem)
{
	FString ProfileMessage;

	FCollisionResponseTemplate ProfileData;
	if (CollisionProfile->GetProfileTemplate(FName(**InItem), ProfileData))
	{
		ProfileMessage = ProfileData.HelpMessage;
	}

	return
		SNew(STextBlock)
		.Text(FText::FromString(*InItem))
		// add
		.IsEnabled(!InItem->Equals(TEXT("Custom...")))
		//
		.ToolTipText(FText::FromString(ProfileMessage))
		.Font(IDetailLayoutBuilder::GetDetailFont());
}

Customをリストから消しちゃう

既にCustomを使用しているプロジェクトだと何らかの問題起きそう

void FBodyInstanceCustomization::RefreshCollisionProfiles()
{
	int32 NumProfiles = CollisionProfile->GetNumOfProfiles();

	bool bCanUseDefaultCollision = CanUseDefaultCollision();

	// first create profile combo list
	CollisionProfileComboList.Empty(NumProfiles + (bCanUseDefaultCollision ? 2 : 1));	//If we can use default collision we'll add a "Default" option

	// first one is default one
	if(bCanUseDefaultCollision)
	{
		CollisionProfileComboList.Add(MakeShareable(new FString(TEXT("Default"))));
	}

	// comment out
	//CollisionProfileComboList.Add(MakeShareable(new FString(TEXT("Custom..."))));
	//

以降は上記コード変更に対しての簡単な補足

続きを読む

【UE5】コリジョン管理・処理に関する講演メモ・補足 : Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries | Unreal Fest 2023

本記事は「Unreal Engine (UE)のカレンダー | Advent Calendar 2023」 13日目の記事です。


はじめに

Uneral Fest 2023 におけるホグワーツレガシーの開発者による講演「Collision Data in UE5: Practical Tips for Managing Collision Settings & Queries(Unreal Engine 5での衝突データ: 衝突設定とクエリの管理に関する実用的なアドバイス)」が素晴らしい内容だったのでメモとして記事にしました。

所々エディタ操作を交えた解説があるので、本記事を軽く読んだ後に講演動画を見ると理解が深まると思います!(公式の日本語字幕こないかなぁ…|д゚)チラッ)
www.youtube.com

関連記事

  • Collision PresetにおけるCustomを無効化する方法について

pafuhana1213.hatenablog.com

  • Collision Presetの選択画面にて検索可能にする方法について

pafuhana1213.hatenablog.com

  • Collision Presetの設定状況をReference Viewerから確認する方法について

pafuhana1213.hatenablog.com

  • Collision Presetのリスト情報を取得する方法について

pafuhana1213.hatenablog.com

  • アウトライナーの目玉アイコン(Visibility)をEditorUtilityからONOFFする方法について

pafuhana1213.hatenablog.com

ざっくりまとめ

  • ホグワーツレガシーの開発では、Collision設定に関するルールが整備されていなかったため、プロジェクトの規模・コンテンツ量が増えるにつれて不具合や対応コストが膨大になった
    • そのため、初期段階からCollision設定に関するルールを作成し、各自がそれを守る・注意することが大事。また、それを継続するための仕組み・ツールづくりも重要
  • Collision設定をAsset・Componentごとにカスタマイズすると不具合の元になるし調査もしづらいので、個々のカスタムは禁止して必ずCollision Presetを指定する形が良い。必要に応じてプリセットを追加していく
    • Preset名はCollisionの処理内容ではなく、使用用途がわかる名前にする
    • Presetの数を増やしてもパフォーマンスに影響はないので、沢山追加してOK
    • 微小なエンジン改造やツールを用意することで、ヒューマンエラーの防止や不具合発生時の調査の効率を上げることができる
  • LineTraceをはじめとした様々なCollision Query関数に関しても不具合のもとになることが多く、正しく理解した上で活用・使い分けをしていく必要がある
    • Collision設定を正しく設定することでQuery処理も正しく動作する。逆もしかり
    • 関数に渡すFCollisionResponseParamsを編集することで、Collision Preset側を弄る(=大量のアセットに影響を及ぼすデータ編集をする)ことなく、Query関数を使ったチェック処理を柔軟に行うことができる
    • デバッグ・可視化用の仕組みを用意するとデバッグ・テストする上で非常に便利
  • Collision設定とQuery処理を正しく活用することで、不具合が少ない堅牢な実装を実現できるだけでなく、ボトルネックになりがちなCollision処理を最適化することができる
続きを読む