FAnimInstanceProxy::ResetCounterInputProxy doesn't reset the counter of child anim nodes

Hi,

We encountered an issue that lead to a crash in the Editor while using ControlRig and Sequencer but we cannot provide a repro.

That’s why I am just going to point out the code that seems to be the issue.

When FAnimInstanceProxy::ResetCounterInputProxy is called, it resets the CachedBonesCounter but multiple animation nodes (like AnimNode_BlendStack) also keep their own counter for comparison purposes.

This eventually leads to an incorrect result when IsSynchronized_All to check if those nodes should update their cache.

I believe ResetCounterInputProxy should also reset the counters of the animation nodes.

Thank you.

[Attachment Removed]

Hey there,

Thanks for raising this. I chatted with the dev team. ResetCounterInputProxy is kind of a hack to handle some issues with the control specifically. So we don’t recommend using it for all animation nodes, which is part of why we haven’t implemented it and are fixing other issues around the cached bones counter. That said, we’ve made many fixes for Control Rig because of the under-the-hood internal changes we made for 5.8. If you can share the crash log, it would help us determine whether we’ve already fixed this.

Dusitn

[Attachment Removed]

Thanks,

A couple of CLs address this space, depending on which version of 5.8 you’re on.

Assuming you’re up to date on 5.8.3, you should backport this change: https://github.com/EpicGames/UnrealEngine/commit/0c1a57fc3bf3fb73b97e2b6513459435692063dc

If you aren’t on 5.8.3, you’ll need a few other changes. Just let me know.

Dustin

[Attachment Removed]

Talking with the team, we don’t think that was related; it’s more about stale cache poses or wrong poses in a cache than it is about binding.

Try all of these CLs as well as the above; some are further recommendations based on the idea.

https://github.com/EpicGames/UnrealEngine/commit/ae6fc00344167646ba593908302eadacad7451fc

https://github.com/EpicGames/UnrealEngine/commit/10267b6ff380b95b49b42d719bade7380fedf0d9

https://github.com/EpicGames/UnrealEngine/commit/57a4ffc93332f966ef6cd6ded0151554ec31fab9

https://github.com/EpicGames/UnrealEngine/commit/886aa9333ad85dff91671ca0ed2456beaad7d3db

[Attachment Removed]

We are not calling it ourselves as far as I know. Looking at the callstack, it’s called by the Sequencer.

FAnimInstanceProxy::ResetCounterInputProxy(FAnimInstanceProxy * InputProxy) Line 3755	C++
FControlRigLayerInstanceProxy::ResetCounter(FAnimInstanceProxy *) Line 407	C++
FAnimNode_ControlRigInputPose::Link(UAnimInstance * InInputInstance, FAnimInstanceProxy *) Line 524	C++
FControlRigLayerInstanceProxy::SetSourceAnimInstance(UAnimInstance * SourceAnimInstance, FAnimInstanceProxy * SourceAnimInputProxy) Line 195	C++
FAnimCustomInstanceHelper::BindToSkeletalMeshComponent<UControlRigLayerInstance>(USkeletalMeshComponent * InSkeletalMeshComponent, bool & bOutWasCreated) Line 186	C++
FControlRigBindingHelper::BindToSequencerInstance(UControlRig * ControlRig) Line 608	C++
FControlRigParameterExecutionToken::Execute(const FMovieSceneContext & Context, const FMovieSceneEvaluationOperand & Operand, FPersistentEvaluationData & PersistentData, IMovieScenePlayer & Player) Line 1341	C++
FMovieSceneExecutionTokens::Apply(const FMovieSceneContext & RootContext, IMovieScenePlayer & Player) Line 60	C++
FMovieSceneTrackEvaluator::EvaluateGroup(const FMovieSceneEvaluationGroup & Group, const FMovieSceneContext & RootContext, IMovieScenePlayer & Player) Line 242	C++
FMovieSceneTrackEvaluator::Evaluate(FMovieSceneContext Context, IMovieScenePlayer & Player, FMovieSceneSequenceID InOverrideRootID) Line 146	C++
UE::MovieScene::FSequenceInstance::RunLegacyTrackTemplates() Line 432	C++
FMovieSceneEntitySystemRunner::GameThread_EvaluationFinalizationPhase(UMovieSceneEntitySystemLinker * Linker) Line 1260	C++
FMovieSceneEntitySystemRunner::FlushNext(UMovieSceneEntitySystemLinker * Linker) Line 448	C++
FMovieSceneEntitySystemRunner::FlushOutstanding(double BudgetMs, UE::MovieScene::ERunnerFlushState TargetState) Line 584	C++
FMovieSceneRootEvaluationTemplateInstance::EvaluateSynchronousBlocking(FMovieSceneContext Context) Line 213	C++
FSequencer::EvaluateInternal(FMovieSceneEvaluationRange InRange, bool bHasJumped) Line 3898	C++
FSequencer::Tick(float InDeltaTime) Line 1308	C++

[Attachment Removed]

After investigation, the outdated cached bones seem to be caused by this order of calls :

  1. SkeletalMesh is initialized and ticked so FAnimInstanceProxy::CacheBones() changes its counter to 0
  2. UE::BlendStack::FBlendStack_SampleGraphExecutionHelper::ConditionalCacheBones matches its counter to 0
  3. Sequencer ticks and FAnimInstanceProxy::ResetCounterInputProxy resets its counter to -1
  4. SkeletalMesh ticks and changes its LOD
  5. FAnimInstanceProxy::CacheBones() changes its counter to 0
  6. UE::BlendStack::FBlendStack_SampleGraphExecutionHelper::ConditionalCacheBones doesn’t update the cached bones since its counter is already at 0
  7. This eventually leads to check(Pose.IsValidIndex(BoneIndex)) failing in FCSPose<PoseType>::GetComponentSpaceTransform in another node

All of this happens in the same frame after opening the sequence causing issues.

[Attachment Removed]

We are sadly still on version 5.8.2.

I am not sure if this helps but I found a past attempt at fixing an issue that looks very similar to what we are experiencing at this commit : https://github.com/EpicGames/UnrealEngine/commit/53a14b574d462beb29b6ac86782dd6dcf61b3b2c

But it was reverted at : https://github.com/EpicGames/UnrealEngine/commit/77356fa3168d6c7b45dc43346ee4bda240871b14

[Attachment Removed]