UE5.6.1でUserWidgetのアニメーションを連続再生するとキーの設定が正しく反映されません

お世話になっております。

UEのバージョンを5.5.4から5.6.1に上げたところ、

一部のUserWidgetのアニメーションの見た目が変わってしまったため、

解決方法を教えていただきたいです。

▼問題が発生しているUserWidget

UImageと以下の2つのアニメーションがあります。

・selectアニメーション(UImageのRenderOpacityを0~1の間で変化させています)

・defaultアニメーション(0フレーム目に、UImageのRenderOpacityを0に設定しています)

▼問題が発生する手順

1. selectアニメーションを再生させる

2. selectアニメーション再生中に、StopAllAnimations()を呼んでからdefaultアニメーションを再生させる

⇒RenderOpacityが0になることを期待していますが、0.5になります。

▼補足

defaultアニメーションの最終フレームにもキーを打つと、問題は発生しなくなります。

また、最終フレームに打ったキーを削除しても、問題は発生しないままです。

この現象は、エンジンの不具合でしょうか。

プログラムの修正で直るようでしたら、修正方法を教えていただきたいです。

アニメーションの作り方が間違っているようでしたら、ご指摘いただきたいです。

よろしくお願いいたします。

再現できるプロジェクトを添付いたしました。

WBP_Testには、以下の2つのアニメーションがあります。

・select(RenderOpacityを、1.0 → 0.0 → 1.0にしています)

・default(RenderOpacityを、アニメーションの最初に0.0にしています)

キーボードの「1」を押すと、StopAllAnimationsが呼ばれてからselectアニメーションが再生され、

キーボードの「2」を押すと、StopAllAnimationsが呼ばれてからdefaultアニメーションが再生されます。

それぞれ、WBP_Testに再生用の関数を作成してあります。

StopAllAnimationsは、レベルブループリントで呼んでいます。

1 → 2 の順に押したとき、中央の正方形のRenderOpacityは0.0になることを期待していますが、

半透明(RenderOpacityは0.5)になることが確認できます。

もう一度「2」を押すと、defaultアニメーションのキーが正常にが反映されて、RenderOpacityが0.0になります。

お世話になっております。

非常に使いやすい再現プロジェクトのご提供、誠にありがとうございます!

UE5.5.4→UE5.6.1の変更が影響を与えたのは間違いないと思いますが、データの持ち方においてもご検討いただきたいことがあります。今回頂戴した「default」アニメーションが、単に1フレーム目だけにキーが打ってあるというだけではなく、キーを包含する「セクション」が長さを持たない(開始が0.0、終了が0.0)セットアップになっている点が気になりました。

[Image Removed]キーにマウスを重ねた時に表示されるUIをドラッグして、少しでも長さを持たせますと、意図したとおりに動作します。

[Image Removed]最終フレームにキーを打つと正常動作したというお話がありましたが、これはキーが2つあることが正常化を促したのではなく、キーを打ったことでセクションレンジが広がったことが決め手になったと思われます。

このようなセクションの持ち方が、不具合が出ているアニメーションに共通することであるか、ご確認いただくことは可能でしょうか?

もちろん、一度の実行では正しく処理されないが、二度実行するとキーを拾うなど、長さゼロのセクションに対する挙動が安定しない点はエンジンプログラム側の問題です。こちら開発チームに問い合わせておきたいと思います。ただし、最終的に「長さ0のセクションは無視する方が正しい」という方向に転ぶ可能性もあり、もしこうしたセクションの持ち方が原因なのであれば、データでご対応いただくほうが確実かと存じます。

以上、よろしくお願いいたします。​

ご確認ありがとうございます。

不具合が発生しているWBPを確認しました。

不具合が発生しているすべてのアニメーションで、セクションが長さを持っておりませんでした。

また、セクションの終了を0.1に設定したところ、すべてのWBPで不具合が解消されました。

頂いた情報から、セクションに長さを持たせるのが正しいように思いましたので、

今後はセクションに長さを持たせるようにしたいと思います。

開発チームへのお問い合わせも、ありがとうございます。

挙動が安定しない点について、今後の対応がわかりましたらご共有いただけますと幸いです。

お世話になっております。

開発チームへのご確認、ありがとうございます。

5.7で修正予定とのこと、承知いたしました。

ご提示いただいた変更を取り入れてみたのですが、最初にご報告した問題は解消されませんでした。

▼試したこと

変更を入れたエンジンを使用したプロジェクトで、提出した再現プロジェクトと同じことをしました。

▼結果

最初にご報告したように、

---

1. selectアニメーションを再生させる

2. selectアニメーション再生中に、StopAllAnimations()を呼んでからdefaultアニメーションを再生させる

⇒RenderOpacityが0になることを期待していますが、0.5になります。

---

の挙動のままでした。

▼確認したいこと

不具合の修正によって、

・長さ0のセクションも反映される

・1回目の再生と2回目の再生の結果は一致する(不安定な挙動が解消される)

となると思ったのですが、この認識で正しいでしょうか。

ご確認いただけますと幸いです。よろしくお願いいたします。

お世話になっております。

ご回答ありがとうございます。

なるほど、5.7.0 Preview 1用のパッチだったのですね。

5.7.0 preview 1に適用すれば希望通りの挙動になるとのこと、承知いたしました。

5.7にする予定があるため、バージョンを上げてから挙動を確認したいと思います。

ご確認ありがとうございました。

お世話になっております。

本件、開発側の対応についてまだ情報を得られておらず、引き続き情報収集に努めます。

大変申し訳ございませんが、いましばらくお時間を頂戴できますと幸いです。

引き続きよろしくお願いいたします。​

お世話になっております。

大変お待たせいたしました。

開発側での協議結果、本件はリファクタリング時に挙動を取りこぼしたことで生じた不具合であり、積極的に修正をかけていく方針となりました。

修正ターゲットは5.7となります。

暫定パッチとしては、MovieScenePlaybackManager.h / .cppに以下の関数を追加していただき、

// .h側 (public関数)
MOVIESCENE_API void SetCurrentTimeOffset(const FFrameTime& InFrameTimeOffset);
 
// .cpp側
void FMovieScenePlaybackManager::SetCurrentTimeOffset(const FFrameTime& InFrameTimeOffset)
{
	const FFrameRate TickResolution = PlaybackPosition.GetOutputRate();
	const FFrameNumber CurrentTickOffset = ConvertFrameTime(InFrameTimeOffset, DisplayRate, TickResolution).RoundToFrame();
	const FFrameNumber EffectiveStartTick = SequenceStartTick + StartOffsetTicks;
	const FFrameNumber LastValidTick = GetLastValidTick();
	PlaybackPosition.Reset(FMath::Clamp(EffectiveStartTick + CurrentTickOffset, EffectiveStartTick, LastValidTick));
}

FWidgetAnimationState.cppを2か所ほどご変更いただければ、エンジン側で挙動修正が行われるはずと存じます。

// FWidgetAnimationState::Play()関数内 460行付近
	if (bRestoreState)
	{
		SharedPlaybackState->GetPreAnimatedState().EnableGlobalPreAnimatedStateCapture();
	}
 
+	bIsBeginningPlay = true;
 
	const FFrameRate DisplayRate = PlaybackManager.GetDisplayRate();
 
	PlaybackManager.SetStartOffset(FFrameTime(0));
 
// FWidgetAnimationState::Stop() 580行付近
void FWidgetAnimationState::Stop()
{
	using namespace UE::MovieScene;
 
	if (PlaybackManager.GetPlaybackStatus() == EMovieScenePlayerStatus::Stopped)
	{
		return;
	}
 
	PlaybackManager.SetPlaybackStatus(EMovieScenePlayerStatus::Stopped);
 
-	// TODO: we should use PlaybackManager.GetEffectiveStartTime(), but the old behavior always used frame zero.
-	PlaybackManager.SetCurrentTime(0);
+	PlaybackManager.SetCurrentTimeOffset(0);

以上、取り急ぎご報告となります。

よろしくお願いいたします。

お世話になっております。

大変失礼しました! 先日共有したパッチは、UE5.7.0 preview 1用のものでして、UE5.6.1には適用できません。​5.7.0preview1へ適用すれば、「確認したいこと」に記述いただいた挙動となることを確認いたしております。

前回ご案内したパッチは、主にWidgetAnimationState.cppを中心に、UE5.6.1系~UE5.7.0 preview 1まで施された改修の上に適用する必要があるため、それなりに大掛かりな作業になる恐れがございます(変更点が多く、当方でも追い切れておりません)。​もし長さ0のデータがそれほど多くなく、エンジンバージョンアップのご予定もあるのであれば、一旦データ側でご対応いただき、バージョンアップを待つのも一つのやり方かと思います。

以上、よろしくお願いいたします。

ご確認ありがとうございます。

それでは本件は解決済みとしてCloseさせていただきます。

もしまたほかにご不明点などありましたら、いつでもEPSをご利用ください。

以上、よろしくお願いいたします。