仿真实体 +ModelId:DroneSpec/FireUnitSpec/SensorSpec → EntitySnapshot

- DroneSpec/FireUnitSpec/SensorSpec 加 ModelId (FK→ModelInfo)
- DroneEntity/PlatformEntity/DetectionEntity 内部带 ModelId
- DetectionSource +ModelId
- EntitySnapshot +ModelId,每帧推送给 Unity
- CollectSnapshots 传播所有实体 ModelId
This commit is contained in:
tian 2026-06-19 09:59:55 +08:00
parent 7415d07d9f
commit c8e066be64
7 changed files with 27 additions and 6 deletions

View File

@ -154,6 +154,7 @@ namespace CounterDrone.Core.Algorithms
public float MaxElevation { get; set; } = float.MaxValue;
public float MinDetectAlt { get; set; } = float.MaxValue;
public float MaxDetectAlt { get; set; } = float.MaxValue;
public string? ModelId { get; set; }
}
/// <summary>规划方案</summary>

View File

@ -114,6 +114,9 @@ namespace CounterDrone.Core
public double MuzzleVelocity { get; set; }
public double CruiseSpeed { get; set; }
public double ReleaseAltitude { get; set; }
/// <summary>3D 模型 IDFK → ModelInfoUnity 可视化用</summary>
public string ModelId { get; set; } = "";
[SQLite.Ignore]
public List<int> AmmoTypes { get; set; } = new();
public double RadarRange { get; set; }
@ -157,6 +160,9 @@ namespace CounterDrone.Core
public double TypicalSpeed { get; set; }
public double TypicalAltitude { get; set; }
/// <summary>3D 模型 IDFK → ModelInfoUnity 可视化用</summary>
public string ModelId { get; set; } = "";
public ScenarioDrone ToScenarioDrone(string waveId = "default")
{
return new ScenarioDrone
@ -179,6 +185,9 @@ namespace CounterDrone.Core
public double EORange { get; set; }
public double IRRange { get; set; }
public double Accuracy { get; set; } = 50.0;
/// <summary>3D 模型 IDFK → ModelInfoUnity 可视化用</summary>
public string ModelId { get; set; } = "";
// 3D 球冠几何(缺失时退化 2D
public double? MinElevation { get; set; }
public double? MaxElevation { get; set; }

View File

@ -12,6 +12,7 @@ namespace CounterDrone.Core.Simulation
{
public string Id { get; }
public DetectionSource Source { get; }
public string? ModelId { get; }
public float PosX => Source.Position.X;
public float PosY => Source.Position.Y;
public float PosZ => Source.Position.Z;
@ -19,10 +20,11 @@ namespace CounterDrone.Core.Simulation
/// <summary>每无人机 Id → 探测状态true=Detected, false=Undetected</summary>
private readonly Dictionary<string, bool> _droneStates = new();
public DetectionEntity(string id, DetectionSource source)
public DetectionEntity(string id, DetectionSource source, string? modelId = null)
{
Id = id;
Source = source;
ModelId = modelId;
}
/// <summary>检查目标是否在本设备探测范围内3D 球冠判定)</summary>

View File

@ -14,6 +14,7 @@ namespace CounterDrone.Core.Simulation
public PowerType PowerType { get; }
public float Wingspan { get; }
public float CruiseSpeed { get; }
public string? ModelId { get; }
public List<Waypoint> Route { get; }
public float PosX { get; private set; }
public float PosY { get; private set; }
@ -48,6 +49,7 @@ namespace CounterDrone.Core.Simulation
DroneType = (DroneType)spec.DroneType;
PowerType = (PowerType)spec.PowerType;
Wingspan = (float)spec.Wingspan;
ModelId = string.IsNullOrEmpty(spec.ModelId) ? null : spec.ModelId;
float spd = (float)route[0].Speed;
if (spd <= 0) throw new InvalidOperationException($"无人机 {id}: 航路点速度必须 > 0");
CruiseSpeed = spd;

View File

@ -44,6 +44,8 @@ namespace CounterDrone.Core.Simulation
// 地基平台
public float MuzzleVelocity { get; }
public string? ModelId { get; }
/// <summary>Ready 包含:冷却就绪 + 有弹药 + 非飞行中</summary>
public bool Ready => CooldownRemaining <= 0 && MunitionCount > 0 && State != PlatformState.FlyingToTarget;
@ -61,6 +63,7 @@ namespace CounterDrone.Core.Simulation
MuzzleVelocity = (float)spec.MuzzleVelocity;
CruiseSpeed = (float)spec.CruiseSpeed;
ReleaseAltitude = (float)spec.ReleaseAltitude;
ModelId = string.IsNullOrEmpty(spec.ModelId) ? null : spec.ModelId;
PatrolX = PosX;
PatrolY = PosY;

View File

@ -40,6 +40,8 @@ namespace CounterDrone.Core.Simulation
public float VelX, VelY, VelZ;
public string? ModelId;
/// <summary>仅 Flush 入库时使用,仿真期间保持 null</summary>
public string? StateData;
}

View File

@ -161,7 +161,7 @@ namespace CounterDrone.Core.Simulation
var detectionSrcs = BuildDetectionSources(config, _fireUnitSpecs, _sensorSpecs);
int detIdx = 0;
foreach (var src in detectionSrcs)
_detectionEntities.Add(new DetectionEntity($"det_{++detIdx}", src));
_detectionEntities.Add(new DetectionEntity($"det_{++detIdx}", src, src.ModelId));
_munitions.Clear();
_clouds.Clear();
@ -492,11 +492,12 @@ namespace CounterDrone.Core.Simulation
RadarRange = (float)spec.RadarRange,
EORange = (float)spec.EORange,
IRRange = (float)spec.IRRange,
Accuracy = (float)(spec.MinElevation.HasValue ? 50f : 50f), // default accuracy
Accuracy = (float)(spec.MinElevation.HasValue ? 50f : 50f),
MinElevation = (float)(spec.MinElevation ?? float.MaxValue),
MaxElevation = (float)(spec.MaxElevation ?? float.MaxValue),
MinDetectAlt = (float)(spec.MinDetectAlt ?? float.MaxValue),
MaxDetectAlt = (float)(spec.MaxDetectAlt ?? float.MaxValue),
ModelId = string.IsNullOrEmpty(spec.ModelId) ? null : spec.ModelId,
});
}
}
@ -519,6 +520,7 @@ namespace CounterDrone.Core.Simulation
MaxElevation = (float)(sensor.MaxElevation ?? float.MaxValue),
MinDetectAlt = (float)(sensor.MinDetectAlt ?? float.MaxValue),
MaxDetectAlt = (float)(sensor.MaxDetectAlt ?? float.MaxValue),
ModelId = string.IsNullOrEmpty(sensor.ModelId) ? null : sensor.ModelId,
});
}
}
@ -553,7 +555,7 @@ namespace CounterDrone.Core.Simulation
{
var d = _drones[i];
float vx = d.PosX - d.PrevX, vy = d.PosY - d.PrevY, vz = d.PosZ - d.PrevZ;
_snapshotPool.Add(new EntitySnapshot { EntityId = d.Id, EntityType = Models.EntityType.Drone, PosX = d.PosX, PosY = d.PosY, PosZ = d.PosZ, VelX = vx, VelY = vy, VelZ = vz, DamageStage = (int)_damageModel.GetDamageStage(1 - d.Hp), Hp = d.Hp });
_snapshotPool.Add(new EntitySnapshot { EntityId = d.Id, EntityType = Models.EntityType.Drone, PosX = d.PosX, PosY = d.PosY, PosZ = d.PosZ, VelX = vx, VelY = vy, VelZ = vz, DamageStage = (int)_damageModel.GetDamageStage(1 - d.Hp), Hp = d.Hp, ModelId = d.ModelId });
}
for (int i = 0; i < _munitions.Count; i++)
{
@ -565,12 +567,12 @@ namespace CounterDrone.Core.Simulation
{
var p = _platforms[i];
var (vx, vy, vz) = p.CurrentVelocity;
_snapshotPool.Add(new EntitySnapshot { EntityId = p.Id, EntityType = Models.EntityType.Platform, PosX = p.PosX, PosY = p.PosY, PosZ = p.PosZ, VelX = vx, VelY = vy, VelZ = vz, PlatformStateStr = p.State.ToString() });
_snapshotPool.Add(new EntitySnapshot { EntityId = p.Id, EntityType = Models.EntityType.Platform, PosX = p.PosX, PosY = p.PosY, PosZ = p.PosZ, VelX = vx, VelY = vy, VelZ = vz, PlatformStateStr = p.State.ToString(), ModelId = p.ModelId });
}
for (int i = 0; i < _detectionEntities.Count; i++)
{
var d = _detectionEntities[i];
_snapshotPool.Add(new EntitySnapshot { EntityId = d.Id, EntityType = Models.EntityType.DetectionEquip, PosX = d.PosX, PosY = d.PosY, PosZ = d.PosZ });
_snapshotPool.Add(new EntitySnapshot { EntityId = d.Id, EntityType = Models.EntityType.DetectionEquip, PosX = d.PosX, PosY = d.PosY, PosZ = d.PosZ, ModelId = d.ModelId });
}
for (int i = 0; i < _clouds.Count; i++)
{