diff --git a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs index e750727764..150ed16bab 100644 --- a/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs +++ b/osu.Game/Rulesets/UI/Scrolling/ScrollingHitObjectContainer.cs @@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.UI.Scrolling private readonly HashSet layoutComputedHitObjects = new HashSet(); // Used to recompute all lifetime when `layoutCache` becomes invalid - private readonly HashSet lifetimeComputedHitObjects = new HashSet(); + private readonly HashSet allHitObjects = new HashSet(); [Resolved] private IScrollingInfo scrollingInfo { get; set; } @@ -150,18 +150,19 @@ namespace osu.Game.Rulesets.UI.Scrolling /// public void InvalidateDrawableHitObject(DrawableHitObject hitObject) { - // Lifetime is computed once early and - // layout (Width/Height if `IHasDuration`, and nested object positions) will be computed when the object becomes alive. - // An assumption is that a hit object layout update (setting `Height` or `Width`) won't affect its lifetime. - // This is satisfied in practice because otherwise the hit object won't be aligned to its `StartTime`. - hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject); + // Lifetime computation is delayed to the next update because `scrollLength` may not be valid here. + // Layout computation will be delayed to when the object becomes alive. + // An assumption is that a hit object layout update (setting `Height` or `Width`) won't affect its lifetime but + // this is satisfied in practice because otherwise the hit object won't be aligned to its `StartTime`. + + layoutCache.Invalidate(); + + allHitObjects.Add(hitObject); - lifetimeComputedHitObjects.Add(hitObject); layoutComputedHitObjects.Remove(hitObject); } - // Use a nonzero value to prevent infinite results - private float scrollLength = 1; + private float scrollLength; protected override void Update() { @@ -170,7 +171,7 @@ namespace osu.Game.Rulesets.UI.Scrolling if (!layoutCache.IsValid) { // this.Objects cannot be used as it doesn't contain nested objects - foreach (var hitObject in lifetimeComputedHitObjects) + foreach (var hitObject in allHitObjects) hitObject.LifetimeStart = computeOriginAdjustedLifetimeStart(hitObject); layoutComputedHitObjects.Clear();