お世話になっております。
以前修正ブランチとして#CL16915897と#CL17494254をご提示頂き入れたのですが、引き続きクラッシュが発生しております。
再度修正の方法を教えていただけないでしょうか?
お手数をおかけしますが、よろしくお願いいたします。
再現手順
1.Widgetを作成し、Animationを追加
2.Animationにてイベントトラックを追加し、0フレームや最終フレームでイベント発行を行う
3.BPでのイベント紐づけを行いイベントが来たら表示を切り替える等の処理を行う
4.レベル遷移時に該当アニメーション再生を行うと、時々クラッシュ
この質問は、以下のスレッドに関連して作成されました: [Content removed]
[Attachment Removed]
大変お待たせしております。
過去のスレッドも確認しましたが、いろいろなCLの取り入れなどが行われており、状況の把握に難航しております。
確実に調査を行うために、状況をそろえてできれば再現プロジェクトを用意したいと思っているのですが
以下の点について把握されている部分についてご共有いただけますと助かります。
・UE4.27(plus)に適用している変更
・クラッシュ時の関係部位のメモリの状態について
・バニラエンジンでの再現プロジェクト
[Attachment Removed]
コールスタック中のCastCheckedは、UWidgetAnimation::CreateDirectorInstanceの中からよびだされたものでしょうか?
[Attachment Removed]
[mention removed]
ご回答ありがとうございます。
こちらの状況をできる限り共有いたします。
>・UE4.27(plus)に適用している変更
・様々な変更があるようでしたので、後ほど改めて共有させていただきます。少々お待ち下さい。
・また、質問の内容にある修正ブランチ(#CL16915897と#CL17494254)につきましては現状クラッシュが発生するようですので、取り消しております。
>・クラッシュ時の関係部位のメモリの状態について
・こちらdmpファイルより得られる変数のメモリ状況であれば、ほとんどがnull(<Unable to read memory>等)のようでどのWidgetが要因となっているかさえ把握できない状況でした。
・何をお伝えすべきか分からない状態です。逆アセンブリがほしい等、上記回答とは違う情報が欲しい場合ご指摘お願いたします。
>・バニラエンジンでの再現プロジェクト
・時間がかかりそうかつ再現するか不明なため、一旦は見送らせていただきたいです。
>・コールスタック中のCastCheckedは、UWidgetAnimation::CreateDirectorInstanceの中からよびだされたものでしょうか?
・いえ、呼び出し元はFMovieSceneRootEvaluationTemplateInstance::GetOrCreateDirectorInstance()となります。
dmpでは下記の24行目、if (NewDirectorInstance)の部分から呼び出されているようでした。
UObject* FMovieSceneRootEvaluationTemplateInstance::GetOrCreateDirectorInstance(FMovieSceneSequenceIDRef SequenceID, IMovieScenePlayer& Player)
{
UObject* ExistingDirectorInstance = DirectorInstances.FindRef(SequenceID);
if (ExistingDirectorInstance)
{
return ExistingDirectorInstance;
}
UObject* NewDirectorInstance = nullptr;
if (SequenceID == MovieSceneSequenceID::Root)
{
if (UMovieSceneSequence* Sequence = WeakRootSequence.Get())
{
NewDirectorInstance = Sequence->CreateDirectorInstance(Player, SequenceID);
}
}
else if (const FMovieSceneSequenceHierarchy* Hierarchy = CompiledDataManager->FindHierarchy(CompiledDataID))
{
const FMovieSceneSubSequenceData* SubData = Hierarchy->FindSubData(SequenceID);
check(SubData);
NewDirectorInstance = SubData->GetSequence()->CreateDirectorInstance(Player, SequenceID);
}
if (NewDirectorInstance)
{
DirectorInstances.Add(SequenceID, NewDirectorInstance);
}
return NewDirectorInstance;
}
お手数おかけしますが、よろしくお願いいたします。
[Attachment Removed]
>・いえ、呼び出し元はFMovieSceneRootEvaluationTemplateInstance::GetOrCreateDirectorInstance()となります。
dmpでは下記の24行目、if (NewDirectorInstance)の部分から呼び出されているようでした。
恐らくCreateDirectorInstanceの中で呼び出されているUWidgetAnimation::CreateDirectorInstanceの中に記述されている
UUserWidget* WidgetContext = CastChecked<UUserWidget>(Player.GetPlaybackContext());のCastが失敗していると思われます。
NewDirectorInstanceの行に実行カーソルがあるように見えるのは、クラッシュ時のコールスタックを確認した際に関数の呼び出し後の位置にカーソルがみえるためだと思われます。
頂戴したコールスタックより、Castの引数にnullptrが与えられていることが分かりますが、そのポインタはPlayer.GetPlaybackContext() で返されています。これは実行中のUserWidgetを返しますが、実体はWeakObjectPtrであり参照しているオブジェクトがイベントトラックの実行によって破壊されてしまう場合にNullを返す可能性がありそうです。バグの再現性があるようであれば、WidgetAnimationを持つWidgetが破壊されていないかログを仕込んだりブレイクポイントを配置するなどの方法で確認は可能でしょうか?
またデバッグビルドでも再現可能であればクラッシュダンプでより詳細な情報を得ることができると思います。
もし実行中のWidgetの参照が失われる可能性のあるイベントを実行するのであれば、イベントトラックから直接実行せずに次のフレームなどに遅延させるなどの方法をとることもできるのではないかと思います。
> レベル遷移時に該当アニメーション再生を行うと、時々クラッシュ
この状態を少々把握できていないのですが、対象のWidgetはレベルの遷移中に動作し続けているということでしょうか?
一般的にレベル遷移中にはガベージコレクションが動作していると思います。もしかするとクラッシュの頻度がガベージコレクションのタイミングに依存している可能性があるため、gc.CollectGarbageEveryFrameコンソール変数などを利用してガベージコレクションの頻度をあげることで再現性を高めることができるかもしれません。ご確認いただけますと幸いです。
[Attachment Removed]
お世話になっております。ご回答いただきありがとうございます。
現在別件が立て込んでおりますので、落ち着き次第いただいた内容を試みる予定となっております。
大変申し訳ございません。よろしくお願いいたします。
[Attachment Removed]
承知しました。トラッキングのために一度返信させていただきます。お時間が中々取れないようであれば自動クローズを防ぐために時間を空けてコメントいただけますと幸いです。
[Attachment Removed]
自動クローズ回避も兼ねて、先んじてわかっている内容をお伝えいたします。
> レベル遷移時に該当アニメーション再生を行うと、時々クラッシュ
頻度についてなのですが、実は別の画面で2件ございます。
1件目が原因Widget及びアニメーションを特定できていない、1度だけ発生したものです。
2件目が原因Widget及びアニメーションを特定済みの毎回発生するものとなります。(アニメーションのイベントトラック削除にて回避済み)
2件目について、念の為ガベージコレクションの頻度を上げて検証しましたが頻度に差はありませんでした。
>この状態を少々把握できていないのですが、対象のWidgetはレベルの遷移中に動作し続けているということでしょうか?
2件目の対象Widgetについて、レベルの遷移中に動作し続けているかこちらでは把握しておりません。エンジン的にはどうなっているでしょうか?
特別レベル遷移中に動作するような処理は書いておらず、CreateWidgetしたままといった状態になると思います。詳しくなくて申し訳ございません。
ログを仕込んでの検証等、今後試みていきます。引き続きよろしくお願いいたします。
[Attachment Removed]
以下のトピックで言及されているPostEvaluationPhaseでの配列伸長によるポインタの無効化の問題の可能性がありそうです。
この動作は結果として、いろいろな形でクラッシュなどの問題が表れますがご指摘のコールスタックでのUserWidgetへの参照が壊れる可能性もありえそうです。
[Content removed]
修正CLは20452691となります。こちらの変更を取り入れて動作の確認を願えますでしょうか。
> 特別レベル遷移中に動作するような処理は書いておらず、CreateWidgetしたままといった状態になると思います。
なるほど、つまり「レベル遷移時に該当アニメーション再生を行うと、時々クラッシュ」は、いわゆるLoadMapやSeamlessTravel中とかといった状態でなく、レベル遷移の「後」にウィジットアニメーションが動作してクラッシュが発生するというようなニュアンスでよろしいでしょうか。
[Attachment Removed]
ご確認ありがとうございます。
> おそらくはそのニュアンスで合っております。
状況について承知いたしました。
一旦修正CLでの動作確認の結果をお待ちしたいと思います。
[Attachment Removed]
自動クローズ回避のためコメントいたします。
おまたせしており大変申し訳ございません、もう少々お待ちいただけますと幸いです。
[Attachment Removed]
お世話になっております。遅くなって申し訳ございません。
>修正CLは20452691となります。
確定クラッシュが発生する状態(フォーカスアニメーションにてイベントトラック使用)に巻き戻し、頂いた修正CLを適用して試みましたが、クラッシュが発生いたしました。3/3発生でした。
コールスタックにも差異はありませんでした。
補足ですが、パッケージではなくエディタのスタンドアローンゲームにて検証しております。
以前頂いていたログを仕込むことや、フレームを遅らせることを試してみます。引き続きご報告いたしますので、お手数おかけしますがよろしくお願いいたします。
[Attachment Removed]
残念ながら修正CLが機能しなかった件承知しました。
確定発生ということなので、null参照になってしまうPlayerをトラッキングする方法が良いと思います。
恐らくMovieSceneEventSystemのTriggerAllEventsやAddEventのタイミングでPlayerがアクセス可能であるか判定し、
もしMovieScenePlayerが破壊されていて参照がnullであることが適切であるならばイベントを追加せずに発火しないようにするような対処を検討できそうです。
[Attachment Removed]
>確定発生ということなので、null参照になってしまうPlayerをトラッキングする方法が良いと思います。
ありがとうございます、こちら試みてみます。
[Attachment Removed]
確認よろしくお願いします。Playerが失われるタイミングが分かったらご共有ください。
もしPlayerのアクセス可能かどうかをチェックするポイントが分かりにくいなどがございましたらご返信いただけますと幸いです。
[Attachment Removed]
お世話になっております。
TriggerAllEvents等の関連する関数へブレイクを貼って試みましたが、クラッシュの直前にPlayerはnullになっていないようでした。Player内にあるUserWidgetもnullではなくウィジェットが入っているようでした。
UWidgetAnimation::CreateDirectorInstanceでのCast時にも、nullではないことを確認しております。データブレイクポイントも貼りましたが止まること無くクラッシュいたしました。(データブレイクは5件のみ行いましたので、別が変わっている可能性はございます)
上記の方法以外で検証方法等ございましたらご教授いただけますと幸いです。
関連していないかもしれませんが、確定で落ちている該当のアニメーションは0フレームのもので、「フォーカスアニメーションをデフォルト表示にする」目的のものと思われます。
0フレームアニメーションでイベントを飛ばすことは想定されていない等ございますでしょうか? [Image Removed]
[Attachment Removed]
Playerが完全に生存しているように見える件承知しました。WeakPointerにポインタが入っているがポインタがすでに削除済みになっている可能性もゼロではないと思いますが正常なPlayerでしょうか?
このクラッシュは最初に頂戴したアサートを表示しCallstackと同じ位置でクラッシュしていますか?
Fatal error: [File:D:/project/Engine/Source/Runtime/CoreUObject/Private/Templates/Casts.cpp] [Line: 10] Cast of nullptr to UserWidget failed
このアサートが出ていないのだとすると完全に別のクラッシュになっている可能性があります。
もし同じコールスタックであるとすると想定していた場所とは別の場所のCastChecked<UUserWidget>で引っかかっているのかもしれません。完全なコールスタックを手に入れるためにデバッグビルドでの再現は可能でしょうか?
[Attachment Removed]