お世話になっております。
<br/>
UE 5.7.2 にて、参照元で報告されているものと同じと思われるクラッシュが発生しています。
※UE 5.6.1 でも現象を確認しています
UE-358685 に似た構成となっているのですが、
1.AStaticMeshActor を継承した独自のクラスを作成し、その BP を用意
2.1 の BP を継承した BP を作成(StaticMeshComponent 自体はそのまま利用しますが、SetupAttachment などで階層変更)
3.2 の BP をレベルに配置
4.3 のレベルを UGameplayStatics::LoadStreamLevel(bShouldBlockOnLoad は false) で ロード
した際、パッケージにてクラッシュが発生しています。
<br/>
UE-358685 と同じものと仮定しての内容となりますが、
5.7.2 でのワークアラウンドの詳細、もしくは、適応可能な CL などはございますでしょうか?
<br/>
コールスタック:
LogThreadingWindows: Error: Runnable thread FAsyncLoadingThread crashed.
LogWindows: Error: === Critical error: ===
LogWindows: Error:
LogWindows: Error: Fatal error!
LogWindows: Error:
LogWindows: Error: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000000000000000
LogWindows: Error:
LogWindows: Error: [Callstack] 0x00007ffc593d1297 VCRUNTIME140.dll!UnknownFunction []
LogWindows: Error: [Callstack] 0x00007ff7e817122b Test.exe!TArray<float,TSizedDefaultAllocator<32> >::operator=() [D:\UE\UE5\Engine\Source\Runtime\Core\Public\Containers\Array.h:822]
LogWindows: Error: [Callstack] 0x00007ff7eba4d700 Test.exe!UE::CoreUObject::Private::Copy<FCustomPrimitiveData>() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Public\UObject\Class.h:1344]
LogWindows: Error: [Callstack] 0x00007ff7e66a7ad3 Test.exe!UScriptStruct::CopyScriptStruct() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\UObject\Class.cpp:3745]
LogWindows: Error: [Callstack] 0x00007ff7e699b46f Test.exe!FObjectInitializer::InitProperties() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp:4618]
LogWindows: Error: [Callstack] 0x00007ff7e69a3d02 Test.exe!FObjectInitializer::PostConstructInit() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp:4354]
LogWindows: Error: [Callstack] 0x00007ff7e697b5c3 Test.exe!FObjectInitializer::~FObjectInitializer() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp:4223]
LogWindows: Error: [Callstack] 0x00007ff7e69b5936 Test.exe!StaticConstructObject_Internal() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp:4970]
LogWindows: Error: [Callstack] 0x00007ff7e6a4dc50 Test.exe!FAsyncPackage2::EventDrivenCreateExport() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading2.cpp:8731]
LogWindows: Error: [Callstack] 0x00007ff7e6a52be2 Test.exe!FAsyncPackage2::Event_ProcessExportBundle() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading2.cpp:7981]
LogWindows: Error: [Callstack] 0x00007ff7e6a53e39 Test.exe!FEventLoadNode2::Execute() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading2.cpp:5979]
LogWindows: Error: [Callstack] 0x00007ff7e6a61807 Test.exe!FAsyncLoadEventQueue2::PopAndExecute() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading2.cpp:6137]
LogWindows: Error: [Callstack] 0x00007ff7e6a6f4d5 Test.exe!FAsyncLoadingThread2::Run() [D:\UE\UE5\Engine\Source\Runtime\CoreUObject\Private\Serialization\AsyncLoading2.cpp:10506]
LogWindows: Error: [Callstack] 0x00007ff7e626dfe8 Test.exe!FRunnableThreadWin::Run() [D:\UE\UE5\Engine\Source\Runtime\Core\Private\Windows\WindowsRunnableThread.cpp:159]
LogWindows: Error: [Callstack] 0x00007ff7e6266f0f Test.exe!FRunnableThreadWin::GuardedRun() [D:\UE\UE5\Engine\Source\Runtime\Core\Private\Windows\WindowsRunnableThread.cpp:79]
LogWindows: Error: [Callstack] 0x00007ffc75eee8d7 KERNEL32.DLL!UnknownFunction []
[Attachment Removed]
Ken.Kuwano
(Ken.Kuwano)
2
お世話になっております。
コールスタックだけを見ると別の問題のようにも見受けられますが、UE-358685 と同じと仮定しておきますと、UE-358685 の報告があった以下のケースが参考になるかもしれません。
[Content removed]
このケース内では、FObjectInstancingGraph::GetInstancedSubobject() を修正し、別のクラスの既存のオブジェクトを検索して名前を変更してから、再度オブジェクトを構築するようにする方法が提案されていますが、全く同じ問題かまでは分からないため直接的に効果があるかは不明です。また、UE-358685 に関してはまだ現在有効なCL等はない状態となっております。
このコールスタックだけを見ますと、非同期ローディングスレッド(FAsyncLoadingThread2)内で FObjectInitializer::InitProperties()でプロパティを初期化中、UScriptStruct::CopyScriptStruct()で構造体をコピー中に問題が発生しており、根本原因んとしてはシリアライズ/デシリアライズに問題がある、メモリ初期過不足、競合状態が発生しているなど、複数の可能性が考えられます。この問題が発生している際にアクセスの競合や初期化不足をステップ実行で確認して頂けますと、問題を更に調べることができます。
[Attachment Removed]
ご確認ありがとうございます。
> UE-358685 の報告があった以下のケース
すみません、頂いたリンクのものを元にスレッドを作成したのですが、参照が切れてしまっているようでした。
> FObjectInstancingGraph::GetInstancedSubobject() を修正し、別のクラスの既存のオブジェクトを検索して名前を変更してから、再度オブジェクトを構築するようにする方法
もし、こちらの詳細がございましたらご共有頂けますと助かります。
どの BP か、追えていたのですが、もう少し発生時に拾える情報が無いか確認致します。
[Attachment Removed]
Ken.Kuwano
(Ken.Kuwano)
4
参照が切れてしまっている件、承知しました。以下が該当しているものだと認識しております。
[Content removed]
>FObjectInstancingGraph::GetInstancedSubobject() を修正し、別のクラスの既存のオブジェクトを検索して名前を変更してから、再度オブジェクトを構築するようにする方法
申し訳ございませんがこちらに関しては具体的な修正コードがありませんでした。情報を元に少し検討する必要があります。
これにあたって、最初に1.~4.までの再現手順を記載頂いておりますが、こちらは容易に再現が可能な問題でしたでしょうか?もしそうであるならば、再現手順か再現プロジェクトを元に、UE-358685 と同じであるかどうかを確認したいと思います。
[Attachment Removed]
ご確認ありがとうございます。
> 以下が該当
貼っていただいた URL にジャンプするとエラーになってしまうようでしたが、crash-when-loading-blueprint-actor の内容で相違ございません。
[Content removed]
※こちらの URL でアクセスできました
> 最初に1.~4.までの再現手順を記載頂いておりますが、こちらは容易に再現が可能な問題
再現プロジェクトが準備可能か検証致します。
現状、プロジェクト側でクラッシュした際のコールスタックを辿った際に、
・FObjectInitializer::InitProperties にて StaticMeshComponent が引数に渡ってきている
・この StaticMeshComponent を持っている BP は crash-when-loading-blueprint-actor に近しい形で作成されたもの
というところまではわかっている状態となりますが、発生確率が 100 % ではなく、それ以外の条件が不明となっております。
引き続き、宜しくお願い致します。
[Attachment Removed]
お世話になっております。
> 再現プロジェクト
Launcher から DL した UE5.7.3 にて再現プロジェクトを作成することができました。
ただ、開発中プロジェクトの一部のソースコードや、リソースを Migrate 機能で移行したものを使用しているため、
専用のアップローダーなどでの受け渡しができればと思うのですが可能でしょうか?
※プロジェクト、パッケージをそれぞれ zip 化したもので計 2 GB 程のサイズとなります
お手数ですが、宜しくお願い致します。
[Attachment Removed]
再現プロジェクトが手元にあるということで是非ご共有頂けますと大変助かります。
先程BOXの招待をKurinoさまに送らせて頂きましたので、そちらにアップロードして頂けますでしょうか。
[Attachment Removed]
ありがとうございます。
Sample.zip(プロジェクト)、SamplePackage.zip(パッケージ) をそれぞれアップロード致しました。
SamplePackage を実行して 1 ~ 2 分ほどで FAsyncLoadingThread でのクラッシュが発生するかと思います。
プロジェクト:
---------------------------------------------------
・SequenceAnimationStaticMeshActor.cpp
StaticMeshActor を継承したものとなっており、そこから作成した BP をレベルに配置しています。
・PER_boot.umap
上述のレベルを複数登録したパーシスタントレベルとなります。
・SampleActor.cpp
テスト処理用の Actor で、PER_boot.umap に配置しています。
UGameplayStatics::LoadStreamLevel、UGameplayStatics::UnloadStreamLevel を用いて、PER_boot に登録したレベルを適当に切り替えています。
---------------------------------------------------
ご確認のほど、宜しくお願い致します。
[Attachment Removed]
再現プロジェクトを共有頂きありがとうございます。こちらの環境でもクラッシュを確認できました。直ぐにご提案可能なCLや回避策が見つからなかったので、現在開発チームに本件を確認しております。お時間を頂き恐縮ですが、今しばらくお待ちください。
[Attachment Removed]
お世話になっております。ご連絡が遅くなってしまい申し訳ございません。
これは既知の不具合でしたが、今のところ構成を変える方法以外に、オーバーライド処理をネイティブC++側に移動させて、そこでオーバーライドが正しく機能するようにし、そこから派生したBPを紐付けるという方法が提案できる方法の1つとして挙げられました。関連するAPIに関する情報は、こちらをご参考にして頂けますと幸いです。
https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/CoreUObject/FObjectInitializer/SetDefaultSubobjectClass
// Proxy actor
ADirectionalLightProxyActor::ADirectionalLightProxyActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass(LightComponentName, UDirectionalLightComponent::StaticClass()))
{
}
[Attachment Removed]
お世話になっております。ご回答ありがとうございます。
> SetDefaultSubobjectClass
すみません、こちらの API については、例えば ACharacter の MovementComponent を別の継承したクラスに置きかえる、といった用途で用いるものという理解でしたが、
今回のケースですと AStaticMeshActor(の StaticMeshComponent) をそのまま用いている状態となります。
こちら、どのような形で不具合を回避するものになりますでしょうか…?
ASequenceAnimationStaticMeshActor::ASequenceAnimationStaticMeshActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass("StaticMeshComponent0", UStaticMeshComponent::StaticClass()))
試しに Sample プロジェクトにて上記を試してみましたが、改善は見られないようでした。
宜しくお願い致します。
[Attachment Removed]
お世話になっております。
AStaticMeshActor は FObjectInitializer を受け取るコンストラクタでサブオブジェクトを構築しますが、派生クラスで Super() のみ呼んでいると、FObjectInitializer のチェーンが途切れ、BP 側のコンポーネント上書きと非同期ロード時のテンプレート解決が壊れやすくなるため、 Super(ObjectInitializer) に変更します。メッシュを UStaticMeshComponent の派生に差し替える場合は SetDefaultSubobjectClass(AStaticMeshActor::StaticMeshComponentName, …) を追加します。
SequenceAnimationStaticMeshActor.h
// ASequenceAnimationStaticMeshActor();
ASequenceAnimationStaticMeshActor(const FObjectInitializer& ObjectInitializer);
#include "Components/StaticMeshComponent.h"
//ASequenceAnimationStaticMeshActor::ASequenceAnimationStaticMeshActor()
// : Super()
// , SceneRootComponent(nullptr)
// , UnrotateComponent(nullptr)
// , AnimationComponent(nullptr)
ASequenceAnimationStaticMeshActor::ASequenceAnimationStaticMeshActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
ただしこの問題はタイミングにも依存している部分もあり、FCustomPrimitiveData コピーは UStaticMeshComponent(UPrimitiveComponent) まわりの初期化に直結しやすく、AStaticMeshActor のデフォルトサブオブジェクトを BP/継承+階層変更と組み合わせたときに、非同期ロード経路で不整合が出る類の問題と相性が悪いです。そのためブロッキングロードにしてロードの完了を担保します。これによって問題が解消されるかと思います。
UGameplayStatics::LoadStreamLevel(GetWorld(), SubLevel01, false, false, LatentAction);
UGameplayStatics::LoadStreamLevel(GetWorld(), SubLevel02, false, false, LatentAction);
UGameplayStatics::LoadStreamLevel(GetWorld(), SubLevel03, false, false, LatentAction);
もしこれでも問題が発生するようであれば、RecreateComponentHierarchy() を一時的に無効化して再パッケージを試して問題を切り分けることができます。ASequenceAnimationStaticMeshActor のコンストラクタと PostLoad で呼んでいる RecreateComponentHierarchy() をコメントアウトし、これで落ちなくなるなら、AStaticMeshActor 既定コンポーネントに対する階層変更がトリガーとなることが分かります。
これ以外のワークアラウンドを取るとしたら、AStaticMeshActor 継承をやめて AActor + 自前 UStaticMeshComponent に変更
することですが、既定 StaticMeshComponent0 を後から付け替える構造を避けられるので、FCustomPrimitiveData コピー経路の不整合を踏みにくくなることでこの問題を解消できるかと思われます。
頂きましたサンプルには複雑なコンポーネントの操作を含んでおり、極力そのままの構成を維持しながら変更したいと思いましたが、これらの方法で有効でない場合は、別の方法を検討する必要がありそうです。
[Attachment Removed]
情報ありがとうございます。
各種頂いた情報を元に、オブジェクトの構成変更以外については検証を行ってみたのですが、クラッシュの解決をすることができませんでした…
試した内容としましては
・コンストラクタでの Super(ObjectInitializer)
・ブロッキングロードにするために UGameplayStatics::LoadStreamLevel(GetWorld(), SubLevel01, false, true, LatentAction); への変更
・RecreateComponentHierarchy() のコメントアウト
・(念のため BP_SequenceAnimationStaticMeshActor のコンパイルと再保存)
を順番に試し、最終的には全ての対応を行った状態で検証しておりました。
ブロッキングロードにしたことでコールスタックが FAsyncLoadEventQueue2::ExecuteSyncLoadEvents に変わったようですが、ブロッキングロードにしても FAsyncLoadingThread を経由しているようです。
LogThreadingWindows: Error: Runnable thread FAsyncLoadingThread crashed.
LogWindows: Error: === Critical error: ===
LogWindows: Error:
LogWindows: Error: Fatal error!
LogWindows: Error:
LogWindows: Error: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000000000000000
LogWindows: Error:
LogWindows: Error: [Callstack] 0x00007ffc14cd1297 VCRUNTIME140.dll!UnknownFunction []
LogWindows: Error: [Callstack] 0x00007ff6e946a13b Test.exe!TArray<float,TSizedDefaultAllocator<32> >::operator=() []
LogWindows: Error: [Callstack] 0x00007ff6ecd52350 Test.exe!UE::CoreUObject::Private::Copy<FCustomPrimitiveData>() []
LogWindows: Error: [Callstack] 0x00007ff6e799bbe3 Test.exe!UScriptStruct::CopyScriptStruct() []
LogWindows: Error: [Callstack] 0x00007ff6e7c8f7ff Test.exe!FObjectInitializer::InitProperties() []
LogWindows: Error: [Callstack] 0x00007ff6e7c98092 Test.exe!FObjectInitializer::PostConstructInit() []
LogWindows: Error: [Callstack] 0x00007ff6e7c6f953 Test.exe!FObjectInitializer::~FObjectInitializer() []
LogWindows: Error: [Callstack] 0x00007ff6e7ca9cc6 Test.exe!StaticConstructObject_Internal() []
LogWindows: Error: [Callstack] 0x00007ff6e7d41fa0 Test.exe!FAsyncPackage2::EventDrivenCreateExport() []
LogWindows: Error: [Callstack] 0x00007ff6e7d46f32 Test.exe!FAsyncPackage2::Event_ProcessExportBundle() []
LogWindows: Error: [Callstack] 0x00007ff6e7d48189 Test.exe!FEventLoadNode2::Execute() []
LogWindows: Error: [Callstack] 0x00007ff6e7d494fa Test.exe!FAsyncLoadEventQueue2::ExecuteSyncLoadEvents() []
LogWindows: Error: [Callstack] 0x00007ff6e7d63805 Test.exe!FAsyncLoadingThread2::Run() []
LogWindows: Error: [Callstack] 0x00007ff6e7562078 Test.exe!FRunnableThreadWin::Run() []
LogWindows: Error: [Callstack] 0x00007ff6e755af9f Test.exe!FRunnableThreadWin::GuardedRun() []
LogWindows: Error: [Callstack] 0x00007ffc289be8d7 KERNEL32.DLL!UnknownFunction []
LogWindows: Error:
LogWindows: Error: Crash in runnable thread FAsyncLoadingThread
> AStaticMeshActor 継承をやめて AActor + 自前 UStaticMeshComponent に変更
上記についてはアプリケーション側で既に大量の BP を作成してしまっていることもあり、避けたいと考えております。。。
既知の不具合とのことでしたが、もし、エンジン改造での回避方法など、他にもございましたら情報を頂けると非常に助かります。
その他、何か情報が取れないか弊社側でも検証致します。
お手数ですが、宜しくお願い致します。
[Attachment Removed]
お世話になっております。
クラスを置き換えるとどうなるかの検証のため、AStaticMeshActor はそのままに USampleStaticMeshComponent : UStaticMeshComonent を作成し、
ASequenceAnimationStaticMeshActor::ASequenceAnimationStaticMeshActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass("StaticMeshComponent0", USampleStaticMeshComponent::StaticClass()))
としたうえで検証してみたところ、
void FObjectInitializer::InitProperties(UObject* Obj, UClass* DefaultsClass, UObject* DefaultData, bool bCopyTransientsFromClassDefaults)
if (Class->GetDefaultObject(false) != DefaultData)
{
for (FProperty* P = Class->PropertyLink; P; P = P->PropertyLinkNext)
{
bool bIsTransient = P->HasAnyPropertyFlags(CPF_Transient | CPF_DuplicateTransient | CPF_NonPIEDuplicateTransient);
if (!bIsTransient || !P->ContainsInstancedObjectProperty())
{
if (P->IsInContainer(DefaultsClass))
{
P->CopyCompleteValue_InContainer(Obj, DefaultData); // クラッシュ
Obj, DefaultData はそれぞれ USampleStaticMeshComponent に変更されていることを確認しましたが、やはりクラッシュはしてしまうようでした。
for (FProperty* P = Class->PropertyLink; P; P = P->PropertyLinkNext) // Class->PropertyLink = ForcedLodModel、P->PropertyLinkNext TranslucencySortPriority発生確率が 100 % ではないものの、毎回同じようなプロパティの場所ではあるようです。
コピー先の Obj とコピー元の DefaultData に何らか差異が生まれてしまっているということになるかと思うのですが、何か情報がございましたらお願い致します。
引き続き、宜しくお願い致します。
[Attachment Removed]
完全な解決に至らず申し訳ございません。
ご質問の件につきまして、FObjectInitializer::PostConstructInit から呼ばれる InitProperties(Obj, BaseClass, Defaults, …) は「Obj のプロパティを Defaults(多くはアーキタイプ/テンプレート)側からコピーして埋める」処理で、ここで FCustomPrimitiveData のような UScriptStruct+TArray を含む型は、コピー元アドレスが有効で、かつ Obj 側のプロパティオフセットと意味が一致していることが前提になります。次のようなケースでは、表面上は同じクラスでもコピーが壊れることが想定されます。
・コピー元ポインタが無効/未初期化:テンプレート解決の失敗やタイミングで、実質「読んではいけないメモリ」から読んでいる(null に近いアドレス、TArray の内部が壊れている等)
・クラス/レイアウトの不一致:DefaultsClass と DefaultData が指すオブジェクトの実クラスや、親子 BP・コンポーネントテンプレートの組み合わせがずれていると、同じプロパティ名でもオフセットやサブオブジェクト構造の前提がズレることがあります
・Obj とテンプレートの「役割」の不一致
例として、ルートコンポーネントの付け替えのように、ネイティブ/CDO では「メッシュがルート」なのに、シリアライズ済みテンプレートやロード順の都合で 別のコンポーネントツリー前提になっている、といった アーキタイプチェーンの不整合です。ここは「値が違う」というより 「誰をコピー元にすべきか」が崩れているに近いです
・非同期ロードスレッド上の構築
ゲームスレッド前提の不変条件をロードスレッドで壊すと、一時的にテンプレートやサブオブジェクトが不完全なまま InitProperties が走る、という話にもつながります
「コピー先 Obj とコピー元 DefaultData(および DefaultsClass)の関係が正しくない」ことは、今回のような CopyScriptStruct → TArray::operator= のクラッシュと関係しうるというのは間違いないのですが、おそらく今回のケースでは3番目のケースが該当する可能性があります(プロジェクト側の実装における、ISequenceAnimationActorInterface::RecreateComponentHierarchy()内の処理における MeshComponent->SetupAttachment(AnimationComponent.Get()); および MeshComponent->AttachToComponent(AnimationComponent.Get(), FAttachmentTransformRules::KeepRelativeTransform);をコメントアウトすることでクラッシュの問題は完全に再現しないため)。サンプルでは非常に高頻度なLevelStreamが発生していたためこれが実運用に近いのかどうかは分かりませんが、SetRootComponent または SetupAttachment/AttachToComponent のタイミングだけでも遅らせることで、この問題は回避できるものと思われます。
[Attachment Removed]
詳細情報ありがとうございます。
> ISequenceAnimationActorInterface::RecreateComponentHierarchy()内の処理における MeshComponent->SetupAttachment(AnimationComponent.Get());
> および
> MeshComponent->AttachToComponent(AnimationComponent.Get(), FAttachmentTransformRules::KeepRelativeTransform);
> をコメントアウトすることでクラッシュの問題は完全に再現しない
上記について、申し訳ありませんが詳細手順を教えて頂いても宜しいでしょうか?
---------------------------
・該当箇所をコメントアウト
・BP_SequenceAnimationStaticMeshActor の階層が変わっていることを確認
BP_SequenceAnimationStaticMeshActor
Scene Root Component
Static Mesh Component // 親子関係が解消されている
Unrotate Component
Animation Component
・BP_SequenceAnimationStaticMeshActor を上書き保存
・プラットフォーム - プロジェクトをパッケージ化 で Win64 Development のパッケージを作成
---------------------------
の手順ではクラッシュが回避できておらずとなります。。。
> サンプルでは非常に高頻度なLevelStreamが発生していたためこれが実運用に近いのかどうかは分かりません
につきましては、検証のために高頻度で行っていますが、頻度が少ない実運用でも症状自体は発生している状態となります。
(シーン遷移時間の短縮のため、次のシーンの先読みを行うケースで利用)
引き続き、宜しくお願い致します。
[Attachment Removed]
>上記について、申し訳ありませんが詳細手順を教えて頂いても宜しいでしょうか?
これは、サンプルプロジェクトの中にあった ISequenceAnimationActorInterface::RecreateComponentHierarchy()内の処理を以下のようにコメントアウトしたことを示しています。ただし、これは問題の切り分けの1つとして行ったことであって、MeshComponentに対する操作が原因となっていることを示したものであり、根本的な回避策ではありません。同じ構造を維持するには、以下コメントアウトした処理をタイミングを遅らせることで解消されるだろう、ということが推測されることを意図していました(実際に送らせて完全に解消されるかは確認できていませんが、少なくとも以下の部分に関連することを確認したものです)。
FUObjectThreadContext& ThreadContext = FUObjectThreadContext::Get();
if (ThreadContext.IsInConstructor > 0)
{
UnrotateComponent->SetMobility(SceneRootComponent->GetMobility());
UnrotateComponent->SetupAttachment(SceneRootComponent.Get());
AnimationComponent->SetupAttachment(UnrotateComponent.Get());
// MeshComponent->SetupAttachment(AnimationComponent.Get());
}
else
{
UnrotateComponent->SetMobility(SceneRootComponent->GetMobility());
UnrotateComponent->AttachToComponent(SceneRootComponent.Get(), FAttachmentTransformRules::KeepRelativeTransform);
AnimationComponent->AttachToComponent(UnrotateComponent.Get(), FAttachmentTransformRules::KeepRelativeTransform);
// MeshComponent->AttachToComponent(AnimationComponent.Get(), FAttachmentTransformRules::KeepRelativeTransform);
}
[Attachment Removed]
ありがとうございます。
> サンプルプロジェクトの中にあった ISequenceAnimationActorInterface::RecreateComponentHierarchy()内の処理を以下のようにコメントアウト
> コメントアウトすることでクラッシュの問題は完全に再現しない
> 問題の切り分けの1つとして行ったことであって、MeshComponentに対する操作が原因となっている
頂いた内容を適用したとしてもクラッシュが発生してしまうという状況なのですが、検証頂いているエンジンバージョンや環境、細かい手順など何か差がございますでしょうか…?
先日お送りした内容に加え、ASequenceAnimationStaticMeshActor を AStaticMeshActor をほぼそのまま継承した状態にするために、
・CreateDefaultSubobject で生成している SceneRootcomponent、UnrotateComponent、AnimationComponent なども生成しないように
・RecreateComponentHierarchy をコールしないように
・(BP の再保存、Cook で生まれたキャッシュなどの削除をしたうえでパッケージ作成)
といったことも試してみましたが、やはりクラッシュが回避できないようでして、MeshComponent に対する操作が原因、というところに辿りつけずにおります。。。
こちらの検証手順に問題がある可能性がございますのでご指摘頂けますと幸いです。
宜しくお願い致します。
[Attachment Removed]
ご確認頂きありがとうございます。
申し訳ございません、AttachToComponent のコメントアウトだけではクラッシュが回避できませんでした。こちらでクラッシュが発生しないことが確認できたのは、以下の変更の場合のケースでした。コンストラクタをObjectInitializer付きに変更し、SetRootComponent をコメントアウトするケースです。BP クラスに対してはコンストラクタで生成済みのコンポーネントを再利用せず、新規作成を試みてしまうため、非同期ロードスレッド上でオブジェクトのリサイクル(既存オブジェクトの破棄)が発生し、スレッドセーフでない破棄処理がクラッシュを引き起こしていると推定されるため、以下のケースでサンプル上での問題が発生しないケースを確認しておりました。
\Source\TBT\SequenceAnimationStaticMeshActor.h
// ASequenceAnimationStaticMeshActor();
ASequenceAnimationStaticMeshActor(const FObjectInitializer& ObjectInitializer);
----------------------------------------------------------------------------
\Source\TBT\SequenceAnimationStaticMeshActor.cpp
#if 0
ASequenceAnimationStaticMeshActor::ASequenceAnimationStaticMeshActor()
: Super()
, SceneRootComponent(nullptr)
, UnrotateComponent(nullptr)
, AnimationComponent(nullptr)
#else
ASequenceAnimationStaticMeshActor::ASequenceAnimationStaticMeshActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
#endif
----------------------------------------------------------------------------
\Source\TBT\SequenceAnimationActorInterface.cpp
// Self->SetRootComponent(SceneRootComponent.Get());
Component構成の変更が許容されるのであれば、 BPの継承を1段にフラット化(C++ クラス → BP_A → BP_B の 2 段 BP 継承を単一の BP にまとめること)で問題のコードパスを回避できる可能性があるのですが、現状この方法が難しいとなると、SetRootComponent のタイミングを BeginPlayまで遅らせる方法が現実的かと思われます。上記のRecreateComponentHierarchy() 内で Self->SetRootComponent(SceneRootComponent.Get()); している箇所を、BeginPlayで実行させることで本クラッシュが発生しないことは確認できておりますので、可能であればこの方法をご検討いただけますと幸いです。
[Attachment Removed]
詳細情報ありがとうございます。
> コンストラクタをObjectInitializer付きに変更し、SetRootComponent をコメントアウト
> サンプル上での問題が発生しないケースを確認しておりました。
> RecreateComponentHierarchy() 内で Self->SetRootComponent(SceneRootComponent.Get()); している箇所を、BeginPlayで実行させることで本クラッシュが発生しない
頂いた情報と同じ状態にしてもクラッシュを回避することができていないという状況でして、検証されたプロジェクトやパッケージを一度 Box 経由で頂戴することは可能でしたでしょうか・・・?
Component 構成の変更が難しいところでして、SetRootComponent を遅らせるといった何らかのワークアラウンドで回避できると非常に助かります。
[Attachment Removed]