| | | 1 | | using UnityEngine; |
| | | 2 | | |
| | | 3 | | // Launch angle input. |
| | | 4 | | public struct LaunchAngleInput { |
| | | 5 | | // Horizontal distance in meters. |
| | 0 | 6 | | public float Distance { get; } |
| | | 7 | | |
| | | 8 | | // Altitude in meters. |
| | 0 | 9 | | public float Altitude { get; } |
| | | 10 | | |
| | 0 | 11 | | public LaunchAngleInput(float distance, float altitude) { |
| | 0 | 12 | | Distance = distance; |
| | 0 | 13 | | Altitude = altitude; |
| | 0 | 14 | | } |
| | | 15 | | } |
| | | 16 | | |
| | | 17 | | // Launch angle output. |
| | | 18 | | public struct LaunchAngleOutput { |
| | | 19 | | // Launch angle in degrees. |
| | | 20 | | public float LaunchAngle { get; } |
| | | 21 | | |
| | | 22 | | // Time to reach the target position in seconds. |
| | | 23 | | public float TimeToPosition { get; } |
| | | 24 | | |
| | | 25 | | public LaunchAngleOutput(float launchAngle, float timeToPosition) { |
| | | 26 | | LaunchAngle = launchAngle; |
| | | 27 | | TimeToPosition = timeToPosition; |
| | | 28 | | } |
| | | 29 | | } |
| | | 30 | | |
| | | 31 | | // Launch angle data point. |
| | | 32 | | public struct LaunchAngleDataPoint { |
| | | 33 | | // Launch angle input. |
| | | 34 | | public LaunchAngleInput Input { get; } |
| | | 35 | | |
| | | 36 | | // Launch angle output. |
| | | 37 | | public LaunchAngleOutput Output { get; } |
| | | 38 | | |
| | | 39 | | public LaunchAngleDataPoint(in LaunchAngleInput input, in LaunchAngleOutput output) { |
| | | 40 | | Input = input; |
| | | 41 | | Output = output; |
| | | 42 | | } |
| | | 43 | | } |
| | | 44 | | |
| | | 45 | | // The launch angle planner class is an interface for a planner that outputs the optimal launch |
| | | 46 | | // angle and the time-to-target. |
| | | 47 | | public interface ILaunchAnglePlanner { |
| | | 48 | | // Calculate the optimal launch angle in degrees and the time-to-target in seconds. |
| | | 49 | | public LaunchAngleOutput Plan(in LaunchAngleInput input); |
| | | 50 | | public LaunchAngleOutput Plan(Vector3 position) { |
| | | 51 | | Vector2 direction = ConvertToDirection(position); |
| | | 52 | | return Plan(new LaunchAngleInput(distance: direction[0], altitude: direction[1])); |
| | | 53 | | } |
| | | 54 | | |
| | | 55 | | // Get the intercept position. |
| | | 56 | | public Vector3 GetInterceptPosition(Vector3 position); |
| | | 57 | | |
| | | 58 | | // Convert from a 3D vector to a 2D direction that ignores the azimuth. |
| | | 59 | | protected static Vector2 ConvertToDirection(Vector3 position) { |
| | | 60 | | return new Vector2(Vector3.ProjectOnPlane(position, Vector3.up).magnitude, |
| | | 61 | | Vector3.Project(position, Vector3.up).magnitude); |
| | | 62 | | } |
| | | 63 | | } |