Morph target application during actor construction with Leader Pose components

We are building a modular character system in UE5.6.0 using the Leader Pose Component setup, as described in Epic’s documentation:

Leader Pose Component Documentation

Our setup requires morph targets on the follower meshes so they properly fit the leader mesh. We’ve tried applying morph targets to the follower meshes during actor construction ( OnConstruction()/ Blueprint Construction Script), but this leads to problems:

  • Looking at the engine source, USkeletalMeshComponent::SetMorphTarget has the UnsafeDuringActorConstruction meta tag. This makes us think applying morph targets during construction is not supported.
  • Without morph targets applied, follower meshes (jersey, shorts, accessories, etc.) can clip into the leader mesh. This shows up when dragging a character into a level in the editor or when previewing in a Blueprint viewport.
  • We can apply morph targets in BeingPlay(), which resolves clipping at runtime, but this does not solve the issue in edit mode (editor viewport or Blueprint preview).

Question:

Is there an officially supported way (or known workaround) to apply morph targets to skeletal mesh components in editor mode so that modular characters render correctly at all times? Specifically, how should morph targets be handled given that SetMorphTarget is unsafe during actor construction?

Steps to Reproduce
1. Import or create two skeletal meshes that share the same skeleton:

  • A Body mesh (leader).
  • A Jersey mesh (follower) that requires a morph target to correctly fit over the body.

2. Create an ACharacter subclass (or Blueprint based on Character).

3. Add a USkeletalMeshComponent for the body (leader).

4. Add another USkeletalMeshComponent for the jersey (follower).

5. In OnConstruction(), set the jersey to use the body as its Leader Pose Component and apply a morph target to the jersey mesh using SetMorphTarget()

Expected Result:

The jersey mesh should immediately fit correctly to the body mesh (morph target applied) both in the editor viewport and in the Blueprint preview panel.

Actual Result:

The morph target does not apply reliably.

In the editor viewport, the jersey clips into the body.

Hi, sorry for the delay getting back to you on this. There are a number of different issues at play here with the morph target pipeline so it’s taken a while to dig through the code and look at the different options.

The challenge here is more than just being able to call SetMorphTarget from the construction script. The whole pipeline at the moment requires an animation update to push the morph target data to the renderer (although there is no fundamental reason that should actually be needed to apply a morph). And by default, at least, there’s no animation update running on a mesh in the level viewport. Using Leader Pose also adds an extra level of complexity.

The best approach will depend on what’s acceptable for your project. One option is to for the animation update to run on meshes in the level viewport by setting bUpdateAnimationInEditor on your lead mesh component. With that set, you can push the morph target data in two ways:

  • An anim blueprint (or post-process anim blueprint) on the lead mesh component. This anim bp would contain a ModifyCurve node, which would set the morph target curve value. For this curve to be copied to the follower mesh, it has to be added specifically as a morph target curve in the skeleton of the lead component (see the screenshot below - only morph and material curves are copied to follower components). With the skeleton and anim bp setup like that, and bUpdateAnimationInEditor set on the lead mesh, the morph should appear in the level viewport.[Image Removed]
  • Call SetMorphTarget directly on the follower mesh each tick. There isn’t really a good way to do this from a blueprint (unless you force your actor to tick in the editor), so it’s likely you may want to do this in C++ from the mesh component tick. With bUpdateAnimationInEditor set, the morph value will propagate to the renderer and should be displayed. (You need to call it every frame because the follower mesh update clears the morph target curves each frame.)

If you don’t want the animation update to run in the level viewport, then things get more complicated, and you will need some kind of code implementation. As I mentioned, there’s no fundamental reason why the animation update should need to run to set a morph. But currently, the pipeline requires that it does. I have some modifications that allow this to be bypassed for regular mesh components, but I don’t have this working for follower components at the moment, as that adds extra complexity. So let me know if this is an approach that you would be interested in, and I can investigate further.

Hi Euan, thank you for your response. I don’t think the first method will work for us since (a) we don’t assign an Anim BP to the character by default. We assign it at runtime and (b) we don’t use Anim BP curves to modify morph target values. But this is something we can adjust. The second method would require calling SetMorphTarget on every follower mesh each tick, which doesn’t seem ideal.

We found a different workaround that works for us by deferring SetLeaderPoseComponent calls to the next tick.

  1. When we create a mesh component and attach it to the leader mesh, we add it to PendingFollowers.
  2. After all follower meshes are attached, we call ScheduleLinkFollowersNextTick().
  3. In ScheduleLinkFollowersNextTick() we use FTSTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UNbaCharacterMeshComponent::HandleLinkFollowersTick), 0.0f).
  4. In HandleLinkFollowersTick() we loop through the pending followers and set their leader pose.
  5. Finally, we call RefreshBoneTransform() after assigning all LeaderPoseComponent.

With this method, morph targets are still applied during construction. We also need to rebuild meshes in BeginPlay() to make sure morphs and leader poses are correct at runtime.

We are not completely sure why this approach works, but I thought it would be useful to share. Do you have any insight on this? Thank you.

Hi, some of the code you mentioned appears to be specific to your project, but I think what you’re doing in general sounds sensible. You didn’t mention how/when in the process you’re setting the morph targets, but I assume you’re doing that first before you set the leader pose component in HandleLinkFollowersTick. By setting the morph target on the mesh first, then setting the lead component, you avoid the extra complications that I mentioned that occur when the mesh is a follower component.

> With this method, morph targets are still applied during construction. We also need to rebuild meshes in BeginPlay() to make sure morphs and leader poses are correct at runtime.

This also makes sense. It’s actually the reason why SetMorphTarget is marked as not callable in construction scripts. As you’ve seen, the morphs also have to be set at runtime since the various curve containers for the morphs aren’t serialized, so without also doing this in runtime code, you wouldn’t see the morphs applied in a cooked build.