We’re having a problem with LevelSequencer when using the TransformOrigin system to animate the transform of the whole LevelSequence. It seems that the more nested levels of subsequences containing subsequences we have, the more likely the whole system ‘breaks’ and leaves behind any number of objects in these subsequences.
Looking into the problem a bit it appears to me that this is an issue with the sorted InstanceHandleToParentHandle array in UMovieSceneTransformOriginSystem. The intention when this is sorted in UMovieSceneTransformOriginSystem::OnSchedulePersistentTasks is that the array can then be processed in a linear order where the parent transforms will always be processed before children transforms are calculated, but the naive implementation of the default Sort method being used does not take into account a hierarchy that is multiple levels deep. In this case you can’t just compare the node sort order according to “is node B a parent of node A” because that ignores that fact that the grand-parent node of child node A also needs to be processed before A.
I have locally implemented a more correct sorting algorithm to replace the simple Sort, and will continue to test it but it does not, unfortunately, seem to fix the broken case in the attached repro project.
Our quick test of an improved sorting algorithm in MovieSceneTransformOriginSystem.cpp to replace line 338):
`TMap<uint16, uint16> HierarchyMap, InstanceDepthMap;
for (const FInstanceToParentPair& Pair : InstanceHandleToParentHandle)
HierarchyMap.Add(Pair.Child.InstanceID, Pair.Parent.InstanceID);
for (const FInstanceToParentPair& Pair : InstanceHandleToParentHandle)
{
uint16 InstanceID = Pair.Child.InstanceID;
uint16 Depth = 0, CurrentID = InstanceID;
while (HierarchyMap.Contains(CurrentID))
{
Depth++;
CurrentID = HierarchyMap[CurrentID];
}
InstanceDepthMap.Add(InstanceID, Depth);
}
InstanceHandleToParentHandle.Sort([&InstanceDepthMap](const FInstanceToParentPair& A, const FInstanceToParentPair& B)
{
return InstanceDepthMap[A.Child.InstanceID] < InstanceDepthMap[B.Child.InstanceID];
});`