| | | 1 | | using UnityEngine; |
| | | 2 | | |
| | | 3 | | // The maximum speed assignment assigns hierarchical agents to hierarchical agents by maximizing the |
| | | 4 | | // overall intercept speed. The assignment cost is defined as the agent's fractional speed loss |
| | | 5 | | // during the maneuver. |
| | | 6 | | public class MaxSpeedAssignment : CostBasedAssignment { |
| | | 7 | | // Minimum fractional speed to prevent division by zero. |
| | | 8 | | private const float _minFractionalSpeed = 1e-6f; |
| | | 9 | | |
| | | 10 | | public MaxSpeedAssignment(AssignDelegate assignFunction) |
| | 3 | 11 | | : base(CalculateSpeedLoss, assignFunction) {} |
| | | 12 | | |
| | 31 | 13 | | private static float CalculateSpeedLoss(IHierarchical hierarchical, IHierarchical target) { |
| | 31 | 14 | | if (hierarchical is not HierarchicalAgent hierarchicalAgent) { |
| | 0 | 15 | | return 0; |
| | | 16 | | } |
| | | 17 | | |
| | 31 | 18 | | IAgent agent = hierarchicalAgent.Agent; |
| | | 19 | | // The speed decays exponentially with the traveled distance and with the bearing change. |
| | 31 | 20 | | float distanceTimeConstant = 2 * (agent.StaticConfig.BodyConfig?.Mass ?? 0) / |
| | | 21 | | (Constants.CalculateAirDensityAtAltitude(agent.Position.y) * |
| | | 22 | | (agent.StaticConfig.LiftDragConfig?.DragCoefficient ?? 0) * |
| | | 23 | | (agent.StaticConfig.BodyConfig?.CrossSectionalArea ?? 0)); |
| | 31 | 24 | | float angleTimeConstant = agent.StaticConfig.LiftDragConfig?.LiftDragRatio ?? 1; |
| | | 25 | | // During the turn, the minimum radius dictates the minimum distance needed to make the turn. |
| | 31 | 26 | | float minTurningRadius = agent.Velocity.sqrMagnitude / agent.MaxNormalAcceleration(); |
| | | 27 | | |
| | 31 | 28 | | Vector3 directionToTarget = target.Position - agent.Position; |
| | 31 | 29 | | float distanceToTarget = directionToTarget.magnitude; |
| | 31 | 30 | | float angleToTarget = Vector3.Angle(agent.Velocity, directionToTarget) * Mathf.Deg2Rad; |
| | | 31 | | // The fractional speed is the product of the fractional speed after traveling the distance and |
| | | 32 | | // of the fractional speed after turning. |
| | 31 | 33 | | float fractionalSpeed = |
| | | 34 | | Mathf.Exp(-((distanceToTarget + angleToTarget * minTurningRadius) / distanceTimeConstant + |
| | | 35 | | angleToTarget / angleTimeConstant)); |
| | | 36 | | // Prevent division by zero. |
| | 31 | 37 | | fractionalSpeed = Mathf.Max(fractionalSpeed, _minFractionalSpeed); |
| | 31 | 38 | | return agent.Speed / fractionalSpeed; |
| | 31 | 39 | | } |
| | | 40 | | } |