Description

When an entity stops being batched into an instanced skinned mesh component, the "Collect unwanted items & remove" sweep removes its instance, but never frees its ASTP track. Only ProcessRemovesForComponent calls DeallocateTrack, and outside the stationary ISM switcher and its destructor nothing in MassRepresentation calls RemoveInstance. So for a moving entity the sweep is the only way out of a component, and every despawn, LOD change or significance range change leaves a track behind.

The leaked track stays active, so it is still uploaded every frame, and it keeps its last sequence index. Once that sequence is released with DeallocateSequence, the ensure fires and the track is left pointing at a freed slot.

This is the non-external-ID path. The sweep is the same in //UE5/Main MassVisualizationComponent.cpp#74 (around line 951) and //UE6/Main #12 (around line 1069). We are on 5.8 with 57928894 and 58169258 cherry-picked from UE5/Main, which is where AllocateSequence and DeallocateSequence come from.

Steps to Reproduce

Steps to Reproduce

I have not isolated this into a template project, but it is all stock Mass and ASTP code. The sweep in our build is unmodified apart from the fix in the description.

 

  1. Set up Mass entities with a SkinnedMeshInstance representation whose FMassSkinnedMeshInstanceVisualizationMeshDesc has a UAnimSequenceTransformProviderData as its TransformProvider. UMassVisualizationComponent gives each component its own UAnimSequenceTransformProviderDataInstance.
  2. Drive them with UMassUpdateInstancedSkinnedMeshProcessor plus FMassRepresentationAnimationFragment and UMassConsumeInstancedSkinnedMeshAnimationProcessor, so each entity gets a track.
  3. Make some entities stop being batched into that component: despawn them, LOD them to Actor or None, or move them to another significance range.
  4. The "Collect unwanted items & remove" sweep removes their instances, but their tracks stay allocated and active, and their TrackMap and ResolvedAnimStates entries stay too. A track is only reused if the same entity comes back to that component, which a despawned one never does.
  5. Play a sequence added at runtime with AllocateSequence, then release it with DeallocateSequence once no live entity plays it. If a leaked track last played it, a non-shipping build hits the "sequence slot %d released while set on track %d layer %d" ensure.

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-401320 in the post.

0
Login to Vote

Unresolved
CreatedOct 7, 2026
UpdatedOct 7, 2026
View Jira Issue