CounterDroneBackend/src/Unity/Assets/Scripts/Managers/ManagerVerification.cs
tian 46ce1234ee 修复 Unity 编译错误:变量冲突、DroneWave.DroneType 不存在、nullable 警告
- SimulationBootstrap: scenario 变量名冲突 → sc
- ManagerVerification: DroneWave.DroneType → Target (DroneWave 无此属性)
- ReportManager: string? → 拆为两个重载避免 nullable annotation 警告
2026-06-18 15:27:13 +08:00

135 lines
6.3 KiB
C#

using System.Collections.Generic;
using CounterDrone.Core;
using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;
using CounterDrone.Core.Simulation;
using UnityEngine;
using AVector3 = CounterDrone.Core.Algorithms.Vector3;
namespace CounterDrone.Unity
{
[ExecuteAlways]
public class ManagerVerification : MonoBehaviour
{
[ContextMenu("Run Full Verification")]
void Run()
{
Debug.Log("===== Manager Verification Start =====");
var paths = new UnityPathProvider();
if (System.IO.File.Exists(paths.GetMainDbPath()))
System.IO.File.Delete(paths.GetMainDbPath());
if (System.IO.Directory.Exists(paths.GetFramesDir()))
System.IO.Directory.Delete(paths.GetFramesDir(), true);
var modelMgr = gameObject.AddComponent<ModelManager>();
modelMgr.Awake();
Debug.Log("1. ModelManager OK");
var scenarioMgr = gameObject.AddComponent<ScenarioManager>();
scenarioMgr.Awake();
var scenario = scenarioMgr.CreateScenario("Verification", "");
var scenarioId = scenario.Id;
Debug.Log($"2. ScenarioManager OK. scenario: {scenarioId}");
scenarioMgr.SaveScene(scenarioId, new CombatScene { WindSpeed = 0 });
scenarioMgr.SaveTarget(scenarioId, new DroneProfile
{
WaveId = "default",
DroneType = (int)DroneType.FixedWing, PowerType = (int)PowerType.Piston,
Quantity = 1, TypicalSpeed = 200, TypicalAltitude = 500,
});
scenarioMgr.SaveRoute(scenarioId, "default", new RoutePlan { FormationMode = (int)FormationMode.Single },
new List<Waypoint>
{
new Waypoint { PosX = 0, PosY = 500, PosZ = 0, Speed = 200 },
new Waypoint { PosX = 10000, PosY = 500, PosZ = 0, Speed = 200 },
});
scenarioMgr.UpdateStep(scenarioId, 3);
Debug.Log("3. Scenario configured");
var db = new DatabaseManager(paths).OpenMainDb();
SqliteConnectionTracker.Track(db);
var ammoCatalog = db.Table<AmmunitionSpec>().ToList();
var detail = scenarioMgr.GetDetail(scenarioId);
var droneGroup = new DroneWave
{
WaveId = "default",
Target = detail.Targets[0],
Route = detail.Routes[0],
Waypoints = detail.WaypointGroups["default"],
};
var fireUnits = new List<FireUnit>();
for (int i = 0; i < 8; i++)
fireUnits.Add(new FireUnit
{
Id = $"u{i}",
Type = PlatformType.GroundBased,
Position = new AVector3(5000 + i * 50, 0, 50),
MuzzleVelocity = 800,
TotalMunitions = 3,
AmmoTypes = new() { AerosolType.InertGas, AerosolType.ActiveMaterial, AerosolType.ActiveFuel },
});
var result = new DefensePlanner(ammoCatalog, PlannerConfig.Load(paths)).Plan(fireUnits, new List<DroneWave> { droneGroup }, detail.Scene, new List<DetectionSource>());
scenarioMgr.SaveCloud(scenarioId, new CloudDispersal
{
PositionX = (droneGroup.Waypoints[0].PosX + droneGroup.Waypoints[^1].PosX) / 2,
PositionY = (droneGroup.Waypoints[0].PosY + droneGroup.Waypoints[^1].PosY) / 2,
PositionZ = (droneGroup.Waypoints[0].PosZ + droneGroup.Waypoints[^1].PosZ) / 2,
DisperseHeight = droneGroup.Target.TypicalAltitude,
});
var equips = new List<EquipmentDeployment>();
foreach (var u in fireUnits)
equips.Add(new EquipmentDeployment
{
EquipmentRole = (int)EquipmentRole.LaunchPlatform,
PlatformType = (int)u.Type, Quantity = 1,
PositionX = u.Position.X, PositionY = u.Position.Y, PositionZ = u.Position.Z,
AerosolType = (int)u.AmmoTypes[0],
MunitionCount = u.TotalMunitions, Cooldown = u.Cooldown, MuzzleVelocity = u.MuzzleVelocity,
CruiseSpeed = u.CruiseSpeed > 0 ? u.CruiseSpeed : null,
ReleaseAltitude = u.ReleaseAltitude > 0 ? u.ReleaseAltitude : null,
});
scenarioMgr.SaveDeployment(scenarioId, equips);
SqliteConnectionTracker.Untrack(db);
db.Dispose();
var plan = result.Best;
Debug.Log($"4. Plan: {plan.ThreatsEngaged} threats engaged, {plan.MergedSchedule.Count} rounds, prob={plan.OverallProbability:P0}");
var runner = gameObject.AddComponent<SimulationRunner>();
runner.Awake();
runner.LoadAndStart(scenarioId);
runner.Engine.TimeScale = 10f;
float endTime = Time.realtimeSinceStartup + 60f;
int frameCount = 0;
float tickDt = 1f / 20f;
while (runner.Engine.State == SimulationState.Running && Time.realtimeSinceStartup < endTime)
{
runner.Engine.Tick(tickDt);
frameCount++;
}
Debug.Log($"5. Simulation done. State={runner.Engine.State}, DroneStatus={runner.Engine.Drones[0].Status}, HP={runner.Engine.Drones[0].Hp:F2}, Frames={frameCount}");
runner.Stop();
var reportMgr = gameObject.AddComponent<ReportManager>();
reportMgr.Awake();
detail = scenarioMgr.GetDetail(scenarioId);
var simEvents = new List<SimEvent>(runner.Engine.Events);
var status = runner.Engine.Drones.Count > 0 ? runner.Engine.Drones[0].Status.ToString() : "Unknown";
var report = reportMgr.Generate(scenarioId, detail, simEvents, status, runner.Engine.SimulationTime);
var path = reportMgr.Export(report.Id);
Debug.Log($"6. Report OK. Exported: {path}");
var replay = gameObject.AddComponent<ReplayController>();
replay.Awake();
replay.LoadReplay(scenarioId);
Debug.Log($"7. Replay OK. {replay.TotalFrames} frames, {replay.CurrentFrames.Count} records");
Debug.Log("===== ALL MANAGERS VERIFIED =====");
}
}
}