UAF FMontageTrait evaluates its Source child without updating it once a montage reaches full weight

Summary

When a montage playing in a UAF Montage slot reaches full weight, the slot’s Source input stops being updated but is still evaluated every frame (with “Always Update Source” unchecked, which is the default).

Cause (ue5-main line numbers): FMontageTrait::QueueChildrenForTraversal only queues the Source child while its weight is relevant (MontageTrait.cpp:531), but GetChildren returns Source unconditionally (:521), and the evaluate traversal visits every valid child without checking it was updated (IEvaluate.cpp:172-178). FBlendLayerTrait in the same module handles its inactive child correctly by resetting it; FMontageTrait never resets Source.

Second effect: at full weight the source pose weight is also not added to the blend list (MontageTrait.cpp:335), so the stale source keyframe is never consumed. It stays on the VM keyframe stack, and a downstream two-pose blend (e.g. per-bone masked layering) blends against the stale keyframe instead of the intended one.

Workaround: tick “Always Update Source” on the Montage node. Confirmed working.

Suggested fix: make the two traversals agree - either skip evaluating a Source that wasn’t queued for update (like FBlendLayerTrait does), or keep it updated and append its weight so the keyframe is consumed.

Repro’d on 5.8.1; code unchanged on ue5-main as of 2026-08-03.

What Type of Bug are you experiencing?

Animation

Steps to Reproduce

  1. Project with the UAF plugins enabled (UAF, UAFAnimGraph, UAFPoseSearch).
  2. UAF animation graph with a Motion Matching node.
  3. Add a Montage node and connect the Motion Matching output to its Source input. Leave “Always Update Source” unchecked (default).
  4. Play any montage in that slot whose blend-in completes (weight reaches 1.0).
  5. Watch the output log while it’s at full weight.

Expected Result

No errors - a child that isn’t updated on a frame shouldn’t be evaluated that frame.

Observed Result

Once per frame while the montage is at full weight:

LogPoseSearch: Error: FMotionMatchingTrait::PostEvaluate, PostEvaluate called without calling PreUpdate on this frame! Some trait in the TraitStack doesn’t propagate correctly the PreUpdate!
LogPoseSearch: Error: FHistoryCollectorTrait::PostEvaluate, PostEvaluate called without calling PreUpdate on this frame! Some trait in the TraitStack doesn’t propagate correctly the PreUpdate!

It stops during blend-in/out (the source weight is relevant then), so it looks intermittent.

Affects Versions

5.8

Platform(s)

Windows