Ballistics Aim

BallisticAim
is a MonoBehaviour that computes and applies the required yaw (Y-axis) and pitch (X-axis) rotations for a two-pivot launcher (e.g., turret or cannon) to hit a specified 3D target. It leverages the core Ballistics.Solution
methods to solve for projectile trajectories, taking into account an initial muzzle speed and constant acceleration (gravity). The component enforces configurable rotational limits on both pivots, returning whether the calculated aim falls within those limits.
Demo Scene
See the (32) Targeting Tool scene for a practical demonstration of the tool.
Namespace & Dependencies
using Heathen.UnityPhysics.API; // Provides Ballistics.Solution(...)
using Unity.Mathematics; // For math.clamp and related utilities
using UnityEngine;
using UnityEngine.Serialization; // For [FormerlySerializedAs]
Fields & Properties
initial Speed
The muzzle (launch) speed of the projectile in units/second.
Displayed in the Inspector as “Initial Speed” (formerly named
initialVelocity
).
Constant Acceleration
The acceleration vector applied to the projectile throughout its flight (typically gravity).
Default value:
(0, –9.81f, 0)
.
Y Pivot
Reference to the yaw pivot (parent pivot) around which horizontal rotation is applied.
Expected to rotate about its local Y-axis.
X Pivot
Reference to the pitch pivot (child of yPivot
) that tilts up/down.
Expected to rotate about its local X-axis.
Y Limit
Minimum/maximum allowed yaw angles (in degrees) relative to world-space zero.
Default:
(-180, 180)
.
X Limit
Minimum/maximum allowed pitch angles (in degrees) relative to local zero.
Default:
(-180, 180)
.
Public Methods
Aim(Vector3 target)
Calculates a firing solution for a stationary target.
Calls
Ballistics.Solution(yPivot.position, initialSpeed, target, constantAcceleration, out Quaternion lowAngle, out _);
If the returned solution count is ≤ 0, the method returns
false
(no valid trajectory).Otherwise, it applies
lowAngle
to the two pivots (Y-pivot then X-pivot) viaApplyAimRotation(...)
and returns whether both yaw and pitch remain within their specified limits.
Aim(Vector3 target, Vector3 targetVelocity)
Calculates a firing solution for a moving target.
Calls
Ballistics.Solution(yPivot.position, initialSpeed, target, targetVelocity, constantAcceleration.magnitude, out Quaternion lowAngle, out _);
This overload factors in linear target motion (leading).
If no valid solution exists, returns
false
; otherwise, applieslowAngle
and returns whether the resulting angles respectyLimit
andxLimit
.
Usage Example
Scene Setup
Create an empty GameObject named “TurretRoot” (this is the
yPivot
).As a child of “TurretRoot”, create “TurretBarrel” (this is the
xPivot
).Attach your projectile-spawning script as a child of “TurretBarrel” so its forward (local Z+) direction is the launch direction.
Add the
BallisticAim
component to “TurretRoot”.
Inspector Assignment
Drag “TurretRoot” into the
yPivot
slot.Drag “TurretBarrel” into the
xPivot
slot.Set Initial Speed to your muzzle velocity (e.g.,
50f
).Leave Constant Acceleration at
(0, –9.81f, 0)
for Earth-like gravity.Adjust Y Limit and X Limit to prevent over-rotation or self-collision (e.g.,
yLimit = (–90, +90)
,xLimit = (–5, +45)
).
Runtime Aim Call
public class TurretController : MonoBehaviour { [SerializeField] private BallisticAim ballisticAim; [SerializeField] private Transform target; void Update() { Vector3 targetPosition = target.position; // Optionally, if the target moves: Vector3 targetVelocity = target.GetComponent<Rigidbody>()?.velocity ?? Vector3.zero; // Try to aim; if false, no valid shot or out of limits bool canAim = ballisticAim.Aim(targetPosition, targetVelocity); // You might highlight UI or disable firing if canAim == false } }
Behavior Notes
Low-Angle Solution: This component always uses the “low” solution returned by
Ballistics.Solution
. If you’d prefer a high-arc trajectory, replacelowAngle
with thehighAngle
output instead.Limit Enforcement: If the yaw or pitch is outside the configured ranges, the angle is clamped and the method returns
false
. You can detect out-of-bounds by checking the return value.Pivot Hierarchy: It is crucial that
xPivot
be a direct child ofyPivot
. Otherwise, local pitch rotations will not behave correctly relative to yaw.
Last updated