So… The story begins with linked instances of our
Everything works just fine when we have only one
AnimInstance for our
Skeletal Mesh Component, but it cames with the problem that only one guy can check out and edit this animation blueprint. This gradually became an issue as the team grows.
Thus, we split our animation blueprint into several linked anim instances, which make it much easier for us to manage our anim instance.
It just so happens that the anim notify, which works fine when not placed in linked anim instances, are not triggered on server anymore.
After digging into the codes, it seems that
UAnimInstance::PostUpdateAnimation() animation is not correctly called.
The callling stack starts from
UCharacterMovementComponent::MoveAutonomous, which eventually leads to
For the linked anim instance, their
PostUpdateAnimation are called in
USkeletalMeshComponent::PostAnimEvaluation function like this:
void USkeletalMeshComponent::PostAnimEvaluation(FAnimationEvaluationContext& EvaluationContext)
The skeletal mesh component on server, however, is always set to
Always Tick Pose, which means that they never get evaluated. As a result, the
PostAnimEvaluation are not called.
We fix this issue by moving the
PostUpdateAnimation function of linked instance into
UAnimInstance::PostUpdateAnimation() function like this:
checkf(!bPostUpdatingAnimation, TEXT("PostUpdateAnimation already in progress, recursion detected for SkeletalMeshComponent [%s], AnimInstance [%s]"), *GetNameSafe(GetOwningComponent()), *GetName());
TGuardValue<bool> CircularGuard(bPostUpdatingAnimation, true);
if (GetSkelMeshComponent()->GetAnimInstance() == this)
for (UAnimInstance* LinkedInstance : GetSkelMeshComponent()->GetLinkedAnimInstances())
// Early out here if we are not set to needing an update
And it worked!
After fixing the linked instance update issue, things are still not right.
It works on a single process dedicated server started by editor, but not on a real server.
It turned out that we put our customized anim nodes,
Cache Blend, for instance, in our own plugin. And we put those
AnimGraphNodes in an
Editor module, which cause error like this:
LogUObjectGlobals: Warning: Can’t find file for asset ‘/Script/xxxEditor’ while loading xxxxxx/AnimBP.uasset.
We should use a
Developer or a
UncookedOnly type for the
AnimGraphNode module. Actually,
UncookedOnly is the preferred type since
Developer is deprecated.