The skeleton of an anim sequence will change if the skeleton of an asset that references that anim changes

Hello!

We noticed that some of our animation assets seemed to change skeletons randomly. We tracked it down to the logic in UAnimationAsset::ReplaceSkeleton. In particular the call to GetAllAnimationSequencesReferred, which causes that function to also change the skeleton on any assets that are referenced.

Here’s a quick repro I did in QAGame in vanilla UE 5.6:

Open the following three skeletons and make them all compatible with each other:

/Game/Characters/UE4_Guy/Mesh/UE4_Mannequin_Skeleton.UE4_Mannequin_Skeleton

/Game/Characters/UE5_Guy/Mannequin_Skeleton.Mannequin_Skeleton

/Game/Characters/Mannequins/Meshes/SK_Mannequin.SK_Mannequin

Make a test montage that uses Mannequin_Skeleton.

Add an animation sequence to that montage that uses SK_Mannequin. E.g. /Game/Characters/Mannequins/Animations/Male_MotionMatch/Walk/MM_relaxed_walk_stop_F_rFoot.MM_relaxed_walk_stop_F_rFoot

In the Content Browser, right click the test montage and choose “Replace Skeleton” and choose UE4_Mannequin_Skeleton.

Notice that the animation sequence will automatically change from SK_Mannequin to UE4_Mannequin_Skeleton.

Question:

  1. What is the intention of automatically changing the skeleton on all referenced assets? Was the logic in UAnimationAsset::ReplaceSkeleton just implemented before compatible skeletons existed?
  2. We’re inclined to just remove the logic to replace skeletons on “referred” assets. Can you see any negative consequences to that?

As a bonus test, I added an additional animation sequence to that montage that uses Mannequin_Skeleton: /Game/Characters/UE5_Guy/Animations/A_Mantle_ForDemo.A_Mantle_ForDemo.

At this point, I have a montage that uses animations from two different skeletons, which seems like a reasonable thing to do with Compatible Skeletons. Unfortunately, if I then replace the skeleton of the montage, both animations have their skeletons changed too.

This is a fairly contrived example, but we’ve seen other cases where our build machines (which resave animations semi-nightly) have entered the logic in UAnimationAsset::ReplaceSkeleton and replaced skeletons. Our best guess there is hierarchy changes on the skeleton, but for now we’ve settled with investigating this through the simple repro case above.

Steps to Reproduce

Hey Aaron, that code is really old. It looks like Lina added it back in 2014, although the code to remap the dependent assets was a bit more recent (2016). So it pre-dates Compatible Skeletons by a long way, which explains at least why it was implemented that way originally.

I talked with the runtime team about this, but there’s a reluctance to change the behaviour since it’s arguable that it’s doing what you would expect - if you ask for the montage to have its skeleton updated, then you may expect all the dependent assets to be updated as well (especially if you aren’t using compatible skeletons).

In your case, do you know where the call to ReplaceSkeleton is coming from - is it via UAnimationAsset::ValidateSkeleton? If it’s the case where the editor is automagically updating your assets on postload then I can see more of an argument for making a change here.

In terms of your second question, I think you should be fine to make that change if you want to (and you know that your dependent assets are compatible). If you use the asset browser r-click ReplaceSkeleton option, that already gathers the dependent assets independently, so the behaviour shouldn’t change there. But I’m assuming it’s the PostLoad behaviour that’s actually causing you problems.

Hey Euan,

After a bit more digging, we’re pretty confident this is happening after a skeleton hierarchy change. That will cause the ValidateSkeleton call in PostLoad to trigger the ReplaceSkeleton logic.

So we can have content creators setting up this scenario for months (by replacing skeletons on montages and not realizing they have to submit the anim sequences too, or even just dragging anim sequences from one compatible skeleton in the montage for another). But then someone updates the skeleton and we start hitting this. It’s especially nefarious because the p4 history makes it look like the next person to touch those assets was the one to change their skeleton. In our case, it looked like our build machine was changing skeletons when running a resave commandlet.

In any case, thanks for the response. We’ll go ahead with just disabling that logic for now.

-Aaron

Alright, I’ll go back to the runtime team to discuss this further and see if we can change the behaviour. Thanks for flagging it.