本記事は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から確認できるようにするといいぞ」という内容がありましたが、具体的にどうすればいいのかは説明がなかったので…調べて記事にしました!
動いてる様子
アメリカのUnrealFestでホグワーツレガシーの開発者が紹介していた、CollisionPreset設定をReference Viewerで確認できる拡張もできた!…エンジン改造必須だけど…#UE5 #UE5Study https://t.co/uTT0WHr0Zq pic.twitter.com/dI3KKIPlq6
— おかず (@pafuhana1213) 2023年12月12日
なぜこの対応を入れると良いのか?など講演の内容に関しては下記記事でまとめてるのでどうぞ!
(Collision Preset設定に関する設定ミス・不具合を調査する上で便利、などが理由です)
pafuhana1213.hatenablog.com
対応方法について
PrimitiveComponent(BP, レベル上のActor)への対応
void UPrimitiveComponent::Serialize(FArchive& Ar) { ... // add #if WITH_EDITOR if (Ar.IsSaving()) { // This marks the saved name for later searching Ar.MarkSearchableName(FBodyInstance::StaticStruct(), BodyInstance.GetCollisionProfileName()); } #endif // }
StaticMeshアセットへの対応
void UStaticMesh::Serialize(FArchive& Ar) { … // add #if WITH_EDITOR if (Ar.IsSaving() && GetBodySetup()) { // This marks the saved name for later searching Ar.MarkSearchableName(FBodyInstance::StaticStruct(), GetBodySetup()->DefaultInstance.GetCollisionProfileName()); } #endif // }
上記対応を入れた後にアセットを再保存することでReference Viewer上でCollisionPresetの設定状況が確認可能になります。コンテンツブラウザ上でのResaveか、下記記事にある方法で一括Resaveするのが良いと思います!
qiita.com
MarkSearchableNameについて
上記の対応で使っているMarkSearchableNameはアセットのデータ(FArchive)に対してName型の文字列情報をReferenceとして仕込む関数で、エンジン標準ではDataTable・CurveTableの行情報(FDataTableRowHandle, FCurveTableRowHandle)とGameplayTagで使われています。
void FDataTableRowHandle::PostSerialize(const FArchive& Ar) { if (Ar.IsSaving() && !IsNull() && DataTable) { // Note which row we are pointing to for later searching Ar.MarkSearchableName(DataTable, RowName); } }
void FGameplayTag::PostSerialize(const FArchive& Ar) { // This only happens for tags that are not nested inside a container, containers handle redirectors themselves // Only do redirects for real loads, not for duplicates or recompiles if (Ar.IsLoading() && Ar.IsPersistent() && !(Ar.GetPortFlags() & PPF_Duplicate) && !(Ar.GetPortFlags() & PPF_DuplicateForPIE)) { // Rename any tags that may have changed by the ini file. UGameplayTagsManager::Get().SingleGameplayTagLoaded(*this, Ar.GetSerializedProperty()); } if (Ar.IsSaving() && IsValid()) { // This marks the saved name for later searching Ar.MarkSearchableName(FGameplayTag::StaticStruct(), TagName); } }
なお、MarkSearchableNameの第1引数にはUEnumかUStructが設定されることが想定されています。
この仕組みを使ってPrimitiveComponentとStaticMeshアセットにBodyInstanceが持つCollisionPreset名を紐付けることで、ReferenceViewer上でCollisionPresetの設定状況を確認可能にしています。
現状確認している不具合
非WorldPartitionレベルの場合、レベル上のActorにおけるCollisionPreset設定をLevelアセットのReferenceから確認できます。しかし、WorldPartitionレベルの場合はBlockAllしかReferenceに追加されません。たぶんOneFilePerActorが理由かなと思ってます。うまく解決できたら追記します!
さいごに
MarkSearchableNameは今回紹介した用途以外でも自由に使えるので、プロジェクト固有のデータとか仕込んでおくと設定管理・不具合調査時に役に立つかもしれません!
おしまい