From d70d1f0bf88563dfcd3701f4916e525780660608 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Sun, 14 Jun 2026 22:12:32 +0800 Subject: [PATCH] fix: multi-lane cloud offset used global index instead of per-lane index Bug: offset = (eventIdx - (totalRoundsNeeded-1)/2) * spacing used global eventIdx across all lanes. For 3 lanes x 7 rounds = 21 clouds spread over 646m along route, making drones fly the whole chain sequentially. Fix: offset = (roundInLane - (singleNeeded-1)/2) * spacing. Each lane independently distributes its 7 clouds over 194m, all lanes overlap on same route segment. Drones hit simultaneously. Result: 3 drones destroyed at same time (t=91.6s, same X=5089), was sequential 87/91/96s. 193 tests pass. --- src/CounterDrone.Core/Algorithms/DefensePlanner.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/CounterDrone.Core/Algorithms/DefensePlanner.cs b/src/CounterDrone.Core/Algorithms/DefensePlanner.cs index b52e27f..5a366d1 100644 --- a/src/CounterDrone.Core/Algorithms/DefensePlanner.cs +++ b/src/CounterDrone.Core/Algorithms/DefensePlanner.cs @@ -142,7 +142,6 @@ namespace CounterDrone.Core.Algorithms for (int l = 0; l < yLanes; l++) laneNeeded[l] = singleNeeded; int currentLane = 0; int roundsCollected = 0; - int eventIdx = 0; var assignedUnits = new List<(FireUnit unit, int rounds, List events)>(); foreach (var c in candidates.OrderBy(c => c.EarliestInterceptTime) @@ -170,19 +169,21 @@ namespace CounterDrone.Core.Algorithms var fevents = new List(); int unitIdx = fireUnits.IndexOf(c.Unit); + int baseRoundInLane = singleNeeded - laneNeeded[currentLane]; for (int ch = 0; ch < toTake; ch++) { - float offset = (eventIdx - (totalRoundsNeeded - 1) / 2f) * spacing; + // offset 基于车道内发序(不是全局 eventIdx),使每车道独立分布在同一航路段, + // 多车道重叠覆盖而非沿航路连成长链 + int roundInLane = baseRoundInLane + ch; + float offset = (roundInLane - (singleNeeded - 1) / 2f) * spacing; var fe = GenerateFireEventsAt(threat, c.Unit, c.AmmoType, ammo, env, offset, yLane, yLanes, formationWidth); - int baseRoundInLane = singleNeeded - laneNeeded[currentLane]; foreach (var e in fe) { - e.FireTime = laneBaseTime[yLane] + (baseRoundInLane + ch) * stagger; + e.FireTime = laneBaseTime[yLane] + roundInLane * stagger; // TargetX/Z 保留 GenerateFireEventsAt 算出的风偏补偿后抛撒点 cloudGenX/Z e.PlatformIndex = unitIdx * c.Unit.TotalChannels + ch; } fevents.AddRange(fe); - eventIdx++; } assignedUnits.Add((c.Unit, toTake, fevents));