In the process of switching to 4.23 from 4.22, we started getting an exception in FAnimInstanceProxy::UpdateCurvesToEvaluationContext when an actor is destroyed.
To be exact, this line:
check(UIDToArrayIndexLookupTable.Num() == InContext.Curve.UIDToArrayIndexLUT->Num());
fires an exception, because InContext.Curve is empty.
What i managed to find so far, is that UpdateCurves… is called from USkeletalMeshComponent::ParallelAnimationEvaluation(), and in my particular case, the instance has a PostProcessAnimInstance (and we have Curves) and as it seems, when the player is killed/unspawned everything else in the AnimEvaluationContext gets emptied, EXCEPT THE POSTPROCESSANIMINSTANCE which remains valid.
So ParallelAnimationEvaluation falls into the else case of its latter if (since AnimInstance is null), and the first time ever, calls the UpdateCurvesToEvaluationContext with the (mostly) empty structure, causing the exception. (placing a breakpoint in there showed that as long as the instance is active it always gets into the if() case, but Curves is also properly filled and isn’t empty)
Searching through the Release Notes i have found a mention of a change in the Animation section that looks related:
"Bugfix: Fixed an issue with thread access of the Default Curve UID List. "
(note that the whole thing happens on a worker thread; my suspicion was that it happens when the instance gets destroyed on the main thread while this animation task was already scheduled)
I suspect that the real problem is that, at least now in 4.23, PostProcessAnimInstance is not cleared when the rest of the AnimEvaluationContext is. Or that the Curve container is cleared differently than before.
That means the fix would be to change how the context is cleared so the function wouldn’t be called once the instance is in the process of being deleted; but i’m not entirely sure yet as still working on finding where that clearing happens. Previously (4.22) we did not have this problem so i’m trying to find out how that worked and what has changed in 4.23.
Until then i have implemented a quick fix, simply extending the already existing
if(InContext.Curve.UIDToArrayIndexLUT != nullptr)
in AnimInstanceProxy::UpdateCurvesToEvaluationContext, to
if(InContext.Curve.UIDToArrayIndexLUT != nullptr && InContext.Curve.Num() != 0),
which makes it skip the loop if the Curve container is empty.
Could somebody please confirm if the above change in 4.23 caused the issue, and preferably fix it properly? Based on my temporary fix, the solution could be either that Curve.UIDToArrayIndexLUT should be set to null, or that PostProcessAnimIstance should also be cleared with the rest of the structure, but not sure which one. I’ll try to reproduce the same situation in 4.22 and see what was the difference, but please don’t wait for that as i might not have the time to dig deeper.