From 202e5ee1174185be23101e6dbe8d3c14bd8ae683 Mon Sep 17 00:00:00 2001 From: tian <11429339@qq.com> Date: Fri, 12 Jun 2026 12:36:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E6=96=87=E6=A1=A3=E6=9B=B4?= =?UTF-8?q?=E6=96=B0:=20=E4=BA=8B=E4=BB=B6=E9=A9=B1=E5=8A=A8API=20+=20Fire?= =?UTF-8?q?Schedule=20+=20=E9=BB=98=E8=AE=A4=E5=BC=B9=E8=8D=AF=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/对接文档_Unity前端.md | 209 ++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 109 deletions(-) diff --git a/docs/对接文档_Unity前端.md b/docs/对接文档_Unity前端.md index 707c0b6..6f1e992 100644 --- a/docs/对接文档_Unity前端.md +++ b/docs/对接文档_Unity前端.md @@ -1,175 +1,166 @@ # 后端对接文档(Unity 前端) -> **版本**:V1.0 -> **日期**:2026-06-11 +> **版本**:V1.1 +> **日期**:2026-06-12 > **Unity 版本**:2022.3.62f3c1 --- ## 一、交付物 -前端同学从项目仓库取以下两个目录,拖入自己的 Unity 项目: +从仓库取以下内容,拖入 Unity 项目: ``` -src/Unity/Assets/Plugins/ ← 16 个 DLL,零配置,拖入即用 -src/Unity/Assets/Scripts/Managers/ ← 6 个 C# 桥接脚本 +src/Unity/Assets/Plugins/ ← 16 个 DLL(Core + sqlite + JSON) +src/Unity/Assets/Scripts/Managers/ ← 桥接脚本 +data/default_ammo.json ← 默认弹药参数(放到 persistentDataPath 下) ``` -> 不要改 DLL,以后更新时替换即可。Manager 脚本可以按需修改。 - --- ## 二、快速验证 -1. 拖入上述两个目录后,等 Unity 编译完成 -2. 创建一个空 GameObject,挂 `ManagerVerification` 组件 +1. 拖入上述目录,等 Unity 编译 +2. 创建空 GameObject,挂 `ManagerVerification` 3. Inspector 右键 → `Run Full Verification` -4. Console 看到 7 行 `OK` 即表示集成成功 +4. Console 看到 7 行 OK --- -## 三、Manager API +## 三、核心流程 -所有 Manager 都是 `MonoBehaviour`,挂到场景即可用。建议做成 Singleton。 - -### ModelManager — 模型管理 +### 3.1 创建想定 & 获取推荐方案 ```csharp -var mgr = GetComponent(); +var scenario = GetComponent(); +var task = scenario.CreateTask("拦截活塞式无人机", ""); +scenario.SaveScene(task.Id, new CombatScene { WindSpeed = 3 }); +scenario.SaveTarget(task.Id, new TargetConfig { PowerType = (int)PowerType.Piston, ... }); +scenario.SaveRoute(task.Id, routePlan, waypoints); -// 导入模型 -ModelInfo model = mgr.Import("C:/models/drone.fbx", "旋翼无人机"); -// 支持的格式: .fbx .obj .stl .glb .gltf(≤500MB) +// 推荐方案(自动从数据库读弹药规格) +var detail = scenario.GetDetail(task.Id); +var ammoCatalog = db.Table().ToList(); // DatabaseManager 已种子 +var rec = new DefaultDefenseAdvisor(ammoCatalog).Recommend(new ThreatProfile { ... }); -// 查询 -List all = mgr.GetAll(); -ModelInfo one = mgr.Get("model-id"); - -// 删除 -mgr.Delete("model-id"); +// 应用到想定 +scenario.SaveCloud(task.Id, rec.Best.RecommendedCloud); +scenario.SaveDeployment(task.Id, rec.Best.Platforms.Select(p => new EquipmentDeployment { ... }).ToList()); ``` -### ScenarioManager — 想定管理 - -```csharp -var mgr = GetComponent(); - -// 创建任务 -SimTask task = mgr.CreateTask("城市防御演习", ""); // 空字符串 = 自动编号 - -// 5 步配置 -mgr.SaveScene(task.Id, new CombatScene { WindSpeed = 5, ... }); -mgr.SaveTarget(task.Id, new TargetConfig { Quantity = 3, ... }); -mgr.SaveDeployment(task.Id, new List { ... }); -mgr.SaveCloud(task.Id, new CloudDispersal { AerosolType = ..., ... }); -mgr.SaveRoute(task.Id, new RoutePlan { ... }, waypointList); - -// 算法推荐(需要先填充弹药库 AmmunitionSpec) -var advisor = new DefaultDefenseAdvisor(ammoCatalog); -var rec = advisor.Recommend(threatProfile); -// rec.Best.RecommendedCloud → 云团参数 -// rec.Best.Platforms → 搭载平台部署方案 -// rec.Best.InterceptProbability → 拦截概率 0~1 - -// 搜索 -var result = mgr.Search("关键词", "2026-01-01", "2026-12-31", page: 1, pageSize: 10); -``` - -### SimulationRunner — 仿真运行 +### 3.2 启动仿真(事件驱动) ```csharp var runner = GetComponent(); -// 加载想定并启动(需先配置好想定 + 云团的 RecommendedTiming) -runner.LoadAndStart(taskId); +// 推荐方案的 FireSchedule 直接传给引擎 +runner.Engine.SetFireSchedule(rec.Best.FireSchedule); +runner.LoadAndStart(task.Id); +runner.Engine.TimeScale = 4f; // 加速 -// 可选:加速 -runner.Engine.TimeScale = 4f; +// 订阅事件,不需要每帧遍历 NewEvents +runner.Engine.OnMunitionLaunched += m => Instantiate(shellPrefab, ToVector3(m.PosX, m.PosY, m.PosZ)); +runner.Engine.OnCloudGenerated += c => SpawnCloud(c.Dispersion.Center, c.Dispersion.Radius); +runner.Engine.OnDroneDestroyed += d => PlayExplosion(d.PosX, d.PosY, d.PosZ); +runner.Engine.OnDroneReachedTarget += d => ShowReached(d.PosX, d.PosY, d.PosZ); +runner.Engine.OnZoneIntruded += (d, z) => AlertIntrusion(z.Name); +runner.Engine.OnSimulationEnded += () => GenerateReport(); -// 每帧 Update -void Update() { - if (runner.Engine.State == SimulationState.Running) { - var result = runner.Engine.Tick(Time.deltaTime); - // result.EntitySnapshots → 所有实体位置,更新 3D GameObject - // result.NewEvents → 本帧事件 - } -} - -// 无人机位置 -runner.Engine.Drones[0].PosX / PosY / PosZ -runner.Engine.Drones[0].Status // Flying / Destroyed / ReachedTarget -runner.Engine.Drones[0].Hp // 0~1 - -// 云团 -runner.Engine.Clouds[i].Dispersion.Center / Radius / CoreDensity +// 不需要手动 Tick —— SimulationBootstrap 已封装好了 ``` -### ReportManager — 报告 +### 3.3 仿真事件一览 + +| 事件 | 参数 | 触发时机 | +|------|------|------| +| `OnMunitionLaunched` | `MunitionEntity` | 发射计划时间到达 | +| `OnCloudGenerated` | `CloudEntity` | 弹药到达释放高度 | +| `OnDroneDestroyed` | `DroneEntity` | HP ≤ 0 | +| `OnDroneReachedTarget` | `DroneEntity` | 到达最后航路点 | +| `OnZoneIntruded` | `DroneEntity`, `ControlZoneEntity` | 进入管控区 | +| `OnSimulationEnded` | 无 | 所有无人机状态 ≠ Flying | + +--- + +## 四、Manager API + +### ScenarioManager + +```csharp +var mgr = GetComponent(); +SimTask task = mgr.CreateTask("任务名", ""); // 空字符串 = 自动编号 SIM-yyyyMMdd-xxx +mgr.SaveScene(id, combatScene); +mgr.SaveTarget(id, targetConfig); +mgr.SaveDeployment(id, equipmentList); +mgr.SaveCloud(id, cloudDispersal); +mgr.SaveRoute(id, routePlan, waypoints); +TaskFullConfig detail = mgr.GetDetail(id); +PagedResult result = mgr.Search("关键词", from, to, page, pageSize); +``` + +### SimulationRunner + +```csharp +var runner = GetComponent(); +runner.Engine.SetFireSchedule(fireEvents); // 从推荐方案取 +runner.LoadAndStart(taskId); +runner.Engine.TimeScale = 4f; +runner.Engine.State / Drones / Clouds / Munitions / Events +runner.Stop(); +``` + +### ReportManager ```csharp var mgr = GetComponent(); - -// 生成(仿真结束后) -var report = mgr.Generate(taskId, config, events, droneStatus, duration); - -// 导出 Markdown 文件 -string path = mgr.Export(report.Id); - -// 搜索 -var result = mgr.Search("关键词", null, null, 1, 10); +var config = scenario.GetDetail(taskId); +var report = mgr.Generate(taskId, config, runner.Engine.Events.ToList(), + runner.Engine.Drones[0].Status.ToString(), + runner.Engine.SimulationTime); +string path = mgr.Export(report.Id); // → persistentDataPath/reports/xxx.md ``` -### ReplayController — 回放 +### ReplayController ```csharp var replay = GetComponent(); - replay.LoadReplay(taskId); - -// 逐帧读取 -for (int i = 0; i < replay.TotalFrames; i++) { - var frame = replay.GetFrame(i); - // frame 是 List,包含该帧所有实体位置 -} +// replay.TotalFrames / replay.GetFrame(frameIndex) ``` --- -## 四、关键数据模型 +## 五、默认弹药 -| 模型 | 说明 | -|------|------| -| `SimTask` | 仿真任务(Id, Name, TaskNumber, Status, CurrentStep) | -| `CombatScene` | 作战场景(天气/风速/温度/时间) | -| `TargetConfig` | 目标配置(类型/数量/速度/动力) | -| `EquipmentDeployment` | 装备部署(探测/发射平台/弹药) | -| `CloudDispersal` | 云团抛撒配置(类型/位置/时机/规模) | -| `RoutePlan` + `Waypoint` | 航路规划 | -| `DefenseSolution` | 推荐方案(气溶胶选型/云团参数/平台部署/拦截概率) | -| `SimulationReport` | 仿真报告(含 Markdown 内容) | -| `SimFrameRecord` | 逐帧回放数据 | +首次运行 `DatabaseManager.OpenMainDb()` 会检查 `persistentDataPath/default_ammo.json`。如果存在且 `AmmunitionSpec` 表为空,自动导入。 -完整数据模型见 Core 源码 `Models/` 目录。 +当前默认参数(`data/default_ammo.json`): + +| 参数 | 惰性气体弹 | 活性材料弹 | 活性燃料弹 | +|------|------|------|------| +| 药剂质量 | 10 kg | 12 kg | 10 kg | +| 爆发药 TNT | 1.5 kg | 4.0 kg | 1.5 kg | +| 初始半径 R₀ | 3.75 m | 5.14 m | 3.75 m | +| 扩散模型 | 三阶段(爆轰→湍流→高斯) | | | --- -## 五、更新后端 - -当后端代码更新后: +## 六、更新后端 ```bash cd src/CounterDrone.Core dotnet publish -c Release -o ../../unity_plugins +# 覆盖 Assets/Plugins/CounterDrone.Core/ 下所有 DLL ``` -然后把 `unity_plugins/` 下的新 DLL 覆盖到 `Assets/Plugins/CounterDrone.Core/` 即可。Manager 脚本一般不需要改。 - --- -## 六、参考 +## 七、参考 | 文档 | 位置 | |------|------| | 架构设计 | `docs/design/architecture/总体架构设计.md` | +| 实体事件映射 | `docs/design/technical/仿真器实体与事件映射.md` | +| 任务跟踪 | `docs/implementation/tasks/实施计划与任务跟踪.md` | | 测试报告 | `test/reports/`(每次集成测试自动生成) | -| 测试状态 | 128 测试,95.4% 行覆盖率 | +| 测试状态 | **129 测试,95.4% 行覆盖率,12 秒** |