Crash: bRequiredBonesUpToDate in EvaluateAnimation - Crash if game thread changes it during evaulate task

We are running a code version of 4.15.

In our game we have some weapons which uses the same posed skeleton as our character (as our weapons have complex animations).

GetWeaponMesh()->SetMasterPoseComponent(MyChar->GetBodyMeshComponent());

We have cases in our game where we are doing some kind of montage on the player and during that the weapons are changed and the above code thus is called, usually during a tick on the Character.

We are getting a rare crash in this case, where the animation system is doing its USkeletalMeshComponent::EvaluateAnimation and his the ensure(bRequiredBonesUpToDate)

This flag is set to false when you set a master pose above as it calls USkeletalMeshComponent::AddSlavePoseComponent

As that all happens on the main thread, what you get is a potential race condition, where the main thread has done the check for the bones, sent the evaluation task off on its thread and before that finishes the main thread ticks the character and calls that code.

I notice we can turn off the entire system with console var, using a.ParallelAnimEvaluation
Besides doing that is there any other suggestion for how to get around this.

Would handling this with a lock so in this rare case the main thread would just wait sound ok?
Since the skeletalmeshcomponent already knows about the ParallelAnimationEvaluationTask.
It could also just called the wait until task completes like in the HandleExistingParallelEvaluationTask when bBlockOnTask is true.

What are the drawbacks or things to consider if we did take that path?

Thanks for your guidance.

Hello Ben,

From looking at past issues related to this, I came across this one that may be able to help you:

Otherwise, is there a reason you’re calling SetMasterPoseComponent on Tick? It’s similar to attachment where it should only need to be done once and shouldn’t need to be done that many times for sure.

Sorry to be clear, we arent doing this every tick, but there are places in our game where the user action will cause different weapons to be “picked up” which then causes a new weapon actor to spawn and that is when the SetMasterPoseComponent occurs.

Now to get around this I ended up doing the following which seems to of worked:

void USkeletalMeshComponent::AddSlavePoseComponent(USkinnedMeshComponent* SkinnedMeshComponent)
{
	Super::AddSlavePoseComponent(SkinnedMeshComponent);

#if 1 //UG_CHANGE - bdriehuis - make sure the parallel anim task completes first!
	if (ParallelAnimationEvaluationTask.IsValid() && ParallelAnimationEvaluationTask->IsComplete() == false)
	{
		HandleExistingParallelEvaluationTask(true, true);
	}
#endif
	bRequiredBonesUpToDate = false;
}

I am not sure if this has any side effects and this again is only solving our one case. I know it will be a rare crash, but if say we were hiding or showing a bone in tick, we could seemingly get the same crash.

I can’t think of any side effects this would have from looking at in this context. I assume it would be best to go with this for now and come back to this if there are any issues that arise from this or if the crash continues. If the crash does come back, please include the callstack from the crash.

Thanks Matthew. So far we have run for a few days without a crash, so fingers crossed. We will definitely keep you up to date as we are a while off shipping and this code path is very likely in our game.