新增: - 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 编译通过
39 KiB
后端对接文档(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
# 方式 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 部署 DLL、脚本和 StreamingAssets 资源
- 创建空 GameObject,挂
SimulationBootstrap - 运行 — 自动种子数据库,选一个
[Demo]想定,启动仿真
SimulationBootstrap是参考模板,展示预设模式(一行代码)和自定义模式两种路径。Inspector 勾选_usePreset切换。
三、完整工作流(5 步)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌──────────┐ ┌──────────┐
│ 基础数据 CRUD │ → │ 创建想定 │ → │ 运行仿真 │ → │ 生成报告 │ → │ 回放 │
│ DataService │ │ ScenarioMgr │ │ SimRunner │ │ ReportMgr │ │ Replay │
└─────────────┘ └─────────────┘ └─────────────┘ └──────────┘ └──────────┘
3.1 管理基础数据
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 创建想定
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 运行仿真
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 生成报告
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 回放
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() 每帧执行:
- 调用
engine.Tick(Time.deltaTime)→ 获取SimulationFrameResult - 遍历
result.EntitySnapshots:- 新实体(EntityId 未见过)→ Instantiate prefab
- 已有实体 → 更新
transform.position - Cloud 类型 → 更新
localScale(按CloudRadius)和材质 alpha(按CloudOpacity)
- 遍历
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 中的相机设置(可供参考):
// 俯瞰视角
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
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);
防御推荐用法("一键应用"功能):
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:
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 修改配置(推荐)
var cfg = GetComponent<ScenarioManager>().Config;
// 读当前 planner 配置
string json = cfg.GetPlannerConfigJson();
// 修改后保存 — 自动重载,planner 立即用新参数
cfg.SavePlannerConfig(modifiedJson);
// 修改 defaults.json — 自动重载,数据库 InsertOrReplace 覆盖同 Id 记录
cfg.SaveDefaults(modifiedDefaultsJson);
用法 2:直接改文件后通知后端重载
// 前端直接修改 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 |
List<DroneSpec> GetAllDrones();
DroneSpec GetDrone(string id);
void SaveDrone(DroneSpec spec);
void DeleteDrone(string id);
// 其余 6 类签名相同,替换前缀即可
SimulationRunner
public FrameDataStore FrameStore { get; }
public SimulationEngine Engine { get; } // 核心引擎
public IDataService DataService { get; set; }
public void LoadAndStart(string scenarioId);
public void Stop();
通过 runner.Engine 访问的成员:
// ── 状态 ──
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
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
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
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() 获取中英文对照,可直接用于下拉框:
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(仿真事件)
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 返回值)
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>(分页查询返回值)
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 返回值)
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 秒(全部通过) |