CounterDroneBackend/docs/design/architecture/总体架构设计.md

1512 lines
62 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 反无人机仿真系统 — 总体架构设计
> **版本**V8
> **日期**2026-06-12
> **状态**:已实现
> **Unity 版本**22.3.62
> **.NET 版本**.NET Standard 2.1
> **变更**:事件驱动替代 EventQueueFireSchedule 统一发射接口;三阶段扩散模型;默认弹药 JSON 配置Phase/Elapsed 属性
---
## 一、系统概述
本系统对新型气溶胶武器的三种防空毁伤机制(吸入式灭火、爆燃式、吸入式爆炸)进行数字化仿真。通过参数化配置与可视化推演,量化评估新型气溶胶武器对不同类型空中威胁源目标(动力系统)的毁伤效能。
系统分为三大模块:
| 模块 | 核心功能 |
|------|----------|
| **模型管理** | 3D 模型导入/预览/删除,编组管理 |
| **想定管理** | 仿真任务 CRUD步骤化配置向导管控区域设置搜索分页 |
| **仿真报告** | 报告列表,含时序图的完整报告预览,导出 PDF/Word删除 |
### 要求来源对照
本设计融合两份需求文档:
| 文档 | 侧重 |
|------|------|
| V1.0 反无人机仿真系统功能需求 | UI 交互、业务流程、业务字段 |
| 技术要求终版 | 毁伤机制、装备体系、可视化效果、性能指标、第三方算法集成 |
---
## 二、架构分层
```
┌──────────────────────────────────────────────────────────┐
│ Unity UI Layer │
│ 模型管理 │ 想定管理(含管控区域) │ 仿真运行&回放 │ 仿真报告 │
├──────────────────────────────────────────────────────────┤
│ Unity Application Layer │
│ ModelPanel | ScenarioWizard | SimulationRunner | │
│ ReplayController | ReportPanel | GroupManager │
├──────────────────────────────────────────────────────────┤
│ Service Layer (Pure C#) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ ModelService │ │ScenarioService│ │ SimulationEngine │ │
│ │ GroupService │ │ DefenseAdvisor│ │ ├ DroneEntity │ │
│ └──────────────┘ └──────────────┘ │ ├ PlatformEntity │ │
│ ┌──────────────┐ ┌──────────────┐ │ ├ MunitionEntity │ │
│ │FrameDataStore│ │ReportService │ │ ├ CloudEntity │ │
│ │ │ │ ├ ReportGen │ │ │ └ GaussianPuff│ │
│ └──────────────┘ │ └ Markdown │ │ ├ ControlZone │ │
│ └──────────────┘ │ ├ IDamageModel×3 │ │
│ │ └ FireSchedule │ │
│ ┌──────────────────────────────────────────────────────┐│
│ │ Algorithm Layer (自主实现) ││
│ │ GaussianPuffDispersion | DamageCalculator ││
│ │ DefaultDefenseAdvisor | Kinematics(PG稳定度) ││
│ └──────────────────────────────────────────────────────┘│
├──────────────────────────────────────────────────────────┤
│ Data Layer │
│ ┌────────────────────────────┐ ┌────────────────────┐ │
│ │ main.db (SQLite) │ │ frames/ (SQLite) │ │
│ │ 11张业务表 + SimEvent │ │ 每任务一个 .db │ │
│ │ + SimulationReport │ │ SimFrameRecord │ │
│ │ < 100MB永久保留 │ │ 6个月 TTL │ │
│ └────────────────────────────┘ └────────────────────┘ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ FileSystem │ │
│ │ 模型文件(.fbx/.obj/.stl/.glb/.gltf) + 预览图 │ │
│ └────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
### 各层职责
| 层 | 依赖 | 职责 |
|----|------|------|
| **Data Layer** | 主库 SQLite + 任务分库 SQLite + 文件系统 | 主库存元数据/事件/报告(<100MB永久保留分库按任务存帧数据6月TTL文件系统存模型文件 |
| **Algorithm Layer** | C#零外部依赖 | 气溶胶扩散模型毁伤计算防御推荐算法全部自主实现 |
| **Service Layer** | Data Layer + Algorithm Layer | 纯业务逻辑仿真引擎录制报告生成 |
| **Application Layer** | Service Layer + Unity | MonoBehaviour 桥接生命周期协调驱动仿真 |
| **UI Layer** | Application Layer | UGUI 页面弹窗3D 预览回放粒子参数传递 |
### 2.1 程序集拆分Core 独立于 Unity
后端代码拆分为两个程序集确保 Core 可脱离 Unity 独立编译和测试
```
CounterDrone.Core.dll ← .NET Standard 2.1 类库
零 UnityEngine 引用
可在任何 .NET 环境运行
├── /Models 数据模型POCO
├── /Repository 数据访问SQLite + 文件存储)
├── /Services 业务服务ModelService, ScenarioService 等)
├── /Simulation 仿真引擎 + 实体SimulationEngine, DroneEntity, ...
└── /Algorithms 扩散模型、毁伤模型、防御推荐
CounterDrone.Core.Tests.dll ← xUnit 测试项目
直接引用 Core.dll
dotnet test 即可运行
├── /Unit 单元测试(每个类独立测)
└── /Integration 集成测试(完整仿真流程)
Unity 项目/Assets/Scripts/ ← Unity 侧
├── /Managers MonoBehaviours 桥接层(薄)
└── /UI UGUI 绑定
引用 → CounterDrone.Core.dll放在 Assets/Plugins/
```
### 2.2 Unity 依赖隔离:关键设计
| 隔离点 | 做法 |
|------|------|
| **时间** | `engine.Tick(float deltaTime)` Unity `Time.deltaTime`测试传固定值 `0.05f` |
| **文件路径** | Core 使用接口 `IPathProvider` Unity 实现返回 `Application.persistentDataPath`测试返回 `./testdata/` |
| **日志** | Core 使用 `Microsoft.Extensions.Logging` 抽象 Unity 桥接到 `Debug.Log`测试用控制台 |
| **模型加载** | Core 不涉及 3D 渲染只管理文件路径和元数据 |
| **粒子参数** | Core 输出 `ParticleParams` 数据对象 Unity 读值设置 ParticleSystem |
### 2.3 Manager 桥接层示例(极薄)
```csharp
// Unity 侧 SimulationRunner.cs — 仅负责桥接
public class SimulationRunner : MonoBehaviour
{
private ISimulationEngine _engine;
private IRecordService _recorder;
void Start()
{
// 通过 DI 或工厂获取实例Core 创建)
_engine = SimulationEngineFactory.Create(taskId);
_recorder = ServiceFactory.CreateRecordService();
}
void Update()
{
if (_engine.State != SimulationState.Running) return;
// 核心只有这一行:把 Unity 时间传入纯 C# 引擎
var result = _engine.Tick(Time.deltaTime);
// 更新 Unity 侧的 3D 物体位置(根据 result 中的实体快照)
UpdateVisuals(result.EntitySnapshots);
}
void UpdateVisuals(List<EntitySnapshot> snapshots)
{
foreach (var s in snapshots)
{
// 找到对应 GameObject设置 transform
_entityMap[s.EntityId].transform.position = s.Position;
}
}
}
```
### 2.4 测试策略
| 测试类型 | 工具 | 内容 |
|------|------|------|
| **单元测试** | xUnit + Moq | Repository 增删改查Service 业务逻辑Algorithm 计算正确性 |
| **仿真确定性测试** | xUnit | 固定输入 + 固定 deltaTime 断言帧 N 的实体位置 = 预期值 |
| **集成测试** | xUnit + SQLite 文件 | 完整想定配置 启动仿真 1000 断言事件序列和对抗结果 |
| **性能测试** | BenchmarkDotNet | Tick() 单帧耗时 P99 < 5ms |
> Core 测试无需 Unity`dotnet test` 即可运行全部测试,适合 CI 流水线。
---
## 三、枚举定义
```csharp
// === 任务 ===
enum TaskStatus { Draft = 0, Configuring = 1, Completed = 2 }
// === 场景 ===
enum SceneType { Urban = 0, Plain = 1, Mountain = 2, Coast = 3 }
enum WeatherType { Sunny = 0, Overcast = 1, Fog = 2, Rain = 3, Night = 4 }
enum WindDirection { N = 0, NE = 1, E = 2, SE = 3, S = 4, SW = 5, W = 6, NW = 7 }
// === 目标 ===
enum TargetType { Rotor = 0, FixedWing = 1, Electric = 2, Piston = 3, HighSpeed = 4 }
enum PowerType { Electric = 0, Piston = 1, Jet = 2 }
// === 装备 & 搭载平台 ===
enum PlatformType { AirBased = 0, GroundBased = 1 } // 空基(大型无人机) / 地基(炮弹)
enum EquipmentRole { Detection = 0, LaunchPlatform = 1 } // 装备角色:探测 / 发射平台
// === 气溶胶 & 毁伤 ===
enum AerosolType { InertGas = 0, ActiveMaterial = 1, ActiveFuel = 2 }
// 对应的毁伤机制名称:吸入式灭火 / 爆燃式 / 吸入式爆炸
enum ReleaseMode { Single = 0, Continuous = 1, Pulse = 2 }
enum TriggerMode { Time = 0, Area = 1, Manual = 2 }
// === 毁伤状态阶段(输出到 StateData 供 Unity 渲染)===
enum DamageStage { Normal = 0, EngineAnomaly = 1, AttitudeLoss = 2, Destroyed = 3 }
// === 编队 & 编组 ===
enum FormationMode { Single = 0, Formation = 1, Swarm = 2 }
enum GroupType { DroneFleet = 0, EquipmentGroup = 1 }
// === 运行时 ===
enum EntityType { Drone = 0, Platform = 1, DetectionEquip = 2, Cloud = 3, Munition = 4 }
enum EventType
{
TargetDetected = 0,
MunitionLaunched = 1,
CloudGenerated = 2,
DroneEnteredCloud = 3,
DroneDestroyed = 4,
DroneReachedTarget = 5,
ZoneIntruded = 6, // 无人机侵入管控区域
WaypointReached = 7,
SimulationEnd = 8
}
// === 报告 ===
enum InterceptResult { Success = 0, Partial = 1, Failed = 2 }
enum PositionMode { PointSelect = 0, ManualInput = 1 }
```
---
## 四、数据模型设计
### 4.1 存储架构:主库 + 任务分库
```
CounterDroneBackend_Data/
├── main.db ← 主库(< 100MB永久保留
│ ├── 11 张业务配置表
│ ├── SimEvent ← 事件表(~30 条/任务)
│ └── SimulationReport
├── frames/ ← 帧数据分库6 个月 TTL
│ ├── {taskId_001}.db ← 单任务 ~161 MB30min 仿真)
│ └── {taskId_002}.db
└── models/ ← 模型文件 + 预览图
```
### 4.2 数据表总览
11 张业务表主库 + 1 张运行时表主库 + 1 张运行时表任务分库
```
主库main.db— 永久保留:
ModelInfo — 模型元数据
AmmunitionSpec — 弹药基础参数第三方数据NEW
SimTask — 仿真任务主表
CombatScene — 步骤1作战场景含24h时间、天气
ControlZone — 步骤1+:管控区域/电子围栏NEW
TargetConfig — 步骤2目标配置
EquipmentDeployment — 步骤3装备部署搭载平台+探测设备)
CloudDispersal — 步骤4云团抛撒配置
RoutePlan — 步骤5航路规划1:N SimTask多编队
Waypoint — 航路点
Group — 编组(独立管理)
SimulationReport — 仿真报告
SimEvent — 仿真事件(时序图数据源)
任务分库frames/{taskId}.db— 6 个月 TTL
SimFrameRecord — 逐帧位置记录(回放用)
```
### 4.3 业务表详细设计
#### ModelInfo — 模型元数据
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| Name | TEXT | NOT NULL | 模型名称 |
| ModelType | TEXT | | 分类标签 |
| FilePath | TEXT | | persistentDataPath 下的相对路径 |
| FileSize | REAL | | MB |
| PreviewPath | TEXT | | 预览图路径 |
| HasHighResTexture | INTEGER | DEFAULT 0 | 是否含 2K+ 贴图 |
| CreatedAt | TEXT | | 导入时间 ISO8601 |
> 支持格式:**.fbx / .obj / .stl / .glb / .gltf**,单文件 ≤ 500MB支持 2K 及以上分辨率贴图。
#### SimTask — 仿真任务主表
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| Name | TEXT | NOT NULL | 任务名称 |
| TaskNumber | TEXT | UNIQUE | SIM-yyyyMMdd-xxx |
| Status | INTEGER | DEFAULT 0 | 0=草稿 1=配置中 2=已完成 |
| CurrentStep | INTEGER | DEFAULT 1 | 当前配置步骤 1-5 |
| TickRate | INTEGER | DEFAULT 20 | 仿真 Tick 频率Hz |
| CreatedAt | TEXT | | |
| UpdatedAt | TEXT | | |
#### CombatScene — 步骤1作战场景
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| TaskId | TEXT | PK, FK | 1:1 SimTask |
| SceneType | INTEGER | | 0城市 1平原 2山区 3海岸 |
| TimeOfDay | TEXT | DEFAULT "12:00" | **NEW** 24h 制时间 "14:30" |
| WeatherType | INTEGER | | 0晴 1阴 2雾 3雨 4夜 |
| WindSpeed | REAL | DEFAULT 5 | m/s范围 0-30 |
| WindDirection | INTEGER | DEFAULT 0 | 八方位 0-7 |
| Temperature | REAL | DEFAULT 20 | |
| Humidity | REAL | DEFAULT 60 | %RH |
| Pressure | REAL | DEFAULT 1013 | hPa |
| Visibility | REAL | DEFAULT 5000 | m范围 100-10000 |
| SceneWidth | REAL | DEFAULT 4000 | **NEW** 场景宽 m(≥4m |
| SceneLength | REAL | DEFAULT 10000 | **NEW** 场景纵深 m(≥100m |
| SceneHeight | REAL | DEFAULT 1000 | **NEW** 场景高 m(≥10m |
> 场景空间范围最低要求4m × 100m × 10m。默认值 4000m × 10000m × 1000m 可配置。
#### ControlZone — 步骤1扩展管控区域 / 电子围栏NEW
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| TaskId | TEXT | FK | |
| Name | TEXT | | 区域名称 |
| VerticesJson | TEXT | NOT NULL | 多边形顶点 JSON`[{"x":0,"y":0,"z":0},...]` |
| MinAltitude | REAL | | 区域底高 m |
| MaxAltitude | REAL | | 区域顶高 m |
| OrderIndex | INTEGER | | 多个区域的顺序 |
> 管控区域在场景设置(地形+天气)之后配置。无人机进入管控区域 → 触发 ZoneIntruded 事件 → 该无人机任务失败。
#### TargetConfig — 步骤2目标配置
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| TaskId | TEXT | FK | |
| GroupId | TEXT | FK | 关联无人机编队 Group |
| TargetType | INTEGER | | 0旋翼 1固定翼 2电推 3活塞 4高速 |
| Quantity | INTEGER | DEFAULT 1 | 目标数量 |
| PowerType | INTEGER | | 0电推 1活塞 2喷吸气 |
| Wingspan | REAL | | m |
| TypicalSpeed | REAL | | km/h |
| TypicalAltitude | REAL | | m |
> 目标类型默认值:
| 目标类型 | 翼展(m) | 典型速度(km/h) | 典型飞行高度(m) |
|----------|---------|---------------|----------------|
| 旋翼 | 1.2 | 60 | 300 |
| 固定翼 | 3.5 | 150 | 1000 |
| 电推 | 1.8 | 100 | 500 |
| 活塞 | 2.5 | 120 | 800 |
| 高速目标 | 1.5 | 300 | 2000 |
#### EquipmentDeployment — 步骤3装备部署重构
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| TaskId | TEXT | FK | |
| EquipmentRole | INTEGER | | 0=探测设备 1=发射平台 |
| Quantity | INTEGER | DEFAULT 1 | 部署数量 |
| GroupId | TEXT | FK | 关联装备编组 Group火力单元多批次时用于分配 |
| // 以下为发射平台专用字段 |
| PlatformType | INTEGER | NULLABLE | 0=空基(大型无人机) 1=地基(炮弹),探测设备为 NULL |
| PositionX | REAL | | 部署位置 |
| PositionY | REAL | | |
| PositionZ | REAL | | |
| AerosolType | INTEGER | NULLABLE | 挂载气溶胶类型探测设备为 NULL |
| MunitionCount | INTEGER | NULLABLE | 挂载弹药数量 |
| MuzzleVelocity | REAL | NULLABLE | **NEW** 弹药初速 m/s地基炮弹用 |
| ReleaseAltitude | REAL | NULLABLE | **NEW** 弹药释放高度 m空基平台用 |
| Cooldown | REAL | DEFAULT 5 | 发射冷却时间 s同弹种连发间隔 |
| AmmoChangeTime | REAL | DEFAULT 300 | **NEW** 更换弹种所需时间 s默认 5 分钟 |
| // 以下为探测设备专用字段 |
| DetectionRadius | REAL | NULLABLE | 探测半径 m |
> **装备体系说明**
> - **搭载平台**2 种):
> - 空基(大型无人机):飞到释放点投放弹药 → 弹药自由落体/滑翔至云团生成点
> - 地基(炮弹):地面发射 → 抛物线弹道 → 到达释放点生成云团
> - **探测设备**:目标搜索发现与跟踪,输出目标坐标给发射平台
> - 弹药类型决定生成云团的 AerosolType 和覆盖体积
#### CloudDispersal — 步骤4云团抛撒配置
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| TaskId | TEXT | PK, FK | 1:1 SimTask |
| AerosolType | INTEGER | | 0吸入式灭火 1爆燃式 2吸入式爆炸 |
| DisperseHeight | REAL | DEFAULT 300 | m |
| TriggerMode | INTEGER | | 0时间 1区域 2手动 |
| SpreadAngle | REAL | DEFAULT 0 | |
| ReleaseMode | INTEGER | | 0单次 1连续 2脉冲 |
| InitialScale | REAL | DEFAULT 1000 | m³ |
| Duration | REAL | DEFAULT 60 | s |
| ReleaseInterval | REAL | DEFAULT 5 | s |
| TotalAmount | REAL | DEFAULT 50 | kg |
| PositionX | REAL | | 抛撒坐标 |
| PositionY | REAL | | |
| PositionZ | REAL | | |
| PositionMode | INTEGER | | 0三维点选 1手动输入 2算法推荐NEW |
| // 算法推荐结果NEW |
| RecommendedPosX | REAL | NULLABLE | 算法推荐最佳抛撒位置 |
| RecommendedPosY | REAL | NULLABLE | |
| RecommendedPosZ | REAL | NULLABLE | |
| RecommendedTiming | REAL | NULLABLE | 算法推荐最佳触发时机仿真秒 |
| CriticalPosX | REAL | NULLABLE | 最危险值抛撒位置 |
| CriticalPosY | REAL | NULLABLE | |
| CriticalPosZ | REAL | NULLABLE | |
| CriticalTiming | REAL | NULLABLE | 最危险值触发时机 |
#### RoutePlan — 步骤5航路规划
> **支持多批次**:通过 `TaskId + GroupId` 唯一标识一条航路,一个任务可有多个编队各自独立航路。
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| TaskId | TEXT | PK(复合) | |
| GroupId | TEXT | PK(复合), FK Group | 关联编队同一任务不同编队可有独立航路 |
| FormationMode | INTEGER | | 0单机 1编队 2蜂群 |
| FormationSpacing | REAL | DEFAULT 50 | m |
| ETA | TEXT | | 预计到达时间 |
#### Waypoint — 航路点
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| TaskId | TEXT | FK | |
| OrderIndex | INTEGER | NOT NULL | 航路顺序 |
| PosX | REAL | | 坐标支持三维点选 |
| PosY | REAL | | |
| PosZ | REAL | | |
| Altitude | REAL | | 该航点飞行高度 m |
| Speed | REAL | | 该段速度 km/h |
#### Group — 编组
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| Name | TEXT | NOT NULL | 编组名称 |
| GroupType | INTEGER | | 0=无人机编队 1=装备编组 |
| Description | TEXT | | 备注 |
| CreatedAt | TEXT | | |
### 4.4 运行时表
> **注意**SimEvent 和 SimulationReport 存储在主库 main.dbSimFrameRecord 存储在各任务的独立分库 frames/{taskId}.db 中。
#### SimFrameRecord — 逐帧记录
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | INTEGER | PK AUTOINCREMENT | |
| TaskId | TEXT | FK | |
| FrameIndex | INTEGER | | 帧序号 |
| Timestamp | REAL | | 仿真时间 |
| EntityId | TEXT | | |
| EntityType | INTEGER | | 实体类型枚举 |
| PosX | REAL | | |
| PosY | REAL | | |
| PosZ | REAL | | |
| RotX | REAL | | |
| RotY | REAL | | |
| RotZ | REAL | | |
| StateData | TEXT | | JSON包含DestroyStageCloudRadiusCloudColor |
> StateData JSON 结构(供 Unity 粒子系统 & 毁伤渲染):
> ```json
> {
> "damageStage": 0, // DamageStage 枚举
> "hp": 0.75, // 剩余血量 0~1
> "cloudRadius": 150.0, // 云团当前半径 mCloudEntity
> "cloudOpacity": 0.8, // 云团透明度CloudEntity
> "cloudColor": "#AABBCC", // 云团颜色CloudEntity
> "particleEmitRate": 500 // 粒子发射率CloudEntity
> }
> ```
#### SimEvent — 仿真事件(时序图数据源)
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| TaskId | TEXT | FK | |
| OccurredAt | REAL | | 仿真时间 |
| EventType | INTEGER | | 事件类型枚举 |
| SourceId | TEXT | | 源实体 ID |
| TargetId | TEXT | | 目标实体 ID |
| DataJson | TEXT | | 事件携带的结构化数据 |
| Description | TEXT | | 事件描述 |
---
## 五、仿真引擎设计
### 5.1 核心实体关系
```
SimulationEngine
├── SimulationState ← 状态(运行/暂停/结束)
├── SceneConfig ← 配置快照(含场景边界、管控区域)
├── List<DroneEntity> ← 无人机(目标方)
│ └── 按编组组织,共享航路
├── List<PlatformEntity> ← 搭载平台(发射方)★重构
│ ├── AirBasedPlatform ← 空基(大型无人机)
│ └── GroundBasedPlatform ← 地基(火炮)
├── List<DetectionEntity> ← 探测设备
├── List<MunitionEntity> ← 飞行中的弹药
│ ├── 空基投放:短程自由落体/滑翔
│ └── 地基发射:抛物线弹道
├── List<CloudEntity> ← 气溶胶云团 ★核心毁伤载体★
│ └── GaussianPuffDispersion三阶段扩散
├── List<ControlZone> ← 管控区域(电子围栏)
├── FireSchedule ← 发射计划(推荐算法生成)
└── FrameDataStore ← 帧数据写入(任务分库)
```
### 5.2 拦截链路(完整流程)
```
探测设备扫描
│ 发现目标 → 输出目标坐标
火控分配(分配给可用搭载平台)
├── 空基平台:飞至投放点
│ │
│ ▼
│ 投放弹药(自由落体/滑翔至云团生成点)
└── 地基平台:计算射击诸元
发射炮弹(抛物线弹道飞向目标区域)
弹药到达释放点 → 生成 CloudEntity
MunitionEntity 销毁
云团扩散膨胀(三阶段模型:爆轰→湍流→高斯)
│ 持续膨胀 + 消散计时
无人机进入云团范围
│ 施加毁伤IDamageModel 接口,三种机制自主实现)
│ 吸入式灭火 / 爆燃式 / 吸入式爆炸
无人机被摧毁 / 存活
│ 毁伤阶段状态输出到 StateData
Unity 渲染毁伤效果(尾焰异常、姿态失控、坠落)
```
### 5.3 仿真 Tick 流程
```
1. 【发射阶段】
按 FireSchedule 执行:
├─ SimulationTime ≥ FireTime → 平台发射弹药
└─ 触发 OnMunitionLaunched 事件
2. 【弹药飞行 → 云团生成】
FOR EACH MunitionEntity
├─ 抛物线弹道 / 自由落体
└─ 到达释放高度 → 生成 CloudEntity → 触发 OnCloudGenerated
3. 【云团演化】
FOR EACH CloudEntity
├─ GaussianPuffDispersion.Tick():三阶段扩散
├─ 更新粒子参数(半径、透明度 → 写入 StateData
└─ 消散条件满足 → 移除
4. 【毁伤判定】
FOR EACH DroneEntity × CloudEntity
├─ 无人机坐标 ∈ 云团有效范围?
├─ 是 → IDamageModel.CalculateDamage()
├─ drone.HP -= damage
└─ HP ≤ 0 → 触发 OnDroneDestroyed
5. 【无人机移动】
FOR EACH 存活 DroneEntity
├─ 沿航路点线性插值
├─ 风偏影响
└─ 到达终点 → 触发 OnDroneReachedTarget
6. 【平台冷却】
FOR EACH PlatformEntityCooldown -= dt
7. 【管控区域判定】
FOR EACH 存活 DroneEntity
├─ Point-in-Polygon 判定
└─ 侵入 → 触发 OnZoneIntruded
8. 【结束判定】
所有无人机 Status ≠ Flying → 触发 OnSimulationEnded
9. 【结束判定】
├─ 所有无人机 (被摧毁 OR 到达目标 OR 侵入管控区) → SimulationEnd
├─ 停止录制
└─ 更新 SimulationState
```
### 5.4 实体行为模型
#### DroneEntity无人机
```
属性:
- 编组 GroupId、航路点队列 Waypoint[]
- 当前位置、速度、朝向
- HP0~1 归一化)
- DamageStageNormal → EngineAnomaly → AttitudeLoss → Destroyed
- 目标类型 TargetType、动力类型 PowerType
- 存活状态(飞行中/抵达目标/侵入管控区/被摧毁)
运动模型(简化运动学):
- 两航路点之间线性插值
- 实际位移 = 航向位移 + 风速矢量 × deltaTime
- 到达判定:||currentPos - waypointPos|| < 1m
结束条件(任一触发即该无人机结束):
- 被毁伤HP ≤ 0→ Destroyed
- 到达攻击目标 → ReachedTarget
- 侵入管控区域 → ZoneIntruded
```
#### PlatformEntity搭载平台★重构
```
空基平台AirBasedPlatform
- 位置(动态,飞向投放点)
- 挂载弹药类型 AerosolType、数量 MunitionCount
- 释放高度 ReleaseAltitude
- 冷却计时器
- 行为:接收目标坐标 → 计算拦截航路 → 飞至投放点 → 投放弹药
地基平台GroundBasedPlatform
- 固定位置
- 弹药初速 MuzzleVelocity
- 挂载弹药类型 AerosolType、数量 MunitionCount
- 冷却计时器
- 行为:接收目标坐标 → 计算射击诸元 → 发射炮弹
```
#### MunitionEntity飞行中弹药★重构
```
属性:
- 弹药类型 AerosolType
- 发射方式 LaunchModeAirDrop / GroundArtillery
- 当前位置、速度
- 目标坐标(云团生成点)
行为(两种弹道):
- AirDrop空基投放
初始位置 = 投放点,初始速度 = 平台速度
运动 = 自由落体 + 水平惯性(简化)
到达条件 = 当前位置.Z ≤ 云团生成高度
- GroundArtillery地基炮弹
初始位置 = 发射点,初始速度 = MuzzleVelocity
运动 = 抛物线弹道
x(t) = x0 + v0*cos(θ)*cos(φ)*t
y(t) = y0 + v0*cos(θ)*sin(φ)*t
z(t) = z0 + v0*sin(θ)*t - 0.5*g*t²
到达条件 = z(t) ≤ 云团生成高度
```
#### CloudEntity气溶胶云团
```
属性:
- 气溶胶类型 AerosolType
- 中心坐标
- 当前半径(调用第三方 DLL 扩散模型计算)
- 最大半径
- 持续时间、剩余时间
- 粒子系统参数(半径、透明度、颜色 → 输出到 StateData
行为(委托第三方 DLL
- 扩散膨胀GaussianPuffDispersion.Tick()(三阶段)
- 消散计时
- 毁伤判定IDamageModel.CalculateDamage()(三种机制自主实现)
```
---
## 六、算法设计 — 接口驱动 & 可替换架构 ★关键
### 设计原则
所有算法组件通过**接口隔离**SimulationEngine 只依赖接口不感知具体实现每个算法组件可独立替换为第三方实现无需修改引擎代码
```
SimulationEngine
┌─────┼─────┐
▼ ▼ ▼
ICloudDispersionModel ← 扩散模型接口
IDamageModel ← 毁伤模型接口
IDefenseAdvisor ← 防御推荐接口
┌───────┼───────┐
▼ ▼ ▼
自主实现 第三方实现 混合(部分自研+部分外购)
(Default) (Future) (Future)
```
### 6.1 算法工厂与注册
```csharp
/// <summary>算法工厂 — 统一管理所有算法组件的创建与替换</summary>
public static class AlgorithmFactory
{
// 注册表:每个接口 → 实现类型
private static readonly Dictionary<Type, Type> _registry = new()
{
{ typeof(ICloudDispersionModel), typeof(GaussianPuffDispersion) },
{ typeof(IDamageModel), typeof(DamageModelRouter) },
{ typeof(IDefenseAdvisor), typeof(DefaultDefenseAdvisor) },
};
/// <summary>替换某个算法实现(第三方接入点)</summary>
public static void Register<TInterface, TImpl>() where TImpl : TInterface
{
_registry[typeof(TInterface)] = typeof(TImpl);
}
/// <summary>创建实例SimulationEngine 统一调用此方法</summary>
public static T Create<T>(params object[] args)
{
var implType = _registry[typeof(T)];
return (T)Activator.CreateInstance(implType, args);
}
}
```
> **替换示例**:将来第三方提供 `ThirdPartyDispersion.dll`,只需一行:
> `AlgorithmFactory.Register<ICloudDispersionModel, ThirdPartyDispersion>();`
> 无需改动 SimulationEngine 任何代码。
### 6.2 第三方提供的数据
```csharp
/// <summary>第三方提供的弹药基础参数(数据配置,非运行时 DLL</summary>
public class AmmunitionSpec
{
public AerosolType AerosolType; // 气溶胶类型
public string Name; // 弹药名称
// 初始扩散状态
public float InitialRadius; // 初始云团半径m
public float InitialVolume; // 初始云团体积
public float CoreDensity; // 核心密度kg/m³
public float EdgeDensity; // 边缘密度kg/m³
public float InitialTemperature; // 初始温度K
public float BuoyancyFactor; // 浮力系数
// 弹药基础参数
public float EffectiveConcentration; // 有效毁伤浓度阈值kg/m³
public float DispersionRateBase; // 基础扩散速率m/s
public float MaxRadius; // 最大有效半径m
public float MaxDuration; // 最大持续时间s
public ParticleRenderParams Particles; // 粒子渲染参数
}
```
> 第三方以 JSON 配置文件形式交付 `AmmunitionSpec` 数组,系统启动时加载到 SQLite `AmmunitionSpec` 表。
### 6.2.1 系统内置默认值(第三方提供前使用)
基于 155mm 炮弹载荷的物理合理估计
| 参数 | 惰性气体弹 | 活性材料弹 | 活性燃料弹 |
|------|------|------|------|
| 药剂质量 (SourceStrength) | 10 kg | 12 kg | 10 kg |
| 爆发药 TNT 当量 (BurstChargeKg) | 1.5 kg | 4.0 kg | 1.5 kg |
| 有效浓度阈值 (EffectiveConcentration) | 0.0001 kg/m³ | 0.0002 kg/m³ | 0.0001 kg/m³ |
| 湍流扩散系数 (TurbulentExpansionK) | 3.0 | 4.0 | 3.0 |
| 最大半径 (MaxRadius) | 100 m | 80 m | 90 m |
| 最大持续时间 (MaxDuration) | 120 s | 90 s | 100 s |
| Phase 1 初始半径 (R₀) | 3.75 m | 5.14 m | 3.75 m |
> **数据来源**10kg烟幕剂抛射药/烟幕剂质量比 5%-20%TNT当量取 1.5kg(典型值)。活性材料弹取爆炸分散型上限 4kg。
### 6.3 扩散模型设计 — 高斯烟团模型Gaussian PuffV2
#### 6.3.1 模型选择
采用**高斯烟团扩散模型**使用**Pasquill-Gifford 稳定度分类**计算扩散系数 σ
#### 6.3.2 大气稳定度映射
从天气类型和风速推导稳定度等级无需额外参数
| 天气 | 风速 | 稳定度 | 太阳辐射 | 湍流 |
|------|------|------|------|------|
| 晴天 | 5 m/s | A极不稳定 | | |
| 晴天 | > 5 m/s | B不稳定 | 中 | 中 |
| 阴天 | 任意 | D中性 | 弱 | 中 |
| 雨天 | 任意 | D中性 | 弱 | 中 |
| 雾天 | 任意 | E稳定 | 无 | 弱 |
| 夜间 | 任意 | F极稳定 | 无 | 最弱 |
#### 6.3.3 σ 扩散系数Pasquill-Gifford
扩散距离 x 米后,水平扩散系数 σ_y、垂直扩散系数 σ_z单位 m
| 稳定度 | σ_y | σ_z |
|------|------|------|
| A | 0.22x / (1+0.0001x)^0.5 | 0.20x |
| B | 0.16x / (1+0.0001x)^0.5 | 0.12x |
| C | 0.11x / (1+0.0001x)^0.5 | 0.08x / (1+0.0002x)^0.5 |
| D | 0.08x / (1+0.0001x)^0.5 | 0.06x / (1+0.0015x)^0.5 |
| E | 0.06x / (1+0.0001x)^0.5 | 0.03x / (1+0.0003x)^0.5 |
| F | 0.04x / (1+0.0001x)^0.5 | 0.016x / (1+0.0003x)^0.5 |
> 对于瞬时释放的烟团Puff扩散距离 x 取云团中心随风漂移的距离x = u × t其中 u 为风速t 为经过时间。若风速为 0取 x ≈ 1m纯湍流扩散
#### 6.3.4 浓度场公式
云团内任意点 (x, y, z) 在时刻 t 的浓度:
```
C(x, y, z, t) = ────────────── × exp[ -½( (x-ut)/σy )² ]
(2π)^(3/2) σy σy σz
× exp[ -½( y/σy )² ]
× { exp[ -½( (z-H)/σz )² ] + exp[ -½( (z+H)/σz )² ] }
其中:
Q = 源强释放物质总量kg来自 AmmunitionSpec
u = 风速m/s
H = 有效释放高度m
σy, σz = 扩散系数(由 6.3.2 和 6.3.3 确定)
```
#### 6.3.5 可判定指标
| 指标 | 计算 | 说明 |
|------|------|------|
| 中心浓度 | C_max = Q / [(2π)^(3/2) σσz] | 云团最浓处 |
| 有效半径 | R_eff = min{ r | C(中心, r) < C_threshold } | 浓度超过阈值的范围 |
| 消散条件 | C_max < C_threshold / 10 经过时间 > MaxDuration | 浓度可忽略 |
> **简化**:实时判定时,无人机位于云团内当且仅当 C(无人机坐标) ≥ EffectiveConcentration。不需要球体假设直接用高斯公式计算。
#### 6.3.6 AmmunitionSpec 调整
| 字段 | 变更 | 说明 |
|------|------|------|
| `DispersionRateBase` | ❌ 删除 | 由 PG 稳定度代替 |
| `InitialRadius` | 保留 | 仍作初始 σ 参考 |
| `SourceStrength` | ✅ 新增 | 源强 Qkg取代线性模型 |
> 浓度 C 的单位为 kg/m³无人机是否受损取决于 C ≥ EffectiveConcentration。
#### 6.3.7 接口(不变)
```csharp
public interface ICloudDispersionModel
{
void Initialize(AmmunitionSpec ammo, CombatScene env, Vector3 releasePos, float releaseTime);
void Tick(float deltaTime, float windSpeed, WindDirection windDir);
Vector3 Center { get; }
float Radius { get; }
float CoreDensity { get; }
float EffectiveRadius { get; }
ParticleParams Particles { get; }
bool IsDissipated { get; }
}
```
### 6.4 毁伤模型设计
三种气溶胶对应三种毁伤机制,我们自主实现:
#### 6.4.1 共同接口
```csharp
public interface IDamageModel
{
/// <summary>每 Tick 计算毁伤值</summary>
/// <param name="droneType">目标类型</param>
/// <param name="powerType">动力类型(影响毁伤效率)</param>
/// <param name="aerosolType">气溶胶类型</param>
/// <param name="cloudDensity">当前位置云团密度kg/m³</param>
/// <param name="exposureTime">累计暴露时间s</param>
/// <param name="deltaTime">本次 Tick 时长</param>
/// <returns>本次毁伤值0~1 归一化)</returns>
float CalculateDamage(TargetType droneType, PowerType powerType,
AerosolType aerosolType, float cloudDensity,
float exposureTime, float deltaTime);
DamageStage GetDamageStage(float accumulatedDamage);
}
```
#### 6.4.2 三种机制的差异
| 机制 | 气溶胶类型 | 毁伤原理 | 毁伤曲线特征 |
|------|------|------|------|
| **吸入式灭火** | 惰性气体 | 发动机吸入惰性气体 → 氧气浓度下降 → 熄火 | 阈值型:密度达标后快速生效,延迟短 |
| **爆燃式** | 活性材料 | 材料接触高温发动机表面 → 化学反应爆燃 | 触发型:密度 + 温度双条件,瞬间高伤害 |
| **吸入式爆炸** | 活性燃料 | 燃料被吸入进气道 → 内部爆炸 | 累积型:随暴露时间指数增长 |
```csharp
// 实现示例伪代码
// 吸入式灭火:阈值判定
class InertGasDamageModel : IDamageModel
{
float CalculateDamage(...) {
if (cloudDensity < effectiveThreshold) return 0; // 浓度不够,无伤害
// 超过阈值后,线性累积毁伤
return damageRate * deltaTime;
}
}
// 爆燃式:瞬时触发
class ActiveMaterialDamageModel : IDamageModel
{
float CalculateDamage(...) {
if (cloudDensity < triggerThreshold) return 0;
if (!triggered) { triggered = true; return burstDamage; } // 一次性爆发
return residualDamage * deltaTime; // 后续余伤
}
}
// 吸入式爆炸:指数累积
class ActiveFuelDamageModel : IDamageModel
{
float CalculateDamage(...) {
if (cloudDensity < effectiveThreshold) return 0;
// 累积暴露 → 指数增长
return baseRate * Mathf.Exp(exposureTime * factor) * deltaTime;
}
}
```
#### 6.4.3 毁伤阶段判定
```
accumulatedDamage: 0.0 ─────── 0.25 ─────── 0.6 ─────── 1.0
DamageStage: Normal EngineAnomaly AttitudeLoss Destroyed
Normal: 正常运行
EngineAnomaly: 发动机异常Unity: 尾焰变色/不稳定)
AttitudeLoss: 姿态失控Unity: 偏航/滚转)
Destroyed: 被摧毁Unity: 坠落动画)
```
### 6.5 防御推荐算法设计
#### 6.5.1 Step A气溶胶选型
基于**规则匹配**,根据目标动力类型推荐最佳毁伤机制:
| 目标动力 | 推荐气溶胶 | 理由 |
|------|------|------|
| 电推式 | 惰性气体(吸入式灭火) | 电动机无高温,爆燃/爆炸不适用;惰性气体使电调/散热失效 |
| 活塞式 | 惰性气体(吸入式灭火) | 活塞发动机依赖氧气,窒息最有效 |
| 喷吸气式 | 活性材料(爆燃式) | 喷气发动机高温表面触发爆燃 |
| — | 活性燃料(吸入式爆炸) | 适用于高价值高速目标,追求一击必杀 |
```csharp
// 选型规则表(可配置)
static readonly Dictionary<PowerType, AerosolType> MatchTable = new()
{
{ PowerType.Electric, AerosolType.InertGas },
{ PowerType.Piston, AerosolType.InertGas },
{ PowerType.Jet, AerosolType.ActiveMaterial },
};
```
#### 6.5.2 Step B云团参数推荐 — 时空交汇优化
```
问题:
输入 = 目标航路 R(t)、风速 Vw、搭载平台位置 Pp、弹药飞行时间 Tf
输出 = 最优抛撒位置 Ps 和触发时机 Ts
方法:
1. 将目标航路离散为时间点 t₁, t₂, ..., tₙ
2. 对每个 tᵢ
a. 无人机位置 = R(tᵢ)
b. 考虑炮弹飞行时间 Tf抛撒时刻 = tᵢ - Tf
c. 云团在 [tᵢ - Tf, tᵢ - Tf + Duration] 内的扩散范围
d. 计算交汇窗口 = 无人机航路 ∩ 云团扩散范围的时空重叠
3. 选择交汇窗口最大的 (Ps, Ts) 作为最佳值
4. 选择交汇窗口刚好有效的边界作为最危险值
简化实现:
- 云团近似为匀速膨胀球体
- 无人机匀速直线飞行(取平均速度)
- 解析解:计算无人机航迹与云团膨胀球面的两个交点
- 最佳 = 无人机在云团中时间最长
- 最危险 = 无人机刚好擦边
```
#### 6.5.3 Step C反推平台部署
```
根据云团方案反推:
Q: 需要覆盖多大面积?
→ 根据目标数量、编队间距、航路宽度 → 需要的云团数
Q: 每个云团需要多少弹药?
→ 云团体积 / 单发覆盖体积 → 弹药数
Q: 用什么平台?
→ 抛撒点距目标 > 平台航程?→ 地基
→ 抛撒点距目标 ≤ 平台航程?→ 空基
→ 根据弹药初速 / 飞行时间校验可行性
Q: 探测设备需要多大半径?
→ 探测半径 ≥ 从平台发现目标到完成拦截期间目标飞过的距离
```
#### 6.5.4 接口
```csharp
public interface IDefenseAdvisor
{
DefenseRecommendation Recommend(ThreatProfile threat);
}
// ThreatProfile / DefenseRecommendation / DefenseSolution 等模型见本节上文
```
### 6.6 新增数据表AmmunitionSpec
| 字段 | 类型 | 约束 | 说明 |
|------|------|------|------|
| Id | TEXT | PK | GUID |
| AerosolType | INTEGER | | 气溶胶类型 |
| Name | TEXT | | 弹药名称 |
| InitialRadius | REAL | | 初始云团半径 m |
| InitialVolume | REAL | | 初始云团体积 m³ |
| CoreDensity | REAL | | 核心密度 kg/m³ |
| EdgeDensity | REAL | | 边缘密度 kg/m³ |
| InitialTemperature | REAL | | 初始温度 K |
| BuoyancyFactor | REAL | | 浮力系数 |
| EffectiveConcentration | REAL | | 有效毁伤浓度阈值 |
| DispersionRateBase | REAL | | 基础扩散速率 m/s |
| MaxRadius | REAL | | 最大有效半径 m |
| MaxDuration | REAL | | 最大持续时间 s |
| ParticlesJson | TEXT | | 粒子渲染参数 JSON |
> 第三方以 JSON 文件交付,导入到此表。系统启动时若表为空则从默认配置文件加载。
### 6.7 算法替换完整示例
以下是将来用第三方 DLL 替换扩散模型的完整流程,演示接口驱动架构的灵活性:
```
┌─ 步骤 1第三方提供实现 ─────────────────────────────┐
│ │
│ ThirdPartyDispersion.dll │
│ └─ class ThirdPartyPuff : ICloudDispersionModel │
│ { │
│ void Initialize(AmmunitionSpec, ...) → P/Invoke → native_init()
│ void Tick(float, float, WindDirection) → P/Invoke → native_tick()
│ Vector3 Center → P/Invoke → native_center()
│ float Radius → P/Invoke → native_radius()
│ ... │
│ } │
│ │
└────────────────────────────────────────────────────────┘
┌─ 步骤 2一行注册 ──────────────────────────────────┐
│ │
│ AlgorithmFactory.Register │
│ <ICloudDispersionModel, ThirdPartyPuff>(); │
│ │
└────────────────────────────────────────────────────────┘
┌─ 步骤 3SimulationEngine 无感知切换 ───────────────┐
│ │
│ var dispersion = AlgorithmFactory │
│ .Create<ICloudDispersionModel>(ammo, env, pos, t);│
│ │
│ // 后续代码完全不变,无论底层是自主实现还是第三方 DLL │
│ dispersion.Tick(deltaTime, windSpeed, windDir); │
│ if (dispersion.IsDissipated) { ... } │
│ │
└────────────────────────────────────────────────────────┘
```
**替换粒度**:每个算法组件独立替换,可以实现如下组合:
```
组合 A当前
ICloudDispersionModel → GaussianPuffDispersion自主
IDamageModel → DamageModelRouter自主
IDefenseAdvisor → DefaultDefenseAdvisor自主
组合 B将来可能
ICloudDispersionModel → ThirdPartyPuff第三方 DLL
IDamageModel → DamageModelRouter自主保留
IDefenseAdvisor → DefaultDefenseAdvisor自主保留
组合 C将来可能
ICloudDispersionModel → ThirdPartyPuff第三方 DLL
IDamageModel → ThirdPartyDamage第三方 DLL
IDefenseAdvisor → DefaultDefenseAdvisor自主保留
```
---
## 七、数据录制与回放
### 7.1 IFrameDataStore 接口
```csharp
/// <summary>帧数据存储 — 每任务一个独立 SQLite 文件</summary>
public interface IFrameDataStore
{
/// <summary>为任务创建帧数据库文件</summary>
void CreateTaskDb(string taskId);
/// <summary>批量写入一帧所有实体状态</summary>
void WriteFrame(string taskId, int frameIdx, float timestamp,
List<EntitySnapshot> entities);
/// <summary>按帧范围读取(回放用)</summary>
List<SimFrameRecord> ReadFrames(string taskId, int fromFrame, int toFrame);
/// <summary>删除任务的帧数据库</summary>
void DeleteTaskDb(string taskId);
/// <summary>清理过期的帧数据库(定时调用)</summary>
void CleanupExpired(DateTime olderThan);
}
```
### 7.2 录制
- 仿真启动时创建 `frames/{taskId}.db`
- 录制帧率 = 仿真 TickRate每想定可配置默认 20Hz
- 每 Tick 调用 `WriteFrame()` 写入该帧所有实体状态
- SQLite 事务批量提交(如每 50 帧一批,减少磁盘 IO
- 仿真事件 `SimEvent` 直接写入主库 `main.db`(每任务 ~30 条,轻量)
### 7.3 回放
- ReplayController 协程驱动
- 打开 `frames/{taskId}.db`,按 FrameIndex 范围查询
- WHERE FrameIndex BETWEEN a AND b 命中索引,毫秒级
- 回放帧率由前端控制(可与录制不同)
- 支持暂停 / 快进 / 后退 / 跳转
### 7.4 容量估算
以默认 20Hz TickRate16 实体为例:
| 仿真时长 | 帧数 | 行数16实体 | 单任务大小 |
|------|------|------|------|
| 5 min | 6,000 | 96,000 | ~27 MB |
| 15 min | 18,000 | 288,000 | ~80 MB |
| 30 min | 36,000 | 576,000 | ~161 MB |
| 60 min | 72,000 | 1,152,000 | ~322 MB |
6 个月累计(假设日均 5 次仿真,每次 30min
| 项目 | 数据 |
|------|------|
| 仿真总次数 | 5 × 180 = 900 次 |
| 帧数据总大小 | 900 × 161 MB ≈ **145 GB** |
| main.db | < **100 MB** |
| 全部合计 | **~145 GB** |
### 7.5 TTL 清理策略
```
仿真完成 → 生成 frames/{taskId}.db
CleanupExpired() 每天执行一次:
├─ 扫描 frames/ 目录
├─ 检查 {taskId}.db 的创建时间
└─ 超过 6 个月 → 删除文件
可选扩展:
- 归档:移到 archive/ 目录并压缩(.db.gz
- 降采样:删除前先保留每 N 帧 1 帧的精简版
```
### 7.6 为什么分库而非单库
| 对比 | 单库(全部在 main.db | 分库(每任务一个 .db |
|------|------|------|
| 帧表行数6月 | 5.18 亿行 | 每库 57.6 万行 |
| 查询延迟 | 秒级(需精细索引) | 毫秒级 |
| 单文件体积 | > 100 GB | 每文件 ~161 MB |
| 备份/VACUUM | 灾难级 | 无痛 |
| 数据损坏影响 | 全部丢失 | 仅一个任务 |
| 运维(删除/归档) | 复杂 SQL | 直接删文件 |
---
## 八、报告生成
### 8.1 报告结构
技术要求终版要求报告包含**时序图**和三个分析维度:
| 阶段 | 内容 | 数据来源 |
|------|------|------|
| **仿真前** | 我方配置(装备类型/数量/编组、弹药类型/数量、部署位置、管控区域) | SimTask + 5 步配置 |
| **仿真中** | 关键事件时序表、各实体轨迹概要、云团演化数据 | SimEvent + SimFrameRecord |
| **仿真后** | 拦截成功率、各阶段耗时、毁伤效果评估、对抗结果判定 | SimEvent 汇总统计 |
### 8.2 对抗结果判定逻辑
```
成功拦截:所有无人机 被摧毁(未抵达目标、未侵入管控区)
部分拦截:部分无人机被摧毁,其余抵达目标或侵入管控区
拦截失败:所有无人机抵达目标或侵入管控区(无摧毁)
```
### 8.3 导出
- 格式PDF / Word默认 PDF
- 模板占位符填充后输出
- 技术选型QuestPDF 或其他 .NET Standard 2.1 兼容方案(待调研)
---
## 九、服务接口概要
```csharp
// === 模型管理 ===
interface IModelService
{
ModelInfo ImportModel(string filePath, string name);
void DeleteModel(string id);
List<ModelInfo> GetAllModels();
ModelInfo GetModel(string id);
}
// === 编组管理 ===
interface IGroupService
{
Group CreateGroup(string name, GroupType type, string description);
void DeleteGroup(string id);
List<Group> GetGroups(GroupType? type);
}
// === 想定管理 ===
interface IScenarioService
{
SimTask CreateTask(string name, string taskNumber);
void DeleteTask(string id);
PagedResult<SimTask> SearchTasks(string kw, DateTime? from, DateTime? to, int page, int size);
TaskFullConfig GetTaskDetail(string id);
// 步骤保存
void SaveScene(string taskId, CombatScene scene);
void SaveControlZones(string taskId, List<ControlZone> zones); // NEW
void SaveTarget(string taskId, TargetConfig target);
void SaveDeployment(string taskId, List<EquipmentDeployment> equips); // 重构
void SaveCloudDispersal(string taskId, CloudDispersal cloud);
void SaveRoute(string taskId, RoutePlan route, List<Waypoint> wps);
void UpdateStep(string taskId, int step);
// 综合防御推荐NEW — 多编队版)
DefenseRecommendation GetDefenseRecommendation(string taskId);
}
// === 仿真引擎 ===
interface ISimulationEngine
{
void Initialize(string taskId);
SimulationFrameResult Tick(float deltaTime);
void Pause();
void Resume();
void Stop();
SimulationState State { get; }
}
// === 数据录制 ===
interface IRecordService
{
void StartRecording(string taskId, int tickRate);
void WriteFrame(int frameIdx, float timestamp, List<EntitySnapshot> entities);
void WriteEvent(SimEvent evt);
void StopRecording();
List<SimFrameRecord> GetFrames(string taskId, int from, int to);
List<SimEvent> GetEvents(string taskId);
void CleanupExpired(DateTime olderThan); // TTL 清理
}
// === 仿真报告 ===
interface IReportService
{
SimulationReport Generate(string taskId);
SimulationReport GetReport(string id);
void DeleteReport(string id);
byte[] ExportReport(string id, string format); // "pdf" | "word"
PagedResult<SimulationReport> SearchReports(string kw, DateTime? from, DateTime? to, int page, int size);
}
```
---
## 九-A、多批次多编队设计
### 数据模型
一个仿真任务可包含**多种类型、多批次**的无人机,每批次(编队)有独立的航路:
```
SimTask "城市防御演习"
├── CombatScene共享
├── ControlZone[](共享)
├── CloudDispersal共享云团参数具体拦截方案由算法确定
├── 编队 A活塞×3 ← Group.Id
│ ├── TargetConfig类型=活塞,数量=3
│ ├── RoutePlan航路 A北→南
│ └── Waypoint[]
├── 编队 B喷气×2 ← Group.Id
│ ├── TargetConfig类型=高速,数量=2
│ ├── RoutePlan航路 B西→东
│ └── Waypoint[]
└── 编队 C旋翼×5 ← Group.Id
├── TargetConfig类型=旋翼,数量=5
├── RoutePlan航路 C
└── Waypoint[]
```
**关键变更**`RoutePlan` 主键从 `TaskId` 改为 `(TaskId, GroupId)` 复合键。
### 推荐算法
算法需要同时考虑**所有无人机编队**和**可用装备火力单元**,自动匹配分配:
```csharp
// 输入:所有无人机编队 + 已部署的火力单元
// 输出:每个编队的拦截方案 + 合并的发射计划
var allSolutions = new List<DefenseSolution>();
var usedPlatforms = new HashSet<int>();
foreach (var droneGroup in threat.DroneGroups)
{
// 从可用装备中选择合适的火力单元(弹药类型匹配目标动力类型)
var availableUnits = fireUnits.Where(u => !usedPlatforms.Contains(u.Id)).ToList();
var solution = advisor.RecommendForGroup(droneGroup, environment, availableUnits);
// 标记占用的平台(一组装备可同时对付一个编队)
foreach (var idx in solution.AssignedPlatformIndices)
usedPlatforms.Add(idx);
allSolutions.Add(solution);
}
// 复用判定(不写死"一对一"或"一对多"
// 同种弹药 → 只需冷却时间(秒级),可直接复用
// 异种弹药 → 需要 AmmoChangeTime默认 5 分钟),检查编队间隔是否够
// 弹药耗尽 → 不可复用
var merged = MergeFireSchedules(allSolutions);
engine.SetFireSchedule(merged);
```
**关键原则**
- 算法决定分配,而非写死"一对一"或"一对多"
- 决策依据:弹药类型匹配、时间窗口重叠、火力单元能力
- 人工可调整算法推荐结果
- 引擎不感知分组——只看合并后的 `FireSchedule`
### 数据表变更
| 表 | 变更 |
|------|------|
| `RoutePlan` | PK 改为 (TaskId, GroupId) 复合键 |
| `TargetConfig` | 不变(已有 GroupId FK |
| `Waypoint` | 关联 `(TaskId, GroupId)` 定位航路 |
`IScenarioService` 新增:
```csharp
void SaveRoute(string taskId, string groupId, RoutePlan route, List<Waypoint> wps); // groupId 参数
```
### 报告
报告新增多编队汇总:
```markdown
## 编队汇总
| 编队 | 目标 | 数量 | 拦截方案 | 结果 |
|------|------|------|------|------|
| 编队A | 活塞 | 3 | 惰性气体 12发 | ✅ 全毁 |
| 编队B | 喷气 | 2 | 活性材料 8发 | ⚠️ 1逃脱 |
```
---
## 十、配置向导步骤(整合后)
整合需求 V1.0 和技术要求终版后,配置向导保持 5 步但内容调整:
```
┌────────────────────────────────────────────────────────┐
│ 步骤 1作战场景设置 │
│ ├─ 场景类型(城市/平原/山区/海岸) │
│ ├─ 时间段24h 制 NEW
│ ├─ 天气 + 风速/风向/温度/湿度/气压/能见度 │
│ ├─ 场景空间范围(宽/纵深/高 NEW
│ └─ 管控区域(电子围栏 NEW
│ └─ 多边形绘制 / 编辑 / 删除 │
├────────────────────────────────────────────────────────┤
│ 步骤 2目标配置 │
│ ├─ 编组选择(已有编队/新建编队) │
│ ├─ 目标类型选择(自动填充默认参数) │
│ ├─ 数量 / 动力类型 / 翼展 / 速度 / 高度 │
│ └─ 预设典型目标库NEW
├────────────────────────────────────────────────────────┤
│ 步骤 3装备部署重构
│ ├─ 装备角色(探测设备 / 发射平台) │
│ ├─ 发射平台类型(空基 / 地基 NEW
│ ├─ 数量 / 编组 / 部署位置 │
│ ├─ 挂载气溶胶类型 / 弹药数量 │
│ ├─ 弹药初速 / 释放高度 / 冷却时间 │
│ └─ 探测半径(探测设备) │
├────────────────────────────────────────────────────────┤
│ 步骤 4云团抛撒配置 │
│ ├─ 气溶胶类型(吸入式灭火/爆燃式/吸入式爆炸) │
│ ├─ 释放参数(高度/触发模式/扩散方向/规模/持续等) │
│ ├─ 抛撒位置(三维点选 / 手动输入 / 算法推荐 NEW
│ ├─ 算法推荐按钮 → 显示最佳值 & 最危险值NEW
│ └─ 可点选采纳推荐值 │
├────────────────────────────────────────────────────────┤
│ 步骤 5航路规划 │
│ ├─ 编队模式(单机/编队/蜂群) │
│ ├─ 编队间距 / 预计到达时间 │
│ ├─ 航路点画布(三维点选添加/调整/删除 NEW
│ └─ 航路点列表(坐标/高度/速度) │
└────────────────────────────────────────────────────────┘
```
---
## 十一、关键技术决策
| # | 决策 | 选择 | 理由 |
|---|------|------|------|
| 1 | 数据持久化 | SQLite (sqlite-net) | 支持复杂查询、筛选、分页 |
| 2 | 模型文件格式 | .fbx / .obj / .stl / .glb / .gltf | 合并两份需求≤500MB2K+贴图 |
| 3 | 模型文件存储 | Application.persistentDataPath | 不与 Unity Assets 耦合 |
| 4 | 序列化方案 | System.Text.Json | Unity 2022+ 内置支持 |
| 5 | Service/Data 层 | 零 UnityEngine 依赖 | 可独立单元测试 |
| 6 | 仿真驱动方式 | 固定 TickRate 帧驱动 | 每想定可配置(默认 20Hz保证确定性 |
| 7 | 仿真并发 | 单仿真 | 简化状态管理 |
| 8 | 拦截机制 | 多阶段链路 | 探测→火控→发射→弹药飞行→云团→毁伤 |
| 9 | 云团扩散模型 | **高斯烟团模型(自主实现)** | 简化球体膨胀 + 风速漂移 + 密度衰减,适合实时 20Hz |
| 10 | 毁伤模型 | **三种机制自主实现** | 吸入式灭火(阈值型)、爆燃式(触发型)、吸入式爆炸(指数累积型) |
| 11 | 防御方案推荐 | **IDefenseAdvisor自主实现** | 规则匹配选型 + 时空交汇优化 + 反推平台部署 |
| 12 | 第三方数据 | **静态配置JSON → SQLite** | 仅提供弹药基础参数和初始扩散状态,不提供运行时算法 |
| 13 | 运动学 | 简化运动学 + 风偏 | 航路点线性插值 + 风速矢量 |
| 14 | 弹药弹道 | 抛物线(地基)/ 自由落体(空基) | 基于初速、角度、释放高度计算 |
| 15 | 编组 | Group 独立实体 | 编组独立管理,任务中引用 |
| 16 | 管控区域 | ControlZone 表 + Tick 判定 | 电子围栏,侵入即任务失败 |
| 17 | 配置向导流程 | **威胁驱动三阶段** | Phase1 定义威胁 → Phase2 算法推荐 → Phase3 审阅确认 |
| 18 | 报告导出 | 模板填充 → Markdown | PDF/Word 待调研 |
| 19 | 坐标系统 | 右手系 Y-up米为单位 | 与 Unity 一致 |
| 20 | 空间范围 | 最低 4×100×10m默认更大 | 可配置 |
| 21 | 帧数据存储 | **主库 + 任务分库** | 主库存元数据+事件(<100MB永久分库每任务存帧数据6月TTL单文件~161MB直接删文件运维 |
| 22 | 程序集拆分 | **Core 独立于 Unity** | Core .NET Standard 2.1 纯类库 UnityEngine 依赖Unity 仅作桥接dotnet test 即可全量测试 |
---
## 十二、性能指标(来自技术要求终版)
| 指标 | 要求 | 说明 |
|------|------|------|
| 最大目标数 | 5 独立运动实体3D 显示 | 显示层面非逻辑上限 |
| 渲染帧率 | 30 FPS满载 + 粒子特效 | Unity 前端职责 |
| 仿真空间 | 4m × 100m × 10m | 默认更大可配置 |
| 粒子系统 | 云团扩散/流动/色彩 | Unity 根据后端参数渲染 |
| 毁伤效果 | 尾焰异常姿态失控坠落 | Unity 根据 DamageStage 渲染 |
---
## 十三、待后续讨论
| # | 议题 | 说明 |
|---|------|------|
| 1 | 第三方 DLL 的具体接口规范 | 需与供应商对齐函数签名数据结构调用约定 |
| 2 | 3 种毁伤机制的差异化细节 | 吸入式灭火 vs 爆燃式 vs 吸入式爆炸的毁伤曲线差异 |
| 3 | 探测设备融合逻辑 | 多设备发现同一目标时的数据融合策略 |
| 4 | 火控分配策略 | 多目标时的优先级分配规则 |
| 5 | 蜂群模式运动模型 | 随机扰动范围个体行为差异 |
| 6 | 报告模板具体格式 | 统计维度图表需求 |
| 7 | 场景类型对仿真的影响 | 山区是否影响探测/运动 |
| 8 | PDF/Word 导出库选型 | QuestPDF 或其他 .NET Standard 2.1 方案 |
| 9 | 预置典型目标库内容 | 具体包含哪些无人机型号及参数 |
| 10 | 扩散模型的大气稳定度参数 | 不同天气条件下 σ 的增长速率如何量化 |
| 11 | 毁伤曲线的具体数值 | 三种机制的 damageRatethresholdburstDamage 等参数取值 |
| 12 | 时空交汇优化的精度 | 离散采样步长 vs 解析解的选择 |