Hello!
I bumped into a bug where binding to a Post Process AnimBP in Sequencer causes MovieScene to run the Spawn and Instantiation phase every frame. I dug into it a bit, and it seems the culprit is in ULevelSequence::GatherExpiredObjects.
The code here explicitly looks at the AnimInstance on the Skeletal Mesh Component to see if its the same as the one that we bound to. The issue is that we should also check the PostProcess. The simplest version would be to simply do that here, but then we’re duplicating the resolve code that exists in FAnimInstanceLocatorFragment. Below is my version of this, though I don’t think it’s fully bullet-proof since technically the LevelSequenceActor could have binding overrides on the AnimBP.
void ULevelSequence::GatherExpiredObjects(const FMovieSceneObjectCache& InObjectCache, TArray<FGuid>& OutInvalidIDs) const
{
using namespace UE::UniversalObjectLocator;
TArrayView<const FMovieSceneBindingReference> References = BindingReferences.GetAllReferences();
for (int32 Index = 0; Index < References.Num(); ++Index)
{
const FMovieSceneBindingReference& Reference = References[Index];
if (Reference.Locator.GetLastFragmentTypeHandle() == FAnimInstanceLocatorFragment::FragmentType)
{
for (TWeakObjectPtr<> WeakObject : InObjectCache.IterateBoundObjects(Reference.ID))
{
UAnimInstance* AnimInstance = Cast<UAnimInstance>(WeakObject.Get());
if (!AnimInstance || !AnimInstance->GetOwningComponent())
{
OutInvalidIDs.Add(Reference.ID);
continue;
}
// Resolve the objects using a more typical MovieScene pattern. This really only works because AnimInstances are always Possessables and typically don't have Dynamic Binding
TArray<UObject*, TInlineAllocator<1>> NewlyResolvedObjects;
LocateBoundObjects(Reference.ID, FResolveParams(AnimInstance->GetOwningComponent()), nullptr, NewlyResolvedObjects);
if (NewlyResolvedObjects.IsEmpty() || !NewlyResolvedObjects.Contains(AnimInstance))
{
OutInvalidIDs.Add(Reference.ID);
}
}
// Skip over subsequent matched IDs
while (Index < References.Num()-1 && References[Index+1].ID == Reference.ID)
{
++Index;
}
}
}
}
Do you think this is a good approach? Any guidance is appreciated.
Thanks!
-Nathaniel
[Attachment Removed]