diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
index 2e63160d36..d1ceca6d8f 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
@@ -180,6 +180,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
this.Delay(800).FadeOut();
break;
}
+
+ Expire();
}
public Drawable ProxiedLayer => ApproachCircle;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
index bcaf73d34f..a26db06ede 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
@@ -11,6 +11,7 @@ using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Graphics.Containers;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.UI;
+using osu.Game.Rulesets.Scoring;
using osuTK;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
@@ -60,6 +61,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
PositionBindable.BindTo(HitObject.PositionBindable);
StackHeightBindable.BindTo(HitObject.StackHeightBindable);
ScaleBindable.BindTo(HitObject.ScaleBindable);
+
+ // Manually set to reduce the number of future alive objects to a bare minimum.
+ LifetimeStart = HitObject.StartTime - HitObject.TimePreempt;
+
+ // Arbitrary lifetime end to prevent past objects in idle states remaining alive in non-frame-stable contexts.
+ // An extra 1000ms is added to always overestimate the true lifetime, and a more exact value is set by hit transforms and the following expiry.
+ LifetimeEnd = HitObject.GetEndTime() + HitObject.HitWindows.WindowFor(HitResult.Miss) + 1000;
}
protected override void OnFree(HitObject hitObject)
@@ -85,14 +93,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public virtual void Shake(double maximumLength) => shakeContainer.Shake(maximumLength);
- protected override void UpdateInitialTransforms()
- {
- base.UpdateInitialTransforms();
-
- // Manually set to reduce the number of future alive objects to a bare minimum.
- LifetimeStart = HitObject.StartTime - HitObject.TimePreempt;
- }
-
///
/// Causes this to get missed, disregarding all conditions in implementations of .
///
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index f7b1894058..14c494d909 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -193,13 +193,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
return base.CreateNestedHitObject(hitObject);
}
- protected override void UpdateInitialTransforms()
- {
- base.UpdateInitialTransforms();
-
- Body.FadeInFromZero(HitObject.TimeFadeIn);
- }
-
public readonly Bindable Tracking = new Bindable();
protected override void Update()
@@ -273,6 +266,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
base.PlaySamples();
}
+ protected override void UpdateInitialTransforms()
+ {
+ base.UpdateInitialTransforms();
+
+ Body.FadeInFromZero(HitObject.TimeFadeIn);
+ }
+
protected override void UpdateStartTimeStateTransforms()
{
base.UpdateStartTimeStateTransforms();
@@ -297,7 +297,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
break;
}
- this.FadeOut(fade_out_time, Easing.OutQuint);
+ this.FadeOut(fade_out_time, Easing.OutQuint).Expire();
}
public Drawable ProxiedLayer => HeadCircle.ProxiedLayer;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 87c7146a64..2a14a7c975 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
base.UpdateHitStateTransforms(state);
- this.FadeOut(160);
+ this.FadeOut(160).Expire();
// skin change does a rewind of transforms, which will stop the spinning sound from playing if it's currently in playback.
isSpinning?.TriggerChange();