[이슈 현상]
런 타임에 시퀀스가 재생되는 경우,
애니메이션 내부에 Notify가 존재하고 해당 애니메이션이 재생되는 액터 URO가 활성화 되어있을 때,
간헐적으로 Notify 출력이 되지 않고 애니메이션이 튀는 이슈가 존재 합니다.
(시퀀스 재생이 아닌 레벨에 액터를 배치한 상태에서는 문제 없음)
[원인]
UAnimSequenceBase::GetAnimNotifiesFromDeltaPositions 함수 파라미터로 전달받는
PreviousPosition 값이 URO로 인해 스킵된 시간 정보가 그대로 적용되는 문제로 확인됩니다.
void UAnimSequenceBase::GetAnimNotifiesFromDeltaPositions(...) { ... // 이 부분에서 간헐적으로 예외처리 되어버림 if( (NotifyStartTime <= CurrentPosition) && (NotifyEndTime > PreviousPosition) ) { } ... }
[보충]
시퀀서가 재생될 때 결정되는 PreviousPosition 은
UE::Anim::FAnimSync::TArray<FAnimTickRecord> UngroupedActivePlayerArrays[index].TimeAccumulator
를 통해 결정되는 것으로 확인됩니다.
AnimNode Tick
FAnimNode_AssetPlayerBase::CreateTickRecordForNode 함수가
FAnimNode_SequenceEvaluatorBase::UpdateAssetPlayer 내부에서 호출되는데,
해당 노드에서 캐싱중인 InternalTimeAccumulator의 주소가
FAnimTickRecord.TimeAccumulator에 적용됩니다.
Sequence Tick
시퀀스로 재생될 경우 일반적인 Tick이 아닌
UMovieSceneSequenceTickManager::TickSequenceActors
를 통해 Tick이 진행되는데,
void E::MovieScene::FEveluateSkeletalAnimations::SetAnimPosition(const FSetAnimPositionParams& Params) const 함수의 내부에서
Params.FromPosition 값이 최종적으로
void FAnimSequencerInstanceProxy::UpdateAnimTrack(…) 함수 파라미터 InFromPosition를 통해 InternalTimeAccumulator 가 갱신 됩니다.
URO로 인해 AnimNode Tick이 진행되지 않는 동안 진행된 Sequence Tick으로 InternalTimeAccumulator 값은 이미 증가 되었고,
이로 인해 UAnimSequenceBase::GetAnimNotifiesFromDeltaPositions 함수에서 유효하지 않은
PreviousPosition 값으로 Notify 출력 여부를 결정합니다.