diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index 3a5e3c098f..289578f3d8 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -225,10 +225,19 @@ protected override void Update() hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject); toComputeLifetime.Clear(); + } - // only AliveObjects need to be considered for layout (reduces overhead in the case of scroll speed changes). + protected override void UpdateAfterChildrenLife() + { + base.UpdateAfterChildrenLife(); + + // We need to calculate hit object positions (including nested hit objects) as soon as possible after lifetimes + // to prevent hit objects displayed in a wrong position for one frame. + // Only AliveObjects need to be considered for layout (reduces overhead in the case of scroll speed changes). foreach (var obj in AliveObjects) { + updatePosition(obj, Time.Current); + if (layoutComputed.Contains(obj)) continue; @@ -293,15 +302,6 @@ private void updateLayoutRecursive(DrawableHitObject hitObject) } } - protected override void UpdateAfterChildrenLife() - { - base.UpdateAfterChildrenLife(); - - // We need to calculate hitobject positions as soon as possible after lifetimes so that hitobjects get the final say in their positions - foreach (var obj in AliveObjects) - updatePosition(obj, Time.Current); - } - private void updatePosition(DrawableHitObject hitObject, double currentTime) { switch (direction.Value)