fix: FireUnit不拆通道 + PlatformIndex按unitIdx*TotalChannels+ch映射

- BuildFireUnits: 一个物理单元 = 一个 FireUnit(TotalChannels = GunCount*ChannelsPerGun)
- _entityCounter 在平台创建前重置为0,platform ID从1开始
- GenerateFireEventsAt 通过 unitIdx*TotalChannels+ch 计算 PlatformIndex
- 移除赋值循环中覆盖 PlatformIndex 的代码
This commit is contained in:
tian 2026-06-13 15:44:35 +08:00
parent 2162a342b7
commit 6cd18bf142
2 changed files with 25 additions and 27 deletions

View File

@ -172,13 +172,17 @@ namespace CounterDrone.Core.Algorithms
float stagger = Kinematics.CloudCoverInterval(effR2 * 2f, (float)threat.Target.TypicalSpeed, c.Unit.ChannelInterval);
var fevents = new List<FireEvent>();
int unitIdx = fireUnits.IndexOf(c.Unit);
for (int ch = 0; ch < toTake; ch++)
{
float offset = (eventIdx - (totalRoundsNeeded - 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 = unitBaseTime + (baseRoundInLane + ch) * stagger;
e.PlatformIndex = unitIdx * c.Unit.TotalChannels + ch;
}
fevents.AddRange(fe);
eventIdx++;
}
@ -193,11 +197,6 @@ namespace CounterDrone.Core.Algorithms
foreach (var (unit, rounds, fireEvents) in assignedUnits)
{
// 平台索引 = 该单元在 fireUnits 列表中的位置
int platIndex = fireUnits.IndexOf(unit);
// 修正 FireEvent 的平台索引
foreach (var fe in fireEvents) fe.PlatformIndex = platIndex;
plan.Assignments.Add(new UnitAssignment
{
FireUnitId = unit.Id,

View File

@ -105,6 +105,9 @@ namespace CounterDrone.Core.Simulation
}
}
// 平台 ID 从 1 开始,确保与报告映射一致
_entityCounter = 0;
_platforms.Clear();
foreach (var equip in config.Equipment)
if (equip.EquipmentRole != (int)EquipmentRole.Detection)
@ -293,33 +296,29 @@ namespace CounterDrone.Core.Simulation
private static List<FireUnit> BuildFireUnits(TaskFullConfig config)
{
var units = new List<FireUnit>();
int idx = 0;
foreach (var eq in config.Equipment.Where(e => e.EquipmentRole == (int)EquipmentRole.LaunchPlatform))
{
int qty = Math.Max(1, eq.Quantity);
int gunCount = eq.GunCount ?? 1;
int chPerGun = eq.ChannelsPerGun ?? 1;
int channels = gunCount * chPerGun;
for (int i = 0; i < qty; i++)
{
// 每个火力单元展开为独立通道GunCount × ChannelsPerGun
int gunCount = eq.GunCount ?? 1;
int chPerGun = eq.ChannelsPerGun ?? 1;
for (int g = 0; g < gunCount; g++)
for (int ch = 0; ch < chPerGun; ch++)
{
units.Add(new FireUnit
{
Id = $"fu{idx++}",
Type = (PlatformType)(eq.PlatformType ?? (int)PlatformType.GroundBased),
Position = new Algorithms.Vector3((float)eq.PositionX + i * 50, (float)eq.PositionY, (float)eq.PositionZ),
GunCount = 1, ChannelsPerGun = 1, ChannelInterval = (float)(eq.ChannelInterval ?? 1),
CruiseSpeed = (float)(eq.CruiseSpeed ?? 0f),
ReleaseAltitude = (float)(eq.ReleaseAltitude ?? 0f),
MuzzleVelocity = (float)(eq.MuzzleVelocity ?? 0f),
// 总弹药均分到每个通道
TotalMunitions = (eq.MunitionCount ?? 1) / (gunCount * chPerGun),
AmmoTypes = new List<AerosolType> { (AerosolType)(eq.AerosolType ?? 0) },
Cooldown = (float)eq.Cooldown,
});
}
units.Add(new FireUnit
{
Id = $"fu{units.Count}",
Type = (PlatformType)(eq.PlatformType ?? (int)PlatformType.GroundBased),
Position = new Algorithms.Vector3((float)eq.PositionX + i * 50, (float)eq.PositionY, (float)eq.PositionZ),
GunCount = gunCount,
ChannelsPerGun = chPerGun,
ChannelInterval = (float)(eq.ChannelInterval ?? 1),
CruiseSpeed = (float)(eq.CruiseSpeed ?? 0f),
ReleaseAltitude = (float)(eq.ReleaseAltitude ?? 0f),
MuzzleVelocity = (float)(eq.MuzzleVelocity ?? 0f),
TotalMunitions = eq.MunitionCount ?? channels,
AmmoTypes = new List<AerosolType> { (AerosolType)(eq.AerosolType ?? 0) },
Cooldown = (float)eq.Cooldown,
});
}
}
return units;