1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 19:55:45 +08:00

Optimise fallback logic to reduce lookups to bare minimum

This commit is contained in:
Dean Herbert 2021-08-24 19:05:59 +09:00
parent 6aa894e55e
commit 4a294d4de4

View File

@ -44,32 +44,44 @@ namespace osu.Game.Rulesets.UI
}; };
} }
private ISampleInfo[] playableSampleInfo; private HitObject fallbackObject;
/// <summary> /// <summary>
/// Play the most appropriate hit sound for the current point in time. /// Play the most appropriate hit sound for the current point in time.
/// </summary> /// </summary>
public void Play() public void Play()
{ {
var nextObject = var nextObject = hitObjectContainer.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current)?.HitObject;
hitObjectContainer.AliveObjects.FirstOrDefault(h => h.HitObject.StartTime > Time.Current)?.HitObject ??
// fallback to non-alive objects to find next off-screen object if (nextObject == null)
// TODO: make lookup more efficient? {
drawableRuleset.Objects.FirstOrDefault(h => h.StartTime > Time.Current) ?? if (fallbackObject == null || fallbackObject.StartTime < Time.Current)
drawableRuleset.Objects.LastOrDefault(); {
// in the case a next object isn't available in drawable form, we need to do a somewhat expensive traversal to get a valid sound to play.
// note that we don't want to cache the object if it is an alive object, as once it is hit we don't want to continue playing its sound.
// check whether we can use the previous computed sample.
// fallback to non-alive objects to find next off-screen object
// TODO: make lookup more efficient?
fallbackObject = hitObjectContainer.Entries
.Where(e => e.Result?.HasResult != true && e.HitObject.StartTime > Time.Current)?
.OrderBy(e => e.HitObject.StartTime)
.FirstOrDefault()?.HitObject ?? hitObjectContainer.Entries.FirstOrDefault()?.HitObject;
}
nextObject = fallbackObject;
}
if (nextObject != null) if (nextObject != null)
{ {
var hitSound = getNextSample(); var hitSound = getNextSample();
playableSampleInfo = GetPlayableSampleInfo(nextObject); hitSound.Samples = GetPlayableSampleInfo(nextObject).Select(s => nextObject.SampleControlPoint.ApplyTo(s)).Cast<ISampleInfo>().ToArray();
hitSound.Samples = playableSampleInfo;
hitSound.Play(); hitSound.Play();
} }
} }
protected virtual ISampleInfo[] GetPlayableSampleInfo(HitObject nextObject) => protected virtual HitSampleInfo[] GetPlayableSampleInfo(HitObject nextObject) =>
// TODO: avoid cast somehow? nextObject.Samples.ToArray();
nextObject.Samples.Cast<ISampleInfo>().ToArray();
private SkinnableSound getNextSample() private SkinnableSound getNextSample()
{ {