Skip to content

Frag - Sort fragment bounce target list by distance#11143

Merged
PabstMirror merged 1 commit intoacemod:masterfrom
Kitanagoya5381-ARMA3:fix/fragment-bounce-target-sorting
Nov 28, 2025
Merged

Frag - Sort fragment bounce target list by distance#11143
PabstMirror merged 1 commit intoacemod:masterfrom
Kitanagoya5381-ARMA3:fix/fragment-bounce-target-sorting

Conversation

@Hotel2622
Copy link
Copy Markdown
Contributor

Before

IMAGE ALT TEXT HERE

https://www.youtube.com/watch?v=plp0JCyKF9I

After

IMAGE ALT TEXT HERE

https://www.youtube.com/watch?v=6zzXQA7VR3A

Summary

Fragment bounce target selection was relying on a plain array with no
sorting applied. As a result, the bounce logic processed units in whatever
order they happened to be inserted, which created inconsistent behavior.

This PR adds explicit sorting so that the closest targets are always
evaluated first.

Benchmarking

To verify the best sorting approach, I benchmarked multiple methods.
I’m still fairly new to Arma scripting, so there may be a better or more
idiomatic solution that I’m not aware of:

  • BIS_fnc_sortBy using distance
  • BIS_fnc_sortBy using distanceSqr
  • Using apply to build an array of [distanceSquared, target],
    sorting it with native sort, then extracting the targets again

Summary of results

Method 100 Time Notes
sortDistance 21.0037 ms Slowest
sortDistanceSqr 19.9966 ms Slightly faster
sortApply 8.00323 ms Fastest (~2–3× faster)

Test code used:

TRACE_1("",_targets);

// Benchmark using BIS_fnc_sortBy with distance
BEGIN_COUNTER(sortDistance)
private _targets1 = [];
for "i" from 0 to 100 step 1 do {
	_targets1 = [_targets, [], { _fragPosAGL distance _x }, "ASCEND"] call BIS_fnc_sortBy;
};
END_COUNTER(sortDistance)

// Benchmark using BIS_fnc_sortBy with distance squared
BEGIN_COUNTER(sortDistanceSqr)
private _targets2 = [];
for "i" from 0 to 100 step 1 do {
	_targets2 = [_targets, [], { _fragPosAGL distanceSqr _x }, "ASCEND"] call BIS_fnc_sortBy;
};
END_COUNTER(sortDistanceSqr)

// Benchmark using apply + native sort pattern
BEGIN_COUNTER(sortApply)
private _targets3 = [];
for "i" from 0 to 100 step 1 do {
	_targets3 = _targets apply { [_x distanceSqr _fragPosAGL, _x] };
	_targets3 sort true;
	_targets3 = _targets3 apply {_x#1};
};
END_COUNTER(sortApply)

_targets = _targets3;
TRACE_1("",_targets1);
TRACE_1("",_targets2);
TRACE_1("",_targets3);
[] call ace_common_fnc_dumpPerformanceCounters;

Test code result:

20:33:17 [ACE] (frag) TRACE: 2140 frago: _fragPosASL=[5577.67,4574.79,5], _shellType=ModuleOrdnanceMortar_F_ammo z\ace\addons\frag\functions\fnc_frago.sqf:24
20:33:17 [ACE] (frag) TRACE: 2140 : _maxFrags=50, CBA_missionTime - ace_frag_lastFragTime=17.897 z\ace\addons\frag\functions\fnc_frago.sqf:35
20:33:17 [ACE] (frag) TRACE: 2140 fragValues: _fragPosASL=[5577.67,4574.79,5], _fragPosAGL=[5577.67,4574.79,0], _fragRange=1440, _fragVelocity=744.142, _metalMassModifier=1.63707 z\ace\addons\frag\functions\fnc_frago.sqf:41
20:33:17 [ACE] (frag) TRACE: 2140 : _fragRange=1440, count _targets=112, _targets=[B 알파 1-3:1,B 알파 1-3:2,B 알파 1-3:3,B 알파 1-3:4,....
20:33:17 [ACE] (frag) TRACE: 2140 : _targets=[B 알파 1-3:1,B 알파 1-3:2,B 알파 1-3:3,B 알파 1-3:4,....
20:33:17 [ACE] (frag) TRACE: 2140 : _targets1=[B 알파 2-4:7,B 알파 2-5:7,B 알파 2-4:5,B 알파 2-5:5,....
20:33:17 [ACE] (frag) TRACE: 2140 : _targets2=[B 알파 2-4:7,B 알파 2-5:7,B 알파 2-4:5,B 알파 2-5:5,....
20:33:17 [ACE] (frag) TRACE: 2140 : _targets3=[B 알파 2-4:7,B 알파 2-5:7,B 알파 2-4:5,B 알파 2-5:5,....

20:33:17 ace_frag_frago_counter: No results
20:33:17 ace_frag_sortDistance_counter: Average: 0.0210037s / 1 = 21.0037ms
20:33:17 ace_frag_sortDistanceSqr_counter: Average: 0.0199966s / 1 = 19.9966ms
20:33:17 ace_frag_sortApply_counter: Average: 0.00800323s / 1 = 8.00323ms

Notes / Question for Reviewers

Based on my measurements, the apply + sort + extract pattern seems to
perform best over repeated iterations, but I'm not fully certain if this
is the correct or preferred approach within ACE.

Result

  • Targets are now processed in deterministic, distance-based order.
  • Fragment bounce behavior is stable and predictable.
  • Sorting performance has been tested with three different methods.

Fragment bounce was selecting targets in an inconsistent order because
the system used an unsorted array. Implemented explicit distance-based
sorting to ensure nearest targets are evaluated first, resulting in
consistent and predictable fragment bounce behavior.
@rautamiekka
Copy link
Copy Markdown
Contributor

Did you really use a global i in the for loops ?

@PabstMirror PabstMirror added this to the 3.20.2 milestone Nov 19, 2025
@PabstMirror PabstMirror added the kind/enhancement Release Notes: **IMPROVED:** label Nov 19, 2025
Copy link
Copy Markdown
Contributor

@PabstMirror PabstMirror left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good

@Hotel2622
Copy link
Copy Markdown
Contributor Author

Did you really use a global i in the for loops ?

Thanks for pointing that out —
I completely forgot that for "i" writes to the global i.
That could definitely conflict with other code using the same variable.

I’ll make sure to use a private loop counter for [{ private _i = 0 }, going forward. Thank you!😁

@rautamiekka
Copy link
Copy Markdown
Contributor

I’ll make sure to use a private loop counter for [{ private _i = 0 }, going forward. Thank you!😁

If you used that slow, ancient format, then yeah.

@PabstMirror PabstMirror changed the title fix(frag): add proper sorting for fragment bounce target list Frag - Sort fragment bounce target list by distance Nov 28, 2025
@PabstMirror PabstMirror merged commit a4ea70c into acemod:master Nov 28, 2025
3 checks passed
@Hotel2622 Hotel2622 deleted the fix/fragment-bounce-target-sorting branch December 9, 2025 08:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/enhancement Release Notes: **IMPROVED:**

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants