diff --git a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs index 5874f32..dd89239 100644 --- a/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs +++ b/src/CounterDrone.Core/Algorithms/AlgorithmTypes.cs @@ -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; } } /// 规划方案 diff --git a/src/CounterDrone.Core/DefaultData.cs b/src/CounterDrone.Core/DefaultData.cs index 5a9f521..156cb7c 100644 --- a/src/CounterDrone.Core/DefaultData.cs +++ b/src/CounterDrone.Core/DefaultData.cs @@ -114,6 +114,9 @@ namespace CounterDrone.Core public double MuzzleVelocity { get; set; } public double CruiseSpeed { get; set; } public double ReleaseAltitude { get; set; } + + /// 3D 模型 ID(FK → ModelInfo),Unity 可视化用 + public string ModelId { get; set; } = ""; [SQLite.Ignore] public List 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; } + /// 3D 模型 ID(FK → ModelInfo),Unity 可视化用 + 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; + + /// 3D 模型 ID(FK → ModelInfo),Unity 可视化用 + public string ModelId { get; set; } = ""; // 3D 球冠几何(缺失时退化 2D) public double? MinElevation { get; set; } public double? MaxElevation { get; set; } diff --git a/src/CounterDrone.Core/Simulation/DetectionEntity.cs b/src/CounterDrone.Core/Simulation/DetectionEntity.cs index 1bd1152..be28b37 100644 --- a/src/CounterDrone.Core/Simulation/DetectionEntity.cs +++ b/src/CounterDrone.Core/Simulation/DetectionEntity.cs @@ -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 /// 每无人机 Id → 探测状态(true=Detected, false=Undetected) private readonly Dictionary _droneStates = new(); - public DetectionEntity(string id, DetectionSource source) + public DetectionEntity(string id, DetectionSource source, string? modelId = null) { Id = id; Source = source; + ModelId = modelId; } /// 检查目标是否在本设备探测范围内(3D 球冠判定) diff --git a/src/CounterDrone.Core/Simulation/DroneEntity.cs b/src/CounterDrone.Core/Simulation/DroneEntity.cs index f9eca6d..2d1761d 100644 --- a/src/CounterDrone.Core/Simulation/DroneEntity.cs +++ b/src/CounterDrone.Core/Simulation/DroneEntity.cs @@ -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 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; diff --git a/src/CounterDrone.Core/Simulation/PlatformEntity.cs b/src/CounterDrone.Core/Simulation/PlatformEntity.cs index 96dd284..421497b 100644 --- a/src/CounterDrone.Core/Simulation/PlatformEntity.cs +++ b/src/CounterDrone.Core/Simulation/PlatformEntity.cs @@ -44,6 +44,8 @@ namespace CounterDrone.Core.Simulation // 地基平台 public float MuzzleVelocity { get; } + public string? ModelId { get; } + /// Ready 包含:冷却就绪 + 有弹药 + 非飞行中 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; diff --git a/src/CounterDrone.Core/Simulation/SimTypes.cs b/src/CounterDrone.Core/Simulation/SimTypes.cs index e54ccf4..8480ed5 100644 --- a/src/CounterDrone.Core/Simulation/SimTypes.cs +++ b/src/CounterDrone.Core/Simulation/SimTypes.cs @@ -40,6 +40,8 @@ namespace CounterDrone.Core.Simulation public float VelX, VelY, VelZ; + public string? ModelId; + /// 仅 Flush 入库时使用,仿真期间保持 null public string? StateData; } diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index 0b54633..87d4833 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -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++) {