# 后端对接文档(Unity 前端) > **版本**:V1.3 > **日期**:2026-06-15 > **Unity 版本**:2022.3.62f3c1 --- ## 一、交付物 从仓库取以下内容,拖入 Unity 项目: ``` src/Unity/Assets/Plugins/ ← DLL(Core + sqlite + JSON) src/Unity/Assets/Scripts/Managers/ ← 桥接脚本 将以下文件放到 Unity 项目 Assets/StreamingAssets/ 目录下: data/defaults.json ← 默认数据(首次运行自动复制到 persistentDataPath) data/planner_config.json ← 规划器配置(同上) ``` --- ## 二、快速开始 1. 将 `defaults.json` 和 `planner_config.json` 放到 `Assets/StreamingAssets/` 2. 创建空 GameObject,挂 `SimulationBootstrap` 3. 运行 — 自动种子数据库,选一个 `[Demo]` 想定,启动仿真 > `SimulationBootstrap` 是前端开发的参考模板,展示预设模式(一行代码)和自定义模式(用 DefaultData 预设组装)两种路径。 > 如需验证全部模块,挂 `ManagerVerification` → Inspector 右键 `Run Full Verification`。 --- ## 三、核心流程(使用预设想定) ### 3.1 列出预设想定 ```csharp var scenario = GetComponent(); var demos = scenario.Search("Demo", null, null, 1, 100); // → 返回 6 个预设想定: // [Demo] 无防御-无人机抵达目标 // [Demo] 管控区域侵入 // [Demo] 活塞拦截-西风5ms // [Demo] 喷气式拦截-活性材料 // [Demo] 空基拦截-东风5ms // [Demo] 3架空基编队拦截 ``` ### 3.2 启动仿真(一行代码) ```csharp var runner = GetComponent(); // 选一个预设想定,直接运行(引擎自动调用 Planner 生成发射计划) runner.LoadAndStart(demos.Items[0].Id); // 例如:活塞拦截-西风5ms runner.Engine.TimeScale = 4f; // 加速 // 订阅事件 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.OnTargetDetected += (d, det) => ShowDetectionMark(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(); ``` ### 3.3 自定义想定(高级) ```csharp var scenario = GetComponent(); var task = scenario.CreateTask("自定义想定", ""); // 使用默认数据预设快速配置 var defaults = DefaultData.Load(new UnityPathProvider()); scenario.SaveScene(task.Id, defaults.Weather.First(w => w.Id == "sunny-calm").ToCombatScene()); scenario.SaveTarget(task.Id, defaults.Targets.First(p => p.Id == "shahed").ToTargetConfig()); scenario.SaveRoute(task.Id, "default", defaults.Formations.First(f => f.Id == "single").ToRoutePlan(), defaults.Routes.First(r => r.Id == "5km-h500").ToWaypoints(200)); scenario.SaveDeployment(task.Id, new List { defaults.FireUnits.First(f => f.Id == "ground-light") .ToEquipmentDeployment(AerosolType.InertGas, 1, 1500, 0, 50), }); scenario.SaveCloudDispersal(task.Id, new CloudDispersal { AerosolType = (int)AerosolType.InertGas, DisperseHeight = 500 }); scenario.UpdateStep(task.Id, 5); // 运行 var runner = GetComponent(); runner.LoadAndStart(task.Id); ``` ### 3.3 仿真事件一览 | 事件 | 参数 | 触发时机 | |------|------|------| | `OnTargetDetected` | `DroneEntity`, `DetectionEntity` | 无人机首次进入探测设备 3D 球冠范围(离开后再次进入会重新触发) | | `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, "default", 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 / DetectionEntities / Events runner.Stop(); ``` ### ReportManager ```csharp var mgr = GetComponent(); 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 ```csharp var replay = GetComponent(); replay.LoadReplay(taskId); // replay.TotalFrames / replay.GetFrame(frameIndex) ``` --- ## 五、默认数据 首次运行 `DatabaseManager.OpenMainDb()` 自动从 `data/defaults.json` 种子数据库: | 类别 | 内容 | 示例 ID | |------|------|------| | 弹药 | 3 种 | `inert` / `active` / `fuel` | | 编队 | 6 种 | `single` / `line-3` / `swarm-10` | | 航线 | 6 条 | `3km-h300` / `5km-h500` / `10km-h500` / `20km-h500` | | 火力单元 | 4 种 | `ground-light` / `ground-standard` / `ground-heavy` / `air-standard` | | 无人机 | 6 种 | `quadcopter` / `shahed` / `cruise-missile` | | 探测设备 | 4 种 | `radar-mr` / `eo-station` | | 天气 | 6 种 | `sunny-calm` / `fog` / `night` | | 预设想定 | 6 个 | `[Demo] 活塞拦截-西风5ms` | 所有默认数据名称含 `[Demo]` 前缀,UI 中可识别。预设可通过 API 直接获取: ```csharp var defaults = DefaultData.Load(new UnityPathProvider()); var ammo = defaults.Ammunition.First(a => a.Id == "inert"); var route = defaults.Routes.First(r => r.Id == "5km-h500").ToWaypoints(200); var unit = defaults.FireUnits.First(f => f.Id == "ground-light").ToEquipmentDeployment(AerosolType.InertGas, 1, 1500, 0, 50); ``` --- ## 六、更新后端 ```bash cd src/CounterDrone.Core dotnet publish -c Release -o ../../unity_plugins # 覆盖 Assets/Plugins/CounterDrone.Core/ 下所有 DLL ``` --- ## 七、参考 | 文档 | 位置 | |------|------| | 架构设计 | `docs/design/architecture/总体架构设计.md` | | 实体事件映射 | `docs/design/technical/仿真器实体与事件映射.md` | | 任务跟踪 | `docs/implementation/tasks/实施计划与任务跟踪.md` | | 测试报告 | `test/reports/`(每次集成测试自动生成) | | 测试状态 | **191 测试,24 秒(集成)** |