- DroneSpec/FireUnitSpec/SensorSpec 加 ModelId (FK→ModelInfo) - DroneEntity/PlatformEntity/DetectionEntity 内部带 ModelId - DetectionSource +ModelId - EntitySnapshot +ModelId,每帧推送给 Unity - CollectSnapshots 传播所有实体 ModelId
141 lines
5.7 KiB
C#
141 lines
5.7 KiB
C#
using System;
|
||
using CounterDrone.Core;
|
||
using CounterDrone.Core.Algorithms;
|
||
using CounterDrone.Core.Models;
|
||
|
||
namespace CounterDrone.Core.Simulation
|
||
{
|
||
public enum PlatformState { Idle, FlyingToTarget, ReadyToRelease }
|
||
|
||
public class PlatformEntity
|
||
{
|
||
public string Id { get; }
|
||
public EquipmentRole Role { get; }
|
||
public PlatformType? PlatformType { get; }
|
||
public float PosX { get; private set; }
|
||
public float PosY { get; private set; }
|
||
public float PosZ { get; private set; }
|
||
public AerosolType? AerosolType { get; }
|
||
public int MunitionCount { get; private set; }
|
||
public float Cooldown { get; }
|
||
public float CooldownRemaining { get; private set; }
|
||
public PlatformState State { get; private set; } = PlatformState.Idle;
|
||
|
||
// 空基平台
|
||
public float CruiseSpeed { get; }
|
||
public float PatrolX { get; }
|
||
public float PatrolY { get; }
|
||
public float PatrolZ { get; }
|
||
public float ReleaseAltitude { get; }
|
||
private float _targetX, _targetY, _targetZ;
|
||
private float _flightDistance;
|
||
private float _flownDistance;
|
||
private float _driftDistance;
|
||
/// <summary>空基平台精确投放时刻(计算值)</summary>
|
||
public float ExactReleaseTime => _exactReleaseTime;
|
||
private float _exactReleaseTime;
|
||
|
||
public float TargetX => _targetX;
|
||
public float TargetY => _targetY;
|
||
public float TargetZ => _targetZ;
|
||
public float FlightDistance => _flightDistance;
|
||
public float FlownDistance => _flownDistance;
|
||
|
||
// 地基平台
|
||
public float MuzzleVelocity { get; }
|
||
|
||
public string? ModelId { get; }
|
||
|
||
/// <summary>Ready 包含:冷却就绪 + 有弹药 + 非飞行中</summary>
|
||
public bool Ready => CooldownRemaining <= 0 && MunitionCount > 0 && State != PlatformState.FlyingToTarget;
|
||
|
||
public PlatformEntity(string id, FireUnitSpec spec, ScenarioUnit deployment)
|
||
{
|
||
Id = id;
|
||
Role = (EquipmentRole)deployment.EquipmentRole;
|
||
PlatformType = (PlatformType?)spec.PlatformType;
|
||
PosX = (float)deployment.PositionX;
|
||
PosY = (float)deployment.PositionY;
|
||
PosZ = (float)deployment.PositionZ;
|
||
AerosolType = deployment.AerosolType.HasValue ? (AerosolType?)deployment.AerosolType.Value : null;
|
||
MunitionCount = deployment.MunitionCount ?? 1;
|
||
Cooldown = (float)spec.Cooldown;
|
||
MuzzleVelocity = (float)spec.MuzzleVelocity;
|
||
CruiseSpeed = (float)spec.CruiseSpeed;
|
||
ReleaseAltitude = (float)spec.ReleaseAltitude;
|
||
ModelId = string.IsNullOrEmpty(spec.ModelId) ? null : spec.ModelId;
|
||
|
||
PatrolX = PosX;
|
||
PatrolY = PosY;
|
||
PatrolZ = PosZ;
|
||
}
|
||
|
||
public void Update(float deltaTime)
|
||
{
|
||
if (CooldownRemaining > 0)
|
||
CooldownRemaining -= deltaTime;
|
||
|
||
if (State != PlatformState.FlyingToTarget) return;
|
||
|
||
float step = CruiseSpeed * deltaTime;
|
||
_flownDistance += step;
|
||
|
||
if (_flownDistance >= _flightDistance - _driftDistance - 0.01f || _flightDistance < 0.01f)
|
||
{
|
||
// 在投放点(非终点),保留插值位置
|
||
float rt = _flightDistance > 0.01f ? Math.Min(1f, _flownDistance / _flightDistance) : 1f;
|
||
PosX = PatrolX + (_targetX - PatrolX) * rt;
|
||
PosY = PatrolY + (_targetY - PatrolY) * rt;
|
||
PosZ = PatrolZ + (_targetZ - PatrolZ) * rt;
|
||
State = PlatformState.ReadyToRelease;
|
||
return;
|
||
}
|
||
|
||
float t = _flownDistance / _flightDistance;
|
||
PosX = PatrolX + (_targetX - PatrolX) * t;
|
||
PosY = PatrolY + (_targetY - PatrolY) * t;
|
||
PosZ = PatrolZ + (_targetZ - PatrolZ) * t;
|
||
}
|
||
|
||
/// <summary>下令空基平台飞往投放点</summary>
|
||
public void CommandFlyTo(float targetX, float releaseAlt, float targetZ, float fireTime, float disperseHeight)
|
||
{
|
||
if (PlatformType != Models.PlatformType.AirBased) return;
|
||
_targetX = targetX;
|
||
_targetY = releaseAlt;
|
||
_targetZ = targetZ;
|
||
float distToCloud = Kinematics.Distance3D(PosX, PosY, PosZ, targetX, releaseAlt, targetZ);
|
||
float fallTime = Kinematics.AirDropFallTime(releaseAlt, disperseHeight);
|
||
float driftDist = CruiseSpeed * fallTime;
|
||
_flightDistance = distToCloud;
|
||
_flownDistance = 0;
|
||
_driftDistance = driftDist;
|
||
float flightDist = Math.Max(0f, distToCloud - driftDist);
|
||
float flightTime = CruiseSpeed > 0 ? flightDist / CruiseSpeed : 0f;
|
||
_exactReleaseTime = fireTime + flightTime;
|
||
State = PlatformState.FlyingToTarget;
|
||
}
|
||
|
||
/// <summary>地基:直接发射;空基:投弹后冷却</summary>
|
||
public void Release()
|
||
{
|
||
MunitionCount--;
|
||
CooldownRemaining = Cooldown;
|
||
State = PlatformState.Idle;
|
||
}
|
||
|
||
/// <summary>空基平台到达投放点后可投弹</summary>
|
||
public bool CanRelease => State == PlatformState.ReadyToRelease && CooldownRemaining <= 0 && MunitionCount > 0;
|
||
|
||
/// <summary>当前速度矢量(空基平台:飞行方向 × 巡航速度;地基:零矢量)</summary>
|
||
public (float Vx, float Vy, float Vz) CurrentVelocity
|
||
{
|
||
get
|
||
{
|
||
if (PlatformType != Models.PlatformType.AirBased) return (0, 0, 0);
|
||
return Kinematics.DirectionVelocity(PatrolX, PatrolY, PatrolZ, _targetX, _targetY, _targetZ, CruiseSpeed);
|
||
}
|
||
}
|
||
}
|
||
}
|