Skip to content

Commit 58d9792

Browse files
authored
Merge pull request #347 from winnerspiros/copilot/optimize-performance-android
Tighten gameplay hot paths by removing redundant hitobject traversal in note-lock and hitsound selection
2 parents abb3c4c + 7f7b56a commit 58d9792

2 files changed

Lines changed: 24 additions & 13 deletions

File tree

osu.Game.Rulesets.Osu/UI/StartTimeOrderedHitPolicy.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public ClickAction CheckHittable(DrawableHitObject hitObject, double time, HitRe
3030

3131
DrawableHitObject? blockingObject = null;
3232

33-
foreach (var obj in enumerateHitObjectsUpTo(hitObject.HitObject.StartTime))
33+
foreach (var obj in enumerateTopLevelAliveObjectsUpTo(hitObject.HitObject.StartTime))
3434
{
3535
if (hitObjectCanBlockFutureHits(obj))
3636
blockingObject = obj;
@@ -60,7 +60,7 @@ public void HandleHit(DrawableHitObject hitObject)
6060
throw new InvalidOperationException($"A {hitObject} was hit before it became hittable!");
6161

6262
// Miss all hitobjects prior to the hit one.
63-
foreach (var obj in enumerateHitObjectsUpTo(hitObject.HitObject.StartTime))
63+
foreach (var obj in enumerateTopLevelAliveObjectsUpTo(hitObject.HitObject.StartTime))
6464
{
6565
if (obj.Judged)
6666
continue;
@@ -77,22 +77,14 @@ public void HandleHit(DrawableHitObject hitObject)
7777
private static bool hitObjectCanBlockFutureHits(DrawableHitObject hitObject)
7878
=> hitObject is DrawableHitCircle;
7979

80-
private IEnumerable<DrawableHitObject> enumerateHitObjectsUpTo(double targetTime)
80+
private IEnumerable<DrawableHitObject> enumerateTopLevelAliveObjectsUpTo(double targetTime)
8181
{
8282
foreach (var obj in HitObjectContainer!.AliveObjects)
8383
{
8484
if (obj.HitObject.StartTime >= targetTime)
8585
yield break;
8686

8787
yield return obj;
88-
89-
foreach (var nestedObj in obj.NestedHitObjects)
90-
{
91-
if (nestedObj.HitObject.StartTime >= targetTime)
92-
break;
93-
94-
yield return nestedObj;
95-
}
9688
}
9789
}
9890
}

osu.Game/Rulesets/UI/GameplaySampleTriggerSource.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ protected override void Update()
126126
// In the case there are no non-judged objects, the last hit object should be used instead.
127127
if (candidate == null)
128128
{
129-
mostValidObject = hitObjectContainer.Entries.LastOrDefault();
129+
var (_, lastEntry) = getEntryBounds();
130+
mostValidObject = lastEntry;
130131
}
131132
else
132133
{
@@ -136,7 +137,8 @@ protected override void Update()
136137
}
137138
else
138139
{
139-
mostValidObject ??= hitObjectContainer.Entries.FirstOrDefault();
140+
var (firstEntry, _) = getEntryBounds();
141+
mostValidObject ??= firstEntry;
140142
}
141143
}
142144
}
@@ -177,6 +179,23 @@ protected override void Update()
177179
return best ?? mostValidObject.HitObject;
178180
}
179181

182+
private (HitObjectLifetimeEntry? first, HitObjectLifetimeEntry? last) getEntryBounds()
183+
{
184+
HitObjectLifetimeEntry? first = null;
185+
HitObjectLifetimeEntry? last = null;
186+
187+
foreach (var entry in hitObjectContainer.Entries)
188+
{
189+
if (first == null || entry.HitObject.StartTime < first.HitObject.StartTime)
190+
first = entry;
191+
192+
if (last == null || entry.HitObject.StartTime > last.HitObject.StartTime)
193+
last = entry;
194+
}
195+
196+
return (first, last);
197+
}
198+
180199
private bool isAlreadyHit(HitObjectLifetimeEntry h) => h.AllJudged;
181200
private bool isCloseEnoughToCurrentTime(HitObject h) => getReferenceTime() >= h.StartTime - h.HitWindows.WindowFor(HitResult.Miss) * 2;
182201

0 commit comments

Comments
 (0)