新增: - IConfigService / ConfigService:读写 defaults.json / planner_config.json - SavePlannerConfig / SaveDefaults / Reload,无需重启 Unity - PlannerConfigReloaded 事件 → ScenarioManager 自动重建 planner - SimulationEngine.UpdatePlanner / ScenarioService.UpdatePlanner - SimulationRunner.ReloadPlanner 桥接 - DefenseRecommendation / RecommendOption 返回类型 - IScenarioService.GetDefenseRecommendation(配置阶段生成最佳抛撒参数) - ConfigServiceTests 5 个测试 + DefenseRecommendationTests 3 个测试 修复: - 云团间距半径基准不一致(间距用 R30、穿越用 R27 → 统一用 effectiveRadius) - 消除硬编码 30f(DefensePlanner + GaussianPuffDispersion 读 Phase2Duration) - TryGenerateFireEvents 复用 ComputeEffectiveRadius,消除重复计算 - 概率计算间距加重叠系数 - DatabaseManager 不再 DROP SimulationReport(保留历史报告) - 清理迁移代码(MetaEntry / 旧表 DROP / 版本检查) 文档: - 对接文档 V2.1:加 IConfigService API + 配置重载用法 + 修正 DLL 更新说明 - 实施跟踪 V1.8:8.2.1 更新 + 新增 8.2.3/8.2.4 + M14 里程碑 - 270 测试通过,Unity 编译通过
956 lines
39 KiB
Markdown
956 lines
39 KiB
Markdown
# 后端对接文档(Unity 前端)
|
||
|
||
> **版本**:V2.1
|
||
> **日期**:2026-06-22
|
||
> **Unity 版本**:2022.3.62f3c1
|
||
|
||
---
|
||
|
||
## 一、交付物与部署
|
||
|
||
### 1.1 需要取的文件
|
||
|
||
```
|
||
src/Unity/Assets/Plugins/CounterDrone.Core/ ← 22 个 DLL(拖入 Unity 项目的 Plugins 目录)
|
||
src/Unity/Assets/Scripts/Managers/ ← 9 个桥接脚本
|
||
```
|
||
|
||
StreamingAssets 资源文件(放到 Unity 项目 `Assets/StreamingAssets/` 下):
|
||
|
||
```
|
||
StreamingAssets/
|
||
defaults.json ← 默认数据(首次运行自动复制到 persistentDataPath)
|
||
planner_config.json ← 规划器配置
|
||
fonts/CJK-Font.ttf ← PDF 导出用的中文字体(仅 PDF 导出需要)
|
||
```
|
||
|
||
> 以上资源文件可在仓库的 `data/` 目录找到。字体文件名硬编码为 `CJK-Font.ttf`,可替换为任意 CJK TrueType 字体但不可改名。
|
||
|
||
### 1.2 DLL 清单(22 个)
|
||
|
||
全部为纯托管 DLL,无原生库依赖,Unity IL2CPP/Mono 全平台兼容。
|
||
|
||
| DLL | 用途 |
|
||
|-----|------|
|
||
| `CounterDrone.Core.dll` | 核心库 |
|
||
| `SQLite-net.dll` | SQLite ORM |
|
||
| `SQLitePCLRaw.core.dll` / `batteries_v2.dll` / `provider.e_sqlite3.dll` | SQLite 原生提供程序 |
|
||
| `System.Text.Json.dll` / `Encodings.Web.dll` / `Microsoft.Bcl.AsyncInterfaces.dll` | JSON 序列化 |
|
||
| `System.Memory.dll` / `Buffers.dll` / `Numerics.Vectors.dll` / `Runtime.CompilerServices.Unsafe.dll` / `IO.Pipelines.dll` / `Threading.Tasks.Extensions.dll` | 基础库传递依赖 |
|
||
| `PdfSharpCore.dll` | PDF 生成 |
|
||
| `ICSharpCode.SharpZipLib.dll` | PdfSharpCore 依赖(ZIP) |
|
||
| `SixLabors.Fonts.dll` / `SixLabors.ImageSharp.dll` | PdfSharpCore 依赖(字体/图像) |
|
||
| `System.Collections.Concurrent.dll` / `IO.UnmanagedMemoryStream.dll` / `Threading.Tasks.Parallel.dll` / `Threading.dll` / `IO.FileSystem.Primitives.dll` | SixLabors 传递依赖 |
|
||
|
||
### 1.3 DLL 导入设置
|
||
|
||
DLL 拖入 `Assets/Plugins/CounterDrone.Core/` 后,在 Inspector 中确认所有 DLL 的平台勾选:**Editor + Standalone + Android + iOS 全部勾选**(所有 DLL 均全平台兼容)。
|
||
|
||
> **IL2CPP 注意**:若遇 `TypeLoadException`,检查 `Player Settings → Managed Stripping Level`,建议设为 **Low** 或 **Medium**。
|
||
|
||
### 1.4 更新后端 DLL
|
||
|
||
```bash
|
||
# 方式 A:一键脚本(自动编译 + 复制 DLL + Unity 编译验证)
|
||
pwsh scripts/check_unity_build.ps1
|
||
|
||
# 方式 B:手动
|
||
cd src/CounterDrone.Core
|
||
dotnet publish -c Release -o ../../unity_plugins
|
||
# 然后将 unity_plugins/*.dll 全部复制到 src/Unity/Assets/Plugins/CounterDrone.Core/
|
||
```
|
||
|
||
> **重要**:更新 DLL 后首次运行 Unity 会建表+种子默认数据。**历史仿真报告不再丢失**(SimulationReport 表不再被 DROP)。
|
||
|
||
---
|
||
|
||
## 二、快速开始
|
||
|
||
1. 按 1.1 部署 DLL、脚本和 StreamingAssets 资源
|
||
2. 创建空 GameObject,挂 `SimulationBootstrap`
|
||
3. 运行 — 自动种子数据库,选一个 `[Demo]` 想定,启动仿真
|
||
|
||
> `SimulationBootstrap` 是参考模板,展示预设模式(一行代码)和自定义模式两种路径。Inspector 勾选 `_usePreset` 切换。
|
||
|
||
---
|
||
|
||
## 三、完整工作流(5 步)
|
||
|
||
```
|
||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ ┌──────────┐
|
||
│ 基础数据 CRUD │ → │ 创建想定 │ → │ 运行仿真 │ → │ 生成报告 │ → │ 回放 │
|
||
│ DataService │ │ ScenarioMgr │ │ SimRunner │ │ ReportMgr │ │ Replay │
|
||
└─────────────┘ └─────────────┘ └─────────────┘ └──────────┘ └──────────┘
|
||
```
|
||
|
||
### 3.1 管理基础数据
|
||
|
||
```csharp
|
||
var ds = GetComponent<ScenarioManager>().DataService;
|
||
|
||
var drones = ds.GetAllDrones();
|
||
ds.SaveDrone(new DroneSpec { Id = "custom", Name = "自定义", TypicalSpeed = 100, ... });
|
||
ds.DeleteDrone("custom");
|
||
|
||
// 7 类基础数据均提供 GetAll/Get/Save/Delete 四个方法
|
||
```
|
||
|
||
### 3.2 创建想定
|
||
|
||
```csharp
|
||
var scenario = GetComponent<ScenarioManager>();
|
||
|
||
// 方式 A:预设想定
|
||
var demos = scenario.Search("Demo", null, null, 1, 100);
|
||
var scenarioId = demos.Items[0].Id;
|
||
|
||
// 方式 B:自定义(5 步配置)
|
||
var sc = scenario.CreateScenario("我的想定", "");
|
||
scenario.SaveScene(sc.Id, new CombatScene { WindSpeed = 5, WindDirection = (int)WindDirection.E });
|
||
scenario.SaveScenarioDrone(sc.Id, new ScenarioDrone { DroneSpecId = "shahed", WaveId = "w1", Quantity = 3 });
|
||
scenario.SaveDeployment(sc.Id, new List<ScenarioUnit> {
|
||
new() { FireUnitSpecId = "ground-light", Quantity = 2,
|
||
PositionX = 5000, PositionY = 0, PositionZ = 50, AerosolType = 0, MunitionCount = 8 }
|
||
});
|
||
scenario.SaveRoute(sc.Id, "w1", new RoutePlan(), new List<Waypoint> {
|
||
new() { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
|
||
new() { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 }
|
||
});
|
||
scenario.SaveCloud(sc.Id, new CloudDispersal { AerosolType = 0, DisperseHeight = 500 });
|
||
scenario.UpdateStep(sc.Id, 5);
|
||
```
|
||
|
||
### 3.3 运行仿真
|
||
|
||
```csharp
|
||
var runner = GetComponent<SimulationRunner>();
|
||
runner.LoadAndStart(scenarioId);
|
||
runner.Engine.TimeScale = 4f;
|
||
|
||
// 事件订阅
|
||
runner.Engine.OnMunitionLaunched += m => { };
|
||
runner.Engine.OnCloudGenerated += c => { };
|
||
runner.Engine.OnDroneDestroyed += d => { };
|
||
runner.Engine.OnSimulationEnded += () => { };
|
||
|
||
// 逐帧驱动(在 Update 中调用)
|
||
void Update() {
|
||
var result = runner.Engine.Tick(Time.deltaTime);
|
||
foreach (var snap in result.EntitySnapshots) {
|
||
// snap.EntityType, PosX/Y/Z, VelX/Y/Z, Hp, CloudRadius...
|
||
}
|
||
}
|
||
|
||
runner.Stop();
|
||
```
|
||
|
||
### 3.4 生成报告
|
||
|
||
```csharp
|
||
var rm = GetComponent<ReportManager>();
|
||
var detail = scenario.GetDetail(scenarioId);
|
||
var report = rm.Generate(scenarioId, detail, runner.Engine.Events.ToList(),
|
||
runner.Engine.Drones[0].Status.ToString(), runner.Engine.SimulationTime);
|
||
|
||
// Generate() 自动导出 .md 文件到 {persistentDataPath}/reports/
|
||
// PDF 按需导出:
|
||
byte[] pdf = rm.ExportReport(report.Id, "pdf"); // → byte[]
|
||
string path = rm.Export(report.Id, dir, "pdf"); // → 文件路径
|
||
```
|
||
|
||
**Generate 参数**:
|
||
|
||
| 参数 | 类型 | 来源 |
|
||
|------|------|------|
|
||
| `scenarioId` | string | 创建想定时获得 |
|
||
| `config` | ScenarioConfig | `scenario.GetDetail(id)` |
|
||
| `events` | List\<SimEvent\> | `runner.Engine.Events.ToList()`(必须 `.ToList()` 拷贝) |
|
||
| `finalDroneStatus` | string | `runner.Engine.Drones[0].Status.ToString()` |
|
||
| `duration` | float | `runner.Engine.SimulationTime`(秒) |
|
||
|
||
**导出方法**:
|
||
- `ExportReport(id, "pdf")` → `byte[]`,实时渲染 PDF,需字体文件
|
||
- `ExportReport(id, "md")` → `byte[]`,从数据库直接读取,快
|
||
- `Export(id, dir, "pdf"/"md")` → 文件路径,自动创建目录
|
||
- `Export(id)` → 默认导出 MD 到 `{persistentDataPath}/reports/`
|
||
|
||
> PDF 导出依赖 `StreamingAssets/fonts/CJK-Font.ttf`,缺失抛 `FileNotFoundException`。PDF 渲染同步阻塞主线程(小报告 ~100ms,大报告可达 2s),UI 建议显示 loading。
|
||
|
||
### 3.5 回放
|
||
|
||
```csharp
|
||
var replay = GetComponent<ReplayController>();
|
||
replay.LoadReplay(scenarioId);
|
||
for (int i = 0; i < replay.TotalFrames; i++) {
|
||
var frame = replay.GetFrame(i);
|
||
// frame.SimulationTime, frame.EntitySnapshots...
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 四、坐标系与 3D 可视化
|
||
|
||
### 4.1 坐标系约定
|
||
|
||
| 项目 | 约定 |
|
||
|------|------|
|
||
| **向上轴** | **Y 轴 = 高度**(与 Unity 默认一致) |
|
||
| **水平面** | X 轴 = 纵深(航路方向),Z 轴 = 横向 |
|
||
| **单位** | 米(m) |
|
||
| **原点** | 场景一角(非中心),航路通常从 X=0 沿 X 正方向延伸 |
|
||
| **典型场景尺寸** | 4000m × 10000m × 1000m(W × L × H,见 `CombatScene.SceneWidth/Length/Height`) |
|
||
| **典型无人机高度** | 300~500m(PosY = 500 即 500m 高空) |
|
||
| **速度单位** | 航路点 `Waypoint.Speed` = **km/h**;平台 `CruiseSpeed` = **m/s**(引擎内部自动换算) |
|
||
|
||
> `SimulationRunner` 直接 `transform.position = new Vector3(snap.PosX, snap.PosY, snap.PosZ)`,无需轴变换。
|
||
|
||
### 4.2 Prefab 搭建
|
||
|
||
`SimulationRunner` 有 3 个 `[SerializeField]` prefab 字段,Inspector 中拖入:
|
||
|
||
| 字段 | 用途 | null 时回退 | 建议缩放 |
|
||
|------|------|------------|---------|
|
||
| `_dronePrefab` | 无人机 | Cube | Runner 自动设 `localScale = Vector3.one * 50f` |
|
||
| `_cloudPrefab` | 云团 | Sphere | Runner 按云团半径动态设 `localScale = Vector3.one * CloudRadius` |
|
||
| `_platformPrefab` | 发射平台 | Capsule | Runner 自动设 `localScale = (30, 80, 30)` |
|
||
| —(无字段) | 弹药 | Cylinder | Runner 自动设 `localScale = (2, 10, 2)` |
|
||
|
||
**Prefab 组件要求**:
|
||
|
||
| 组件 | 必需 | 说明 |
|
||
|------|------|------|
|
||
| `Renderer` | ✅ | Runner 通过 `GetComponent<Renderer>().material` 设置颜色 |
|
||
| `Collider` | 可选 | Runner 不依赖 Collider |
|
||
| 脚本组件 | 不需要 | 位置由 Runner 每帧驱动,prefab 不需要自带移动脚本 |
|
||
|
||
**云团可视化建议**:prefab 用 Sphere 即可(Runner 设红色半透明材质)。如需粒子效果,可自行扩展——Runner 每帧更新 `CloudRadius`(缩放)和 `CloudOpacity`(材质 alpha),粒子系统可读取这两个值驱动参数。
|
||
|
||
### 4.3 SimulationRunner 可视化机制
|
||
|
||
Runner 的 `Update()` 每帧执行:
|
||
|
||
1. 调用 `engine.Tick(Time.deltaTime)` → 获取 `SimulationFrameResult`
|
||
2. 遍历 `result.EntitySnapshots`:
|
||
- 新实体(EntityId 未见过)→ Instantiate prefab
|
||
- 已有实体 → 更新 `transform.position`
|
||
- Cloud 类型 → 更新 `localScale`(按 `CloudRadius`)和材质 alpha(按 `CloudOpacity`)
|
||
3. 遍历 `engine.Munitions` 同步炮弹位置,清理已消失的弹药 GameObject
|
||
|
||
**实体颜色约定**(Runner 硬编码,可自行修改):
|
||
- 无人机:prefab 原始材质
|
||
- 云团:红色半透明 `(1, 0, 0, CloudOpacity)`
|
||
- 平台:蓝色半透明 `(0.2, 0.5, 1, 0.8)`
|
||
- 弹药:黄色 `(1, 0.92, 0.016, 1)`
|
||
|
||
### 4.4 相机定位参考
|
||
|
||
`SimulationBootstrap` 中的相机设置(可供参考):
|
||
|
||
```csharp
|
||
// 俯瞰视角
|
||
cam.transform.position = new Vector3(midX, 2000, -3000); // midX = 场景中点
|
||
cam.transform.LookAt(new Vector3(midX, 500, 0)); // 看向 500m 高度
|
||
```
|
||
|
||
### 4.5 探测范围可视化
|
||
|
||
`DetectionEntity` 提供 `IsInRange(x, y, z, visibility, out effectiveRange)` 方法。如需绘制 3D 球冠范围,可从 `SensorSpec` 读取 `RadarRange`/`EORange`/`IRRange` 和 `MinElevation`/`MaxElevation`/`MinDetectAlt`/`MaxDetectAlt`,用 wireframe sphere 或 mesh 表示。
|
||
|
||
### 4.6 管控区域可视化
|
||
|
||
`ControlZone` 的 `VerticesJson` 存储多边形顶点 JSON:`[{"x":0,"y":0,"z":0},...]`。配合 `MinAltitude`/`MaxAltitude` 构成 3D 棱柱区域。前端可用 `LineRenderer` 画底面多边形 + 垂直线段表示高度范围。
|
||
|
||
---
|
||
|
||
## 五、Manager API 完整签名
|
||
|
||
所有 Manager 继承 `MonoBehaviour`,在 `Awake()` 中初始化内部服务。**必须在 `Awake` 之后(如 `Start`)才能调用**,`OnDisable` 后不可调用。
|
||
|
||
### ScenarioManager
|
||
|
||
```csharp
|
||
public IScenarioService Service { get; }
|
||
public IDataService DataService { get; } // 基础数据 CRUD(7 类)
|
||
public IConfigService Config { get; } // 配置读写 + 运行时重载
|
||
|
||
// Scenario CRUD
|
||
public Scenario CreateScenario(string name, string number);
|
||
public Scenario UpdateScenario(Scenario s);
|
||
public void DeleteScenario(string id);
|
||
public ScenarioConfig GetDetail(string id);
|
||
public PagedResult<Scenario> Search(string kw, string from, string to, int page, int size);
|
||
|
||
// CombatScene
|
||
public void SaveScene(string scenarioId, CombatScene s);
|
||
public CombatScene GetScene(string scenarioId);
|
||
|
||
// ControlZone
|
||
public void SaveControlZones(string scenarioId, List<ControlZone> z);
|
||
public List<ControlZone> GetControlZones(string scenarioId);
|
||
public void DeleteControlZone(string id);
|
||
|
||
// ScenarioDrone
|
||
public ScenarioDrone SaveScenarioDrone(string scenarioId, ScenarioDrone d);
|
||
public ScenarioDrone AddScenarioDrone(string scenarioId, ScenarioDrone d);
|
||
public void UpdateScenarioDrone(ScenarioDrone d);
|
||
public void DeleteScenarioDrone(string id);
|
||
public List<ScenarioDrone> GetScenarioDrones(string scenarioId);
|
||
|
||
// ScenarioUnit(部署)
|
||
public void SaveDeployment(string scenarioId, List<ScenarioUnit> e);
|
||
public ScenarioUnit AddDeploymentUnit(string scenarioId, ScenarioUnit u);
|
||
public void UpdateDeploymentUnit(ScenarioUnit u);
|
||
public void DeleteDeploymentUnit(string id);
|
||
public List<ScenarioUnit> GetDeploymentUnits(string scenarioId);
|
||
|
||
// Detection(探测设备,复用 ScenarioUnit)
|
||
public void AddDetection(string scenarioId, ScenarioUnit d);
|
||
public void DeleteDetection(string id);
|
||
public List<ScenarioUnit> GetDetections(string scenarioId);
|
||
|
||
// CloudDispersal
|
||
public void SaveCloud(string scenarioId, CloudDispersal c);
|
||
public CloudDispersal GetCloud(string scenarioId);
|
||
public void DeleteCloud(string scenarioId);
|
||
|
||
// Route & Waypoint
|
||
public void SaveRoute(string scenarioId, string waveId, RoutePlan r, List<Waypoint> w);
|
||
public List<RoutePlan> GetRoutes(string scenarioId);
|
||
public void DeleteRoute(string id);
|
||
public List<Waypoint> GetWaypoints(string scenarioId);
|
||
public List<Waypoint> GetWaypointsByWave(string scenarioId, string waveId);
|
||
public void DeleteWaypoint(string id);
|
||
|
||
// Misc
|
||
public void UpdateStep(string scenarioId, int step);
|
||
public EnumMetadata GetEnums(); // 枚举中英文对照(下拉框数据源)
|
||
|
||
// 防御推荐(配置阶段调用,仿真前生成最优抛撒参数)
|
||
public DefenseRecommendation GetDefenseRecommendation(string scenarioId);
|
||
```
|
||
|
||
**防御推荐用法**("一键应用"功能):
|
||
|
||
```csharp
|
||
var rec = scenario.GetDefenseRecommendation(scenarioId);
|
||
if (rec.Success)
|
||
{
|
||
// rec.Best.PosX/Y/Z — 推荐抛撒位置
|
||
// rec.Best.Timing — 推荐抛撒时机(仿真秒)
|
||
// rec.Best.SalvoRounds — 推荐弹药数
|
||
// rec.Best.EstimatedProbability — 估计拦截概率(0~1)
|
||
// rec.Best.ThreatsEngaged / ThreatsUnengaged — 已拦截/未拦截威胁数
|
||
|
||
// 用户点"一键应用" → 写入 CloudDispersal
|
||
var cloud = scenario.GetCloud(scenarioId);
|
||
cloud.PositionX = rec.Best.PosX;
|
||
cloud.PositionY = rec.Best.PosY;
|
||
cloud.PositionZ = rec.Best.PosZ;
|
||
cloud.Source = "Algorithm";
|
||
cloud.PositionMode = (int)PositionMode.AlgorithmRecommended;
|
||
scenario.SaveCloud(scenarioId, cloud);
|
||
}
|
||
else
|
||
{
|
||
Debug.Log($"推荐失败: {rec.Summary}");
|
||
}
|
||
```
|
||
|
||
### IConfigService(通过 `ScenarioManager.Config` 访问)
|
||
|
||
配置文件读写 + 运行时重载,**无需重启 Unity**:
|
||
|
||
```csharp
|
||
public interface IConfigService
|
||
{
|
||
string GetPlannerConfigJson(); // 读取 planner_config.json 原文
|
||
void SavePlannerConfig(string json); // 保存并立即重载(planner 自动重建)
|
||
string GetDefaultsJson(); // 读取 defaults.json 原文
|
||
void SaveDefaults(string json); // 保存并重载种子数据到数据库
|
||
void Reload(); // 从磁盘重新加载(前端直接改文件后通知后端刷新)
|
||
}
|
||
```
|
||
|
||
**用法 1:通过 API 修改配置**(推荐)
|
||
|
||
```csharp
|
||
var cfg = GetComponent<ScenarioManager>().Config;
|
||
|
||
// 读当前 planner 配置
|
||
string json = cfg.GetPlannerConfigJson();
|
||
|
||
// 修改后保存 — 自动重载,planner 立即用新参数
|
||
cfg.SavePlannerConfig(modifiedJson);
|
||
|
||
// 修改 defaults.json — 自动重载,数据库 InsertOrReplace 覆盖同 Id 记录
|
||
cfg.SaveDefaults(modifiedDefaultsJson);
|
||
```
|
||
|
||
**用法 2:直接改文件后通知后端重载**
|
||
|
||
```csharp
|
||
// 前端直接修改 persistentDataPath 下的 JSON 文件
|
||
// 然后通知后端重新加载
|
||
cfg.Reload(); // 重新读磁盘 → 重建 planner → 刷新种子数据
|
||
```
|
||
|
||
> `SavePlannerConfig` 触发后,`ScenarioManager` 内部的 `DefensePlanner` 会自动重建。`SimulationRunner` 中的 planner 在下次 `LoadAndStart` 时自动用新配置。运行中的仿真不受影响(planner 在 `Initialize` 时调用,不在运行中调用)。
|
||
|
||
### IDataService(通过 `ScenarioManager.DataService` 访问)
|
||
|
||
7 类基础数据,每类 4 个方法(`GetAll*` / `Get*(id)` / `Save*(spec)` / `Delete*(id)`):
|
||
|
||
| 基础数据类型 | 方法前缀 | 模型类 |
|
||
|---|---|---|
|
||
| 弹药 | `Ammo` | `AmmunitionSpec` |
|
||
| 火力单元 | `FireUnit` | `FireUnitSpec` |
|
||
| 无人机 | `Drone` | `DroneSpec` |
|
||
| 传感器 | `Sensor` | `SensorSpec` |
|
||
| 环境 | `Environment` | `EnvironmentSpec` |
|
||
| 编队 | `Formation` | `FormationTemplate` |
|
||
| 航线 | `Route` | `RouteTemplate` |
|
||
|
||
```csharp
|
||
List<DroneSpec> GetAllDrones();
|
||
DroneSpec GetDrone(string id);
|
||
void SaveDrone(DroneSpec spec);
|
||
void DeleteDrone(string id);
|
||
// 其余 6 类签名相同,替换前缀即可
|
||
```
|
||
|
||
### SimulationRunner
|
||
|
||
```csharp
|
||
public FrameDataStore FrameStore { get; }
|
||
public SimulationEngine Engine { get; } // 核心引擎
|
||
public IDataService DataService { get; set; }
|
||
|
||
public void LoadAndStart(string scenarioId);
|
||
public void Stop();
|
||
```
|
||
|
||
通过 `runner.Engine` 访问的成员:
|
||
|
||
```csharp
|
||
// ── 状态 ──
|
||
runner.Engine.State // SimulationState: Idle/Running/Paused/Stopped/Completed
|
||
runner.Engine.TimeScale // float,时间倍率(默认 1,设 4 = 4 倍速)
|
||
runner.Engine.SimulationTime // float,仿真累计时间(秒)
|
||
runner.Engine.FrameIndex // int,当前帧序号
|
||
runner.Engine.RecordFrames // bool,是否录制帧数据(回放用),默认 true
|
||
|
||
// ── 实体列表(IReadOnlyList,只读) ──
|
||
runner.Engine.Drones // IReadOnlyList<DroneEntity>
|
||
runner.Engine.Clouds // IReadOnlyList<CloudEntity>
|
||
runner.Engine.Munitions // IReadOnlyList<MunitionEntity>
|
||
runner.Engine.Platforms // IReadOnlyList<PlatformEntity>
|
||
runner.Engine.DetectionEntities // IReadOnlyList<DetectionEntity>
|
||
runner.Engine.Events // IReadOnlyList<SimEvent>(仿真期间持续追加)
|
||
|
||
// ── 方法 ──
|
||
runner.Engine.Tick(float dt) // → SimulationFrameResult(推进一帧)
|
||
runner.Engine.Pause() // Running → Paused
|
||
runner.Engine.Resume() // Paused → Running
|
||
runner.Engine.Stop() // → Stopped + Flush 帧数据到数据库
|
||
|
||
// ── 事件(Action 委托) ──
|
||
runner.Engine.OnMunitionLaunched // Action<MunitionEntity>
|
||
runner.Engine.OnCloudGenerated // Action<CloudEntity>
|
||
runner.Engine.OnDroneDestroyed // Action<DroneEntity>
|
||
runner.Engine.OnDroneReachedTarget // Action<DroneEntity>
|
||
runner.Engine.OnZoneIntruded // Action<DroneEntity, ControlZoneEntity>
|
||
runner.Engine.OnTargetDetected // Action<DroneEntity, DetectionEntity>
|
||
runner.Engine.OnSimulationEnded // Action
|
||
```
|
||
|
||
### ReportManager
|
||
|
||
```csharp
|
||
public IReportService Service { get; }
|
||
|
||
public SimulationReport Generate(string scenarioId, ScenarioConfig cfg,
|
||
List<SimEvent> events, string status, float duration);
|
||
public SimulationReport Get(string id);
|
||
public void Delete(string id);
|
||
public PagedResult<SimulationReport> Search(string kw, string from, string to, int page, int size);
|
||
|
||
public byte[] ExportReport(string reportId, string format); // "pdf" | "md"
|
||
public string Export(string reportId, string outputDir, string format); // "pdf" | "md"
|
||
public string Export(string reportId); // 默认 MD 到 reports 目录
|
||
```
|
||
|
||
### ReplayController
|
||
|
||
```csharp
|
||
public int TotalFrames { get; }
|
||
public int CurrentFrameIndex { get; }
|
||
public List<SimFrameRecord> CurrentFrames { get; }
|
||
|
||
public void LoadReplay(string scenarioId, FrameDataStore frameStore = null);
|
||
public List<SimFrameRecord> GetFrame(int frameIndex);
|
||
```
|
||
|
||
> `LoadReplay` 优先用内存帧数据(仿真刚结束),无则从 SQLite 帧库加载(历史回放)。
|
||
|
||
### ModelManager
|
||
|
||
```csharp
|
||
public IModelService Service { get; }
|
||
|
||
public ModelInfo Import(string filePath, string name);
|
||
public ModelInfo Import(string filePath, string name, int entityType, string desc);
|
||
public ModelInfo Add(ModelInfo model);
|
||
public ModelInfo UpdateModel(ModelInfo model);
|
||
public void Delete(string id);
|
||
public List<ModelInfo> GetAll();
|
||
public ModelInfo Get(string id);
|
||
```
|
||
|
||
---
|
||
|
||
## 六、枚举值清单
|
||
|
||
### 6.1 有官方中文翻译的枚举(GetEnums() 返回)
|
||
|
||
这 13 个枚举通过 `scenario.GetEnums()` 获取中英文对照,可直接用于下拉框:
|
||
|
||
```csharp
|
||
var enums = scenario.GetEnums();
|
||
// enums.DroneType, enums.PowerType, enums.PlatformType, enums.AerosolType,
|
||
// enums.WeatherType, enums.WindDirection, enums.SceneType, enums.FormationMode,
|
||
// enums.TriggerMode, enums.ReleaseMode, enums.EquipmentRole, enums.EntityType,
|
||
// enums.SensorType
|
||
```
|
||
|
||
| 枚举 | 成员 = 值 | 中文 |
|
||
|------|----------|------|
|
||
| **DroneType** | Rotor=0, FixedWing=1, HighSpeed=2 | 旋翼/固定翼/高速目标 |
|
||
| **PowerType** | Electric=0, Piston=1, Jet=2 | 电推/活塞/喷气 |
|
||
| **PlatformType** | AirBased=0, GroundBased=1 | 空基/地基 |
|
||
| **AerosolType** | InertGas=0, ActiveMaterial=1, ActiveFuel=2 | 惰性气体(吸入式灭火)/活性材料(爆燃式)/活性燃料(吸入式爆炸) |
|
||
| **WeatherType** | Sunny=0, Overcast=1, Fog=2, Rain=3, Night=4 | 晴/阴/雾/雨/夜 |
|
||
| **WindDirection** | N=0, NE=1, E=2, SE=3, S=4, SW=5, W=6, NW=7 | 北/东北/东/东南/南/西南/西/西北 |
|
||
| **SceneType** | Urban=0, Plain=1, Mountain=2, Coast=3 | 城市/平原/山区/海岸 |
|
||
| **FormationMode** | Single=0, Formation=1, Swarm=2 | 单机/编队/蜂群 |
|
||
| **TriggerMode** | Time=0, Area=1, Manual=2 | 时间触发/区域触发/手动触发 |
|
||
| **ReleaseMode** | Single=0, Continuous=1, Pulse=2 | 单次齐射/连续释放/脉冲释放 |
|
||
| **EquipmentRole** | Detection=0, LaunchPlatform=1 | 探测设备/发射平台 |
|
||
| **EntityType** | Drone=0, Platform=1, DetectionEquip=2, Cloud=3, Munition=4 | 无人机/发射平台/探测设备/云团/弹药 |
|
||
| **SensorType** | Radar=0, EO=1, IR=2 | 雷达/光电/红外 |
|
||
|
||
### 6.2 无官方翻译的枚举(前端需自行映射中文)
|
||
|
||
| 枚举 | 命名空间 | 成员 = 值 | 含义 |
|
||
|------|---------|----------|------|
|
||
| **SimulationState** | `Simulation` | Idle=0, Running=1, Paused=2, Stopped=3, Completed=4 | 空闲/运行/暂停/停止/完成 |
|
||
| **DroneStatus** | `Simulation` | Flying=0, Destroyed=1, ReachedTarget=2, ZoneIntruded=3 | 飞行中/已摧毁/到达目标/侵入管控区 |
|
||
| **PlatformState** | `Simulation` | Idle=0, FlyingToTarget=1, ReadyToRelease=2 | 空闲/飞向目标/准备投放 |
|
||
| **SimEventType** | `Models` | TargetDetected=0, MunitionLaunched=1, CloudGenerated=2, DroneEnteredCloud=3, DroneDestroyed=4, DroneReachedTarget=5, ZoneIntruded=6, WaypointReached=7, SimulationEnd=8, PlanningFailed=9 | 目标发现/弹药发射/云团生成/进入云团/摧毁/到达目标/侵入管控区/到达航点/仿真结束/规划失败 |
|
||
| **InterceptResult** | `Models` | Success=0, Partial=1, Failed=2 | 成功拦截/部分拦截/拦截失败 |
|
||
| **DamageStage** | `Models` | Normal=0, EngineAnomaly=1, AttitudeLoss=2, Destroyed=3 | 正常/引擎异常/姿态丧失/摧毁 |
|
||
| **ScenarioStatus** | `Models` | Draft=0, Configuring=1, Completed=2 | 草稿/配置中/已完成 |
|
||
|
||
> **EntitySnapshot.EntityType** 用的是 `EntityType` 枚举(int),判断实体类型时用 `(EntityType)snap.EntityType` 或直接比较 int 值。
|
||
|
||
---
|
||
|
||
## 七、关键数据结构
|
||
|
||
### EntitySnapshot(每帧推送)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `EntityId` | string | 实体唯一 ID(属性) |
|
||
| `EntityType` | EntityType | Drone=0/Platform=1/DetectionEquip=2/Cloud=3/Munition=4(属性) |
|
||
| `PosX/Y/Z` | float | 三维位置(Y=高度,米) |
|
||
| `RotX/Y/Z` | float | 旋转 |
|
||
| `VelX/Y/Z` | float | 瞬时速度 (m/s) |
|
||
| `Hp` | float | 无人机血量 (0~1) |
|
||
| `DamageStage` | int | 毁伤阶段(0正常/1引擎异常/2姿态丧失/3摧毁) |
|
||
| `PlatformStateStr` | string? | 平台状态:Idle/FlyingToTarget/ReadyToRelease |
|
||
| `CloudRadius` | float | 云团有效半径(米) |
|
||
| `CloudOpacity` | float | 不透明度 (0~1) |
|
||
| `CloudPhase` | int | 扩散阶段 (1/2/3) |
|
||
| `CloudElapsed` | float | 云团已存在时间 (s) |
|
||
| `ModelId` | string? | 3D 模型 ID(Unity 实例化用) |
|
||
|
||
> 除 `EntityId`/`EntityType` 是属性外,其余均为**公共字段**(非属性)。
|
||
|
||
### SimEvent(仿真事件)
|
||
|
||
```csharp
|
||
public class SimEvent
|
||
{
|
||
public SimEventType Type { get; set; } // 事件类型(见枚举表)
|
||
public float OccurredAt { get; set; } // 发生时刻(仿真秒)
|
||
public string SourceId { get; set; } // 触发实体 ID
|
||
public string TargetId { get; set; } // 目标实体 ID
|
||
public string DataJson { get; set; } // 扩展数据(JSON)
|
||
public string Description { get; set; } // 人类可读描述
|
||
}
|
||
```
|
||
|
||
### SimulationFrameResult(Tick 返回值)
|
||
|
||
```csharp
|
||
public class SimulationFrameResult
|
||
{
|
||
public List<EntitySnapshot> EntitySnapshots { get; set; } // 本帧所有实体快照
|
||
public List<SimEvent> NewEvents { get; set; } // 本帧新事件
|
||
public SimulationState State { get; set; } // 当前仿真状态
|
||
public int FrameIndex { get; set; } // 帧序号
|
||
public float SimulationTime { get; set; } // 仿真累计时间
|
||
}
|
||
```
|
||
|
||
### PagedResult<T>(分页查询返回值)
|
||
|
||
```csharp
|
||
public class PagedResult<T>
|
||
{
|
||
public List<T> Items { get; set; } // 当前页数据
|
||
public int TotalCount { get; set; } // 总记录数
|
||
public int Page { get; set; } // 当前页码(从 1 开始)
|
||
public int PageSize { get; set; } // 每页条数
|
||
public int TotalPages { get; } // 总页数(计算属性)
|
||
}
|
||
```
|
||
|
||
### EnumMetadata / EnumItem(GetEnums 返回值)
|
||
|
||
```csharp
|
||
public class EnumItem
|
||
{
|
||
public string Name { get; set; } // 英文名
|
||
public string ChineseName { get; set; } // 中文名
|
||
public int Value { get; set; } // 枚举值
|
||
}
|
||
|
||
public class EnumMetadata
|
||
{
|
||
public List<EnumItem> DroneType { get; set; }
|
||
public List<EnumItem> PowerType { get; set; }
|
||
public List<EnumItem> PlatformType { get; set; }
|
||
public List<EnumItem> AerosolType { get; set; }
|
||
public List<EnumItem> WeatherType { get; set; }
|
||
public List<EnumItem> WindDirection { get; set; }
|
||
public List<EnumItem> SceneType { get; set; }
|
||
public List<EnumItem> FormationMode { get; set; }
|
||
public List<EnumItem> TriggerMode { get; set; }
|
||
public List<EnumItem> ReleaseMode { get; set; }
|
||
public List<EnumItem> EquipmentRole { get; set; }
|
||
public List<EnumItem> EntityType { get; set; }
|
||
public List<EnumItem> SensorType { get; set; }
|
||
}
|
||
```
|
||
|
||
### SimulationReport
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 报告 ID(主键) |
|
||
| `ScenarioId` | string | 想定 ID |
|
||
| `ScenarioName` | string | 想定名称 |
|
||
| `ScenarioNumber` | string | 想定编号 |
|
||
| `CompletedAt` | string | 完成时间(UTC ISO 8601) |
|
||
| `DroneCount` | int | 无人机总数 |
|
||
| `UnitCount` | int | 装备总数 |
|
||
| `InterceptResult` | int | 拦截结果(0成功/1部分/2失败) |
|
||
| `Content` | string | Markdown 报告文本(快速展示用) |
|
||
| `ReportDataJson` | string? | 结构化数据 JSON(PDF 导出用) |
|
||
|
||
### DefenseRecommendation(防御推荐方案)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Success` | bool | 是否规划成功 |
|
||
| `Summary` | string | 方案摘要(失败时含原因) |
|
||
| `Best` | RecommendOption | 最佳推荐参数 |
|
||
|
||
### RecommendOption(推荐参数)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `PosX/Y/Z` | double | 推荐抛撒位置(Y=高度,米) |
|
||
| `Timing` | double | 推荐抛撒时机(仿真秒) |
|
||
| `SalvoRounds` | int | 推荐弹药数(齐射发数) |
|
||
| `SalvoSpacing` | double | 云团展开间距(米) |
|
||
| `EstimatedProbability` | double | 估计拦截概率(0~1) |
|
||
| `ThreatsEngaged` | int | 已拦截威胁数 |
|
||
| `ThreatsUnengaged` | int | 未拦截威胁数 |
|
||
|
||
---
|
||
|
||
## 八、运行时实体属性
|
||
|
||
仿真运行时通过 `runner.Engine.Drones` / `Clouds` / `Munitions` / `Platforms` / `DetectionEntities` 直接访问。
|
||
|
||
| 实体 | 关键属性 |
|
||
|------|---------|
|
||
| **DroneEntity** | Id, PosX/Y/Z, Hp, Status(DroneStatus), DroneType, PowerType, Wingspan, CruiseSpeed, Route, TraveledArc, TotalArc, Progress, ModelId |
|
||
| **CloudEntity** | Id, PosX/Y/Z, Radius, Density, Phase(1/2/3), Elapsed, IsDissipated, AerosolType |
|
||
| **MunitionEntity** | Id, PosX/Y/Z, Velocity(Vx,Vy,Vz), StartX/Y/Z, LaunchTime, ElapsedTime, LaunchAngle, Azimuth, MuzzleVelocity, FlightDuration, TargetX/Y/Z, HasArrived |
|
||
| **PlatformEntity** | Id, PosX/Y/Z, CurrentVelocity, State(PlatformState), MunitionCount, CooldownRemaining, MuzzleVelocity, CruiseSpeed, ReleaseAltitude, TargetX/Y/Z, FlightDistance, Ready, CanRelease |
|
||
| **DetectionEntity** | Id, PosX/Y/Z, Source, IsInRange(x,y,z,visibility,out range), IsDetected(droneId), ModelId |
|
||
| **ControlZoneEntity** | Id, Name, Vertices(List\<Vector3\>), MinAltitude, MaxAltitude, ContainsPoint(x,y,z) |
|
||
|
||
---
|
||
|
||
## 九、核心模型完整字段
|
||
|
||
### 9.1 ScenarioConfig(想定配置聚合根 — GetDetail 返回值)
|
||
|
||
```
|
||
ScenarioConfig
|
||
Info: Scenario // 想定主表
|
||
Scene: CombatScene // 步骤1:作战环境
|
||
ControlZones: List<ControlZone> // 步骤1:管控区域
|
||
Drones: List<ScenarioDrone> // 步骤2:威胁目标
|
||
Units: List<ScenarioUnit> // 步骤3:我方部署(含探测+发射平台)
|
||
Cloud: CloudDispersal // 步骤4:云团抛撒配置
|
||
Routes: List<RoutePlan> // 步骤5:航路规划(多批次)
|
||
WaypointGroups: Dictionary<string, List<Waypoint>> // 按 WaveId 分组的航路点
|
||
```
|
||
|
||
### 9.2 Scenario(想定主表)
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `Id` | string | GUID | 主键 |
|
||
| `Name` | string | "" | 想定名称 |
|
||
| `ScenarioNumber` | string | "" | 想定编号(唯一) |
|
||
| `Description` | string | "" | 描述 |
|
||
| `Status` | int | 0 | 0=草稿 1=配置中 2=已完成 |
|
||
| `CurrentStep` | int | 1 | 当前配置步骤(1~5) |
|
||
| `TickRate` | int | 20 | 仿真帧率 |
|
||
| `CreatedAt` | string | UTC ISO | 创建时间 |
|
||
| `UpdatedAt` | string | UTC ISO | 更新时间 |
|
||
|
||
### 9.3 CombatScene(步骤 1:作战环境)
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `ScenarioId` | string | "" | 主键 = 想定 ID |
|
||
| `SceneType` | int | 1(Plain) | 0=城市 1=平原 2=山区 3=海岸 |
|
||
| `TimeOfDay` | string | "12:00" | 时间段 |
|
||
| `WeatherType` | int | 0(Sunny) | 0=晴 1=阴 2=雾 3=雨 4=夜 |
|
||
| `WindSpeed` | double | 5.0 | 风速 m/s |
|
||
| `WindDirection` | int | 0(N) | 0~7 = N/NE/E/SE/S/SW/W/NW |
|
||
| `Temperature` | double | 20.0 | 温度 °C |
|
||
| `Humidity` | double | 60.0 | 湿度 %RH |
|
||
| `Pressure` | double | 1013.0 | 气压 hPa |
|
||
| `Visibility` | double | 5000.0 | 能见度 m |
|
||
| `SceneWidth` | double | 4000.0 | 场景宽 m |
|
||
| `SceneLength` | double | 10000.0 | 场景长 m |
|
||
| `SceneHeight` | double | 1000.0 | 场景高 m |
|
||
|
||
### 9.4 ControlZone(管控区域)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `ScenarioId` | string | 想定 ID |
|
||
| `Name` | string | 区域名称 |
|
||
| `VerticesJson` | string | 多边形顶点 JSON:`[{"x":0,"y":0,"z":0},...]` |
|
||
| `MinAltitude` | double | 高度下限 m |
|
||
| `MaxAltitude` | double | 高度上限 m |
|
||
| `OrderIndex` | int | 排序序号 |
|
||
|
||
### 9.5 ScenarioDrone(步骤 2:威胁目标)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `ScenarioId` | string | 想定 ID |
|
||
| `DroneSpecId` | string | FK → DroneSpec |
|
||
| `WaveId` | string | 批次 ID(如 "w1") |
|
||
| `Quantity` | int | 数量 |
|
||
|
||
### 9.6 ScenarioUnit(步骤 3:我方部署)
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `Id` | string | GUID | 主键 |
|
||
| `ScenarioId` | string | "" | 想定 ID |
|
||
| `EquipmentRole` | int | 1 | 0=探测设备 1=发射平台 |
|
||
| `LaunchPlatformSpecId` | string | "" | FK → LaunchPlatformSpec(发射平台时填) |
|
||
| `SensorSpecId` | string | "" | FK → SensorSpec(探测设备时填) |
|
||
| `Quantity` | int | 1 | 数量 |
|
||
| `PositionX/Y/Z` | double | 0 | 部署位置(Y=高度,米) |
|
||
| `AerosolType` | int? | null | 挂载弹药类型(0/1/2) |
|
||
| `AmmunitionSpecId` | string | "" | FK → AmmunitionSpec(挂载的弹药规格,前端配置用) |
|
||
| `MunitionCount` | int? | null | 弹药数量 |
|
||
| `WaveId` | string | "" | 关联批次 |
|
||
| `Description` | string | "" | 备注 |
|
||
| `Source` | int | 0 | 0=手动 1=算法推荐 |
|
||
|
||
### 9.7 CloudDispersal(步骤 4:云团抛撒配置)
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `ScenarioId` | string | "" | 主键 = 想定 ID |
|
||
| `AerosolType` | int | 0 | 0=惰性气体 1=活性材料 2=活性燃料 |
|
||
| `DisperseHeight` | double | 300.0 | 抛撒高度 m |
|
||
| `TriggerMode` | int | 0 | 0=时间 1=区域 2=手动 |
|
||
| `SpreadAngle` | double | 0 | 扩散方向 ° |
|
||
| `ReleaseMode` | int | 0 | 0=单次 1=连续 2=脉冲 |
|
||
| `InitialScale` | double | 1000.0 | 初始规模 m³ |
|
||
| `Duration` | double | 60.0 | 持续时间 s |
|
||
| `ReleaseInterval` | double | 5.0 | 释放间隔 s |
|
||
| `TotalAmount` | double | 50.0 | 释放总量 kg |
|
||
| `PositionX/Y/Z` | double | 0 | 抛撒位置 |
|
||
| `PositionMode` | int | 1 | 0=点选 1=手动输入 2=算法推荐 |
|
||
| `Source` | string | "Manual" | "Manual" 或 "Algorithm" |
|
||
| `SalvoRounds` | int | 0 | 推荐弹药数(算法填充) |
|
||
| `SalvoSpacing` | double | 0 | 云团间距 m(算法填充) |
|
||
| `EstimatedProbability` | double? | null | 算法估计拦截概率 |
|
||
| `RecommendedTiming` | double? | null | 推荐抛撒时机 s |
|
||
| `RecommendedPosX/Y/Z` | double? | null | 推荐抛撒位置 |
|
||
| `CriticalPosX/Y/Z` | double? | null | 关键拦截位置 |
|
||
| `CriticalTiming` | double? | null | 关键拦截时机 s |
|
||
|
||
### 9.8 RoutePlan(步骤 5:航路规划)
|
||
|
||
| 字段 | 类型 | 默认值 | 说明 |
|
||
|------|------|--------|------|
|
||
| `Id` | string | GUID | 主键 |
|
||
| `ScenarioId` | string | "" | 想定 ID |
|
||
| `WaveId` | string | "" | 批次 ID |
|
||
| `FormationMode` | int | 0 | 0=单机 1=编队 2=蜂群 |
|
||
| `LateralSpacing` | double | 50.0 | 横向间距 m |
|
||
| `LateralCount` | int? | null | 横向架数(null=全部) |
|
||
| `LongitudinalCount` | int? | null | 纵深架数(null=1) |
|
||
| `LongitudinalSpacing` | double | 50.0 | 纵向间距 m |
|
||
| `LateralAxis` | int | 2 | 横向展开轴:0=X 1=Y(垂直) 2=Z(默认) |
|
||
| `LongitudinalAxis` | int | 0 | 纵向串列轴:0=X(默认) 1=Y 2=Z |
|
||
| `ETA` | string | "" | 预计到达时间 |
|
||
|
||
### 9.9 Waypoint(航路点)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `ScenarioId` | string | 想定 ID |
|
||
| `WaveId` | string | 批次 ID |
|
||
| `OrderIndex` | int | 顺序索引(从 0 开始) |
|
||
| `PosX` | double | X 坐标 m |
|
||
| `PosY` | double | Y 坐标 = 高度 m |
|
||
| `PosZ` | double | Z 坐标 m |
|
||
| `Altitude` | double | 高度 m(与 PosY 冗余) |
|
||
| `Speed` | double | 该段速度 **km/h** |
|
||
|
||
---
|
||
|
||
## 十、基础数据模型完整字段
|
||
|
||
### 10.1 DroneSpec(无人机模板)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `Name` | string | 名称 |
|
||
| `DroneType` | int | 0=旋翼 1=固定翼 2=高速 |
|
||
| `Model` | string | 型号名称 |
|
||
| `Description` | string | 描述 |
|
||
| `PowerType` | int | 0=电推 1=活塞 2=喷气 |
|
||
| `Wingspan` | double | 翼展 m |
|
||
| `TypicalSpeed` | double | 典型速度 km/h |
|
||
| `TypicalAltitude` | double | 典型高度 m |
|
||
| `ModelId` | string | 3D 模型 ID(FK → ModelInfo) |
|
||
|
||
### 10.2 LaunchPlatformSpec(发射平台模板)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `Name` | string | 名称 |
|
||
| `Description` | string | 描述 |
|
||
| `PlatformType` | int | 0=空基 1=地基 |
|
||
| `GunCount` | int | 火炮数量 |
|
||
| `ChannelsPerGun` | int | 每炮通道数 |
|
||
| `ChannelInterval` | double | 同通道发射间隔 s |
|
||
| `Cooldown` | double | 射击冷却 s |
|
||
| `AmmoChangeTime` | double | 换弹时间 s |
|
||
| `MuzzleVelocity` | double | 初速 m/s |
|
||
| `CruiseSpeed` | double | 巡航速度 m/s(空基) |
|
||
| `ReleaseAltitude` | double | 释放高度 m(空基) |
|
||
| `ModelId` | string | 3D 模型 ID |
|
||
|
||
### 10.3 SensorSpec(传感器模板)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `Name` | string | 名称 |
|
||
| `RadarRange` | double | 雷达探测距离 m(0=无) |
|
||
| `EORange` | double | 光电探测距离 m |
|
||
| `IRRange` | double | 红外探测距离 m |
|
||
| `HasRadar` | bool | 是否含雷达探测能力(由 RadarRange>0 派生) |
|
||
| `HasEO` | bool | 是否含光电探测能力(由 EORange>0 派生) |
|
||
| `HasIR` | bool | 是否含红外探测能力(由 IRRange>0 派生) |
|
||
| `Accuracy` | double | 探测精度(位置误差 m) |
|
||
| `MinElevation` | double? | 最小仰角 |
|
||
| `MaxElevation` | double? | 最大仰角 |
|
||
| `MinDetectAlt` | double? | 最小可探测高度 m |
|
||
| `MaxDetectAlt` | double? | 最大可探测高度 m |
|
||
| `ModelId` | string | 3D 模型 ID |
|
||
|
||
### 10.4 AmmunitionSpec(弹药模板)
|
||
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| `Id` | string | 主键 |
|
||
| `AerosolType` | int | 0=惰性气体 1=活性材料 2=活性燃料 |
|
||
| `Name` | string | 名称 |
|
||
| `InitialRadius` | double | 初始半径 m |
|
||
| `InitialVolume` | double | 初始体积 m³ |
|
||
| `CoreDensity` | double | 核心密度 |
|
||
| `EdgeDensity` | double | 边缘密度 |
|
||
| `InitialTemperature` | double | 初始温度 |
|
||
| `BuoyancyFactor` | double | 浮力系数 |
|
||
| `EffectiveConcentration` | double | 有效浓度 |
|
||
| `SourceStrength` | double | 源强 Q (kg) |
|
||
| `DispersionRateBase` | double | 基础扩散速率 m/s |
|
||
| `BurstChargeKg` | double | 爆发药 TNT 当量 kg |
|
||
| `TurbulentExpansionK` | double | 湍流扩散系数 |
|
||
| `Phase2Duration` | double | Phase 2 持续时间 s |
|
||
| `MaxRadius` | double | 最大半径 m |
|
||
| `MaxDuration` | double | 最大持续时间 s |
|
||
| `ParticlesJson` | string | 粒子渲染参数 JSON |
|
||
|
||
### 10.5 EnvironmentSpec / FormationTemplate / RouteTemplate / ModelInfo
|
||
|
||
| 模型 | 关键字段 |
|
||
|------|---------|
|
||
| **EnvironmentSpec** | Id, Name, WeatherType, WindSpeed, WindDirection, Temperature, Humidity, Pressure, Visibility |
|
||
| **FormationTemplate** | Id, Name, FormationMode, LateralCount, LongitudinalCount, LateralSpacing, LongitudinalSpacing, LateralAxis, LongitudinalAxis |
|
||
| **RouteTemplate** | Id, Name, WaypointsJson(`[{"x":0,"y":0,"z":0},...]`) |
|
||
| **ModelInfo** | Id, Name, EntityType(0=Drone/1=Platform/2=DetectionEquip), Description, FilePath, FileSize, PreviewPath, HasHighResTexture, CreatedAt |
|
||
|
||
---
|
||
|
||
## 十一、默认数据
|
||
|
||
首次运行自动种子,含 6 个 `[Demo]` 预设想定:
|
||
|
||
| 类别 | 示例 ID |
|
||
|------|---------|
|
||
| 弹药 | `inert` / `active` / `fuel` |
|
||
| 编队 | `single` / `line-3` / `swarm-10` |
|
||
| 航线 | `5km-h500` / `10km-h500` / `20km-h500` |
|
||
| 火力单元 | `ground-light` / `air-standard` |
|
||
| 无人机 | `shahed` / `quadcopter` / `cruise-missile` |
|
||
| 传感器 | `radar-mr` / `eo-station` |
|
||
| 环境 | `sunny-calm` / `fog` / `night` |
|
||
|
||
---
|
||
|
||
## 十二、参考
|
||
|
||
| 文档 | 位置 |
|
||
|------|------|
|
||
| 架构设计 | `docs/design/architecture/总体架构设计.md` |
|
||
| 实体事件映射 | `docs/design/technical/仿真器实体与事件映射.md` |
|
||
| 测试状态 | **270 测试,14 秒(全部通过)** |
|