Am I setting up this Sequence correctly? Are we correct in assuming I should be able to constrain a Layered Control Rig node in this way?
Some additional context - Our studio is on UE 5.6. In 5.6, the Constraints.NewEvaluation Console Var is false by default, so the old evaluation scheme is the default. That old scheme does not have this issue - I can constrain Layered control rig nodes without jitter. But we keep hitting crashes with the old scheme, due to non-thread safe animation evaluation.
So, we are trying out the Constraints.NewEvaluation scheme, which is enabled by default in 5.7 and according to Perforce changelist descriptions, should address the threaded issues and improve performance. But this issue described in the ticket is making the new scheme unusable for us.
In the example Sequence in this ticket, this is in 5.7 Preview. Looking at Epic Perforce, I believe updates have been made to the Constraint codebase since 5.7 Preview was released. Is it possible that these new updates would solve this issue?
In a ThirdPersonTemplate Project, create a New Level Sequence
Add a Skeletal Mesh Actor to the Sequence, SKM_Quinn_Simple.
Delete the Control Rig track and add a new Control Rig with Layered checked, so CR_Mannequin_Body (Layered) is added to SKM_Quinn_Simple
Assign an Animation to SKM_Quin_Simple Animation track - MM_Dash
Add a Static Mesh Actor to the Sequence, Cube
Add a Transform.Location Key of (0, 200, 0) at frame 0
Using the Constraints tab in Animation Mode, create a Constraint between SKM_Quin_Simple hand_r_fk_ctrl and the Cube [Image Removed]
When Creating the Constraint, make sure Use Current Offset and Maintain Offset are false
Setup should look like this [Image Removed]
Play the Sequence, Looping the Playback Range. Observe how the hand_r_fk_ctrl does not stay constrained to the Cube Transform. In the Attachments of this ticket is a video.
I’ll let you know if and when there is a workaround. I’m curious how often the crashes are? Are crashes relatively easy to repro with a default mannequin? I haven’t been able to trigger it.
I appreciate the issue ticket, I’ll keep an eye on it for 5.7 updates.
I can provide you a repro for the type of crash we are hitting using default mannequin. I have hit this crash is 5.6 and in 5.7 with CVar Constraints.NewEvaluation set to False. It’s a race condition, which I believe can happen with an even simpler setup, but using this setup you will likely hit the crash quickly.
Steps to Reproduce Crash with Constrained Layered Control Rigs in Constraint “Old” Evaluation Scheme
Make sure CVar Constraints.NewEvaluation is false. It is false by default in 5.6 but in 5.7 it is true by default so you will have to set it.
In a ThirdPersonTemplate Project, create a New Level Sequence
Add 2 Skeletal Mesh Actors to the Sequence, SKM_Quinn_Simple and SKM_Quinn_Simple2.
Delete the Control Rig track from SKM_Quinn_Simple and add a new Control Rig with Layered checked, so CR_Mannequin_Body (Layered) is added to SKM_Quinn_Simple
Add a Static Mesh Actor to the Sequence, Cube
Add a Transform.Location Key of (0, 200, 0) at frame 0
Using the Constraints tab in Animation Mode, create a Constraint between SKM_Quinn_Simple2 and the Cube [Image Removed]When Creating the Constraint, make sure Use Current Offset and Maintain Offset are false. This will snap SKM_Quin_Simple2 to the Cube.
Next, using the Constraints tab in Animation Mode, create another Constraint between SKM_Quinn_Simple, hand_r_fk_ctrl and SKM_Quin_Simple2 head (just the regular head bone not on the Control Rig). Make sure Use Current Offset and Maintain Offset are false again. [Image Removed]
Setup should look like this [Image Removed]
No animations need to be added to the Skeletal Mesh Actors.
Play the Sequence, Looping the Playback Range. You might have to let the sequence loop several times, up to a minute or two. But eventually, the editor will crash. I’ve attached the /Saved/Crashes folder from my project.
When I dug into this on my end, I think this is because of a lack of a prerequisite to make sure the constrained child component ticks after the constraint. The SKM_Quinn_Simple Skeletal Mesh Component can sometimes tick before the constraint that constraints the hand_r to the SKM_Quinn_Simple2 head. In this situation, animation can be evaluating on a worker thread while the constraint starts its tick.
The animation worker thread evaluates Control Rig and ends up triggering the UTickableParentConstraint::OnHandleModified callback, which ends up accessing the FRigPose object. Meanwhile, the constraint is ticking and trying to set the control value for hand_r. UTickableTransformConstraint::SetGlobalTransform ends up accessing the same FRigPose object at the same time, resulting in the crash.
Thanks for the crash report and the debug advice. I’ve passed it along as bug information for the moment since we want the new evaluation method to be our primary method. In the meantime, I’ll see if I can get you a workaround the crash as well, whatever comes first.