Pose not updating until one frame after enabling mesh visibility. EvaluateAnimation not called when USkeletalMeshComponent is invisible?

In order to display a ghostly silhouette for one of my characters at a prior position, I wrote a custom AnimInstance that overwrites the silhouette mesh’s pose with one of my choosing.

I am using SetVisibility to disable the silhouette mesh until I want it to appear at the desired location with the specified pose.

Here’s the problem I have been experiencing:

When enabling the silhouette mesh’s visibility, it appears for exactly one frame with the pose it had when it was at its previous visible position before changing to the specified pose.

Even if I set the pose and location well before re-enabling visibility, this phenomenon still occurs.

The reason for this appears to be that EvaluateAnimation is not called when the mesh is invisible, so the pose won’t update until a frame after I re-enable visibility, causing this effect.

I scoured the source but still haven’t been able to determine why EvaluateAnimation isn’t being called (I suppose it’s to improve performance, but I still haven’t been able to figure out where this is being handled), nor have I been able to figure out a way to resolve this problem.

Is there any way to force EvaluateAnimation to be called, or does there happen to be a different way to hide the mesh such that EvaluateAnimation still gets called?

Edit: I tried warping the mesh far away instead of calling SetVisibility, but the same problem occurred. Is LOD or some other factor disabling animation for meshes that aren’t currently visible? For what I’m trying to do, I need to keep the animation running even if the character isn’t visible. Is there any way to do this?

1 Like

I figured it out!

Update frequency was being handled in USkinnedMeshComponent.


The following settings fixed all my problems (in addition to waiting for the animation to evaluate before enabling visibility):

Mesh->bEnableUpdateRateOptimizations = false; // prevent anim frame skipping optimization based on visibility etc

Mesh->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::AlwaysTickPoseAndRefreshBones; // update animation even when mesh is not visible

2 Likes

Thank you so much! I was really in a bind before finding this.

FYI - MeshComponentUpdateFlag is deprecated as of 4.21.

Now, you should use VisibilityBasedAnimTickOption:

GetMesh()->bEnableUpdateRateOptimizations = false; // prevent anim frame skipping optimization based on visibility etc
GetMesh()->VisibilityBasedAnimTickOption = EVisibilityBasedAnimTickOption::AlwaysTickPoseAndRefreshBones; // update animation even when mesh is not visible
2 Likes