From 3bb6e7a091493a8b35f1761f6b69eeb006ecce8b Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Wed, 17 Jun 2026 12:16:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=A8=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E5=B1=9E=E6=80=A7=E6=9A=B4=E9=9C=B2=EF=BC=8C=E8=AE=A9=20Unity?= =?UTF-8?q?=20=E5=89=8D=E7=AB=AF=E5=8F=AF=E7=9B=B4=E6=8E=A5=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E6=89=80=E6=9C=89=E8=BF=90=E8=A1=8C=E6=97=B6=E6=95=B0?= =?UTF-8?q?=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 引擎层: - 新增 Platforms 列表 (SimulationEngine.Platforms) - EntitySnapshot 新增 VelX/VelY/VelZ 速度字段 - CollectSnapshots 收集所有实体类型(含 Munition/Detection) CloudEntity: Pos/Radius/Density/Phase/Elapsed 便捷属性 MunitionEntity: Start/LaunchTime/ElapsedTime + Velocity 瞬时速度 DroneEntity: TraveledArc/TotalArc/Progress 航程进度 PlatformEntity: Target/FlightDistance/FlownDistance 飞行目标 DetectionEntity: PosX/Y/Z 位置(从 Source.Position) --- .../Simulation/CloudEntity.cs | 8 +++++++ .../Simulation/DetectionEntity.cs | 3 +++ .../Simulation/DroneEntity.cs | 4 ++++ .../Simulation/MunitionEntity.cs | 20 ++++++++++++++++++ .../Simulation/PlatformEntity.cs | 6 ++++++ src/CounterDrone.Core/Simulation/SimTypes.cs | 2 ++ .../Simulation/SimulationEngine.cs | 21 +++++++++++++++---- 7 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/CounterDrone.Core/Simulation/CloudEntity.cs b/src/CounterDrone.Core/Simulation/CloudEntity.cs index e974466..2a8a7fe 100644 --- a/src/CounterDrone.Core/Simulation/CloudEntity.cs +++ b/src/CounterDrone.Core/Simulation/CloudEntity.cs @@ -12,6 +12,14 @@ namespace CounterDrone.Core.Simulation public float CreatedAt { get; } public bool IsDissipated => Dispersion.IsDissipated; + public float PosX => Dispersion.Center.X; + public float PosY => Dispersion.Center.Y; + public float PosZ => Dispersion.Center.Z; + public float Radius => Dispersion.Radius; + public float Density => Dispersion.CoreDensity; + public int Phase => Dispersion.Phase; + public float Elapsed => Dispersion.Elapsed; + public CloudEntity(string id, AerosolType aerosolType, ICloudDispersionModel dispersion, float createdAt) { Id = id; diff --git a/src/CounterDrone.Core/Simulation/DetectionEntity.cs b/src/CounterDrone.Core/Simulation/DetectionEntity.cs index 4255cea..1bd1152 100644 --- a/src/CounterDrone.Core/Simulation/DetectionEntity.cs +++ b/src/CounterDrone.Core/Simulation/DetectionEntity.cs @@ -12,6 +12,9 @@ namespace CounterDrone.Core.Simulation { public string Id { get; } public DetectionSource Source { get; } + public float PosX => Source.Position.X; + public float PosY => Source.Position.Y; + public float PosZ => Source.Position.Z; /// 每无人机 Id → 探测状态(true=Detected, false=Undetected) private readonly Dictionary _droneStates = new(); diff --git a/src/CounterDrone.Core/Simulation/DroneEntity.cs b/src/CounterDrone.Core/Simulation/DroneEntity.cs index c7c786d..f695068 100644 --- a/src/CounterDrone.Core/Simulation/DroneEntity.cs +++ b/src/CounterDrone.Core/Simulation/DroneEntity.cs @@ -24,6 +24,10 @@ namespace CounterDrone.Core.Simulation public float PrevX { get; private set; } public float PrevY { get; private set; } public float PrevZ { get; private set; } + + public float TraveledArc => _traveledArc; + public float TotalArc => _totalArc; + public float Progress => _totalArc > 0 ? _traveledArc / _totalArc : 0f; /// 沿航路已飞行弧长(米),由 RouteGeometry 驱动 private float _traveledArc; /// 航路总弧长(米),构造时一次性算好(航路静态,无需每帧重算) diff --git a/src/CounterDrone.Core/Simulation/MunitionEntity.cs b/src/CounterDrone.Core/Simulation/MunitionEntity.cs index e840621..d4b131c 100644 --- a/src/CounterDrone.Core/Simulation/MunitionEntity.cs +++ b/src/CounterDrone.Core/Simulation/MunitionEntity.cs @@ -24,6 +24,26 @@ namespace CounterDrone.Core.Simulation public float Azimuth { get; } public float MuzzleVelocity { get; } public float FlightDuration { get; private set; } + public float StartX => _startX; + public float StartY => _startY; + public float StartZ => _startZ; + public float LaunchTime => _launchTime; + public float ElapsedTime => _time; + + public (float Vx, float Vy, float Vz) Velocity + { + get + { + float cosA = (float)System.Math.Cos(LaunchAngle); + float sinA = (float)System.Math.Sin(LaunchAngle); + float sinAz = (float)System.Math.Sin(Azimuth); + float cosAz = (float)System.Math.Cos(Azimuth); + float vx = MuzzleVelocity * cosA * sinAz; + float vy = MuzzleVelocity * sinA - 9.81f * _time; + float vz = MuzzleVelocity * cosA * cosAz; + return (vx, vy, vz); + } + } private readonly float _startX, _startY, _startZ; private readonly float _launchTime; diff --git a/src/CounterDrone.Core/Simulation/PlatformEntity.cs b/src/CounterDrone.Core/Simulation/PlatformEntity.cs index 5c58521..f9e1b2c 100644 --- a/src/CounterDrone.Core/Simulation/PlatformEntity.cs +++ b/src/CounterDrone.Core/Simulation/PlatformEntity.cs @@ -34,6 +34,12 @@ namespace CounterDrone.Core.Simulation public float ExactReleaseTime => _exactReleaseTime; private float _exactReleaseTime; + public float TargetX => _targetX; + public float TargetY => _targetY; + public float TargetZ => _targetZ; + public float FlightDistance => _flightDistance; + public float FlownDistance => _flownDistance; + // 地基平台 public float MuzzleVelocity { get; } diff --git a/src/CounterDrone.Core/Simulation/SimTypes.cs b/src/CounterDrone.Core/Simulation/SimTypes.cs index e04a0dc..e54ccf4 100644 --- a/src/CounterDrone.Core/Simulation/SimTypes.cs +++ b/src/CounterDrone.Core/Simulation/SimTypes.cs @@ -38,6 +38,8 @@ namespace CounterDrone.Core.Simulation public int CloudPhase; public float CloudElapsed; + public float VelX, VelY, VelZ; + /// 仅 Flush 入库时使用,仿真期间保持 null public string? StateData; } diff --git a/src/CounterDrone.Core/Simulation/SimulationEngine.cs b/src/CounterDrone.Core/Simulation/SimulationEngine.cs index 6632e1c..d5efc47 100644 --- a/src/CounterDrone.Core/Simulation/SimulationEngine.cs +++ b/src/CounterDrone.Core/Simulation/SimulationEngine.cs @@ -26,6 +26,7 @@ namespace CounterDrone.Core.Simulation public IReadOnlyList Drones => _drones; public IReadOnlyList Clouds => _clouds; + public IReadOnlyList Platforms => _platforms; public IReadOnlyList Munitions => _munitions; public IReadOnlyList DetectionEntities => _detectionEntities; public IReadOnlyList Events => _allEvents; @@ -503,18 +504,30 @@ namespace CounterDrone.Core.Simulation for (int i = 0; i < _drones.Count; i++) { var d = _drones[i]; - _snapshotPool.Add(new EntitySnapshot { EntityId = d.Id, EntityType = Models.EntityType.Drone, PosX = d.PosX, PosY = d.PosY, PosZ = d.PosZ, DamageStage = (int)_damageModel.GetDamageStage(1 - d.Hp), Hp = d.Hp }); + 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 }); + } + for (int i = 0; i < _munitions.Count; i++) + { + var m = _munitions[i]; + var (vx, vy, vz) = m.Velocity; + _snapshotPool.Add(new EntitySnapshot { EntityId = m.Id, EntityType = Models.EntityType.Munition, PosX = m.PosX, PosY = m.PosY, PosZ = m.PosZ, VelX = vx, VelY = vy, VelZ = vz }); } for (int i = 0; i < _platforms.Count; i++) { var p = _platforms[i]; - if (p.PlatformType != Models.PlatformType.AirBased) continue; - _snapshotPool.Add(new EntitySnapshot { EntityId = p.Id, EntityType = Models.EntityType.Platform, PosX = p.PosX, PosY = p.PosY, PosZ = p.PosZ, PlatformStateStr = p.State.ToString() }); + 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() }); + } + 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 }); } for (int i = 0; i < _clouds.Count; i++) { var c = _clouds[i]; - _snapshotPool.Add(new EntitySnapshot { EntityId = c.Id, EntityType = Models.EntityType.Cloud, PosX = c.Dispersion.Center.X, PosY = c.Dispersion.Center.Y, PosZ = c.Dispersion.Center.Z, CloudRadius = c.Dispersion.Radius, CloudOpacity = c.Dispersion.Particles.Opacity, CloudPhase = c.Dispersion.Phase, CloudElapsed = c.Dispersion.Elapsed }); + _snapshotPool.Add(new EntitySnapshot { EntityId = c.Id, EntityType = Models.EntityType.Cloud, PosX = c.PosX, PosY = c.PosY, PosZ = c.PosZ, CloudRadius = c.Radius, CloudOpacity = c.Dispersion.Particles.Opacity, CloudPhase = c.Phase, CloudElapsed = c.Elapsed }); } return _snapshotPool; }