Knowledge Base
HomeProductsCommunityReviewsSocial
Toolkit for Unity
Toolkit for Unity
  • Welcome
  • Physics
    • Introduction
    • Ballistics
      • API.Ballistics
      • Ballistics Aim
      • Ballistic Path
      • Ballistic Path Follow
      • Ballistic Path Line Render
      • Ballistics Data
      • Ballistic Targeting
      • Trick Shot
      • Trick Shot Constant Acceleration
      • Trick Shot Line
    • Verlet (Physics Transform)
      • Scaled Animation Curve
      • Verlet Transform Node
      • Verlet Transforms
      • Verlet Transform Tree
      • Verlet Transform Tree Settings
    • Old KB
  • User eXperience
    • Introduction
    • Old KB
Powered by GitBook
On this page
  • 1. Maximum Range & Flight Time
  • 1.1 MaxRange (3D)
  • 1.3 FlightTime2D (2D)
  • 1.4 FinalVelocity (3D)
  • 1.5 FinalVelocity2D (2D)
  • 2. Launch‐Angle Solutions (Stationary Targets)
  • 2.1 Solution (3D with Constant Acceleration)
  • 2.2 Solution2D (2D with Constant Acceleration)
  • 2.3 Solution (3D with Gravity Scalar)
  • 2.4 Solution2D (2D with Gravity Scalar)
  • 3. Aiming Solutions (Moving Targets)
  • 3.1 Solution (3D, Moving Target)
  • 3.2 Solution2D (2D, Moving Target)
  • 4. Arc‐Ceiling Solutions (Fixed and Moving Targets)
  • 4.1 Solution (3D, Prescribed Arc Ceiling, Stationary Target)
  • 4.2 Solution2D (2D, Prescribed Arc Ceiling, Stationary Target)
  • 4.3 Solution (3D, Prescribed Arc Ceiling, Moving Target)
  • 4.4 Solution2D (2D, Prescribed Arc Ceiling, Moving Target)
  • 5. Flight‐Time Specified Solutions
  • 5.1 Solution (3D, Flight Time Specified)
  • 5.2 Solution2D (2D, Flight Time Specified)
  • 6. Speed‐Given‐Angle Solutions
  • 6.1 Solution (3D, Speed Given Angle)
  • 6.2 Solution2D (2D, Speed Given Angle)
  • 7. Trajectory Marching (Raycast & SphereCast)
  • 7.1 Raycast (3D)
  • 7.2 SphereCast (3D)
  • 7.3 Raycast2D (2D)
  • 7.4 CircleCast (2D)
  • 7.5 SphereCast (Simplified Overload, 3D)
  • Usage Scenarios & Tips
  1. Physics
  2. Ballistics

API.Ballistics

The Ballistics class (namespace Heathen.UnityPhysics.API) offers a comprehensive set of static methods for solving projectile‐motion problems in both 3D and 2D contexts. Designers and programmers can use these utilities to:

  • Estimate maximum range or required speed/angle.

  • Compute flight time or final velocity for a given trajectory.

  • Solve for launch rotations (low/high arc) toward stationary or moving targets.

  • Generate full, sampled trajectories via raycasts or spherecasts that account for gravity or other constant accelerations.

Below is a grouped reference of all public methods, with usage notes, parameter descriptions, and practical tips.


1. Maximum Range & Flight Time

1.1 MaxRange (3D)

public static float MaxRange(float speed, float gravity, float height)
  • Purpose: Returns the maximum horizontal distance (range) reachable when launching at 45° from a given height, ignoring air resistance.

  • Parameters:

    • speed (float): Initial launch speed (> 0).

    • gravity (float): Gravity magnitude (> 0).

    • height (float): Launch‐point height above the landing plane (≥ 0).

  • Returns:

    • Maximum range (units), or 0 if invalid inputs (speed ≤ 0, gravity ≤ 0, or height < 0).

  • Usage:

    • Quickly gauge how far a cannonball or grenade would travel when fired at 45°.

    • Clamp AI or camera aiming—e.g., if targetDistance > MaxRange(speed, 9.81f, muzzleHeight), skip the shot.


public static float FlightTime(
    Vector3 start,
    Vector3 end,
    Vector3 velocity,
    Vector3 constantAcceleration,
    float tolerance = 0.01f
)
  • Purpose: Finds a positive flight time t such that the projectile, launched from start with initial velocity and subjected to constantAcceleration, arrives at end.

  • Parameters:

    • start, end (Vector3): World‐space start and end positions.

    • velocity (Vector3): Initial velocity vector.

    • constantAcceleration (Vector3): Constant acceleration (e.g., (0, –9.81f, 0)).

    • tolerance (float): Maximum allowed error when comparing solutions on each axis (default 0.01).

  • Returns:

    • A positive flight time (seconds) if a consistent solution across X/Y/Z axes is found; otherwise float.NaN.

  • Usage:

    • Determine “time to impact” given a known launch vector—useful for synchronizing timed effects.

    • Validate a precomputed trajectory—if FlightTime(...) returns NaN, there is no way to reach end with the given inputs.


1.3 FlightTime2D (2D)

public static float FlightTime2D(
    Vector2 start,
    Vector2 end,
    Vector2 velocity,
    Vector2 constantAcceleration,
    float tolerance = 0.01f
)
  • Purpose: Same as FlightTime but in the X/Y plane (2D).

  • Parameters:

    • start, end (Vector2): 2D start and end positions.

    • velocity (Vector2): Initial 2D velocity.

    • constantAcceleration (Vector2): 2D acceleration.

    • tolerance (float): Allowed difference between X and Y solutions (default 0.01).

  • Returns:

    • Positive flight time if a consistent solution exists; otherwise NaN.

  • Usage:

    • Pinpoint when a 2D projectile reaches a specific point (e.g., for triggering splash effects).


1.4 FinalVelocity (3D)

public static Vector3 FinalVelocity(
    Vector3 initialVelocity,
    Vector3 constantAcceleration,
    float flightTime
)
  • Purpose: Computes the final velocity after time flightTime under constant acceleration.

  • Returns: initialVelocity + constantAcceleration * flightTime.

  • Usage:

    • After computing flight time via FlightTime, call this to know the speed/direction at impact.


1.5 FinalVelocity2D (2D)

public static Vector2 FinalVelocity2D(
    Vector2 initialVelocity,
    Vector2 constantAcceleration,
    float flightTime
)
  • Purpose: 2D analog of FinalVelocity.

  • Returns: initialVelocity + constantAcceleration * flightTime.


2. Launch‐Angle Solutions (Stationary Targets)

These methods solve for one or two possible launch rotations (quaternions) that send a projectile from projectile to target, given speed or gravity. They return the number of valid solutions (0, 1, or 2), and output lowAngle (flatter trajectory) and highAngle (steeper trajectory). In 3D, you can supply a full acceleration vector; in 2D, analogous methods operate on Vector2.


2.1 Solution (3D with Constant Acceleration)

public static int Solution(
    Vector3 projectile,
    float speed,
    Vector3 target,
    Vector3 constantAcceleration,
    out Quaternion lowAngle,
    out Quaternion highAngle
)
  • Purpose: Solves for low‐ and high‐arc launch rotations when acceleration may not be purely vertical (e.g., gravity + wind).

  • Algorithm:

    1. Rotate world so constantAcceleration aligns with (0, –1, 0).

    2. Solve 2D problem in that space with scalar gravity = ‖constantAcceleration‖.

    3. Rotate solutions back to original space.

  • Parameters:

    • projectile, target: World‐space positions.

    • speed: Scalar launch speed (> 0).

    • constantAcceleration: Any nonzero acceleration vector.

  • Returns:

    • 0 if no solutions (e.g., out of range or zero acceleration), 1 if a single tangent, or 2 if two distinct arcs exist.

    • lowAngle/highAngle are set to identity if no solutions; otherwise, the corresponding quaternions.

  • Usage:

    if (Ballistics.Solution(muzzlePos, muzzleSpeed, enemyPos, Physics.gravity, out Quaternion low, out Quaternion high) > 0)
    {
        // Use low or high: e.g., turret.rotation = low;
    }
  • Designer Tips:

    • Use low‐arc (lowAngle) for faster, direct shots.

    • Use high‐arc (highAngle) for lobbed trajectories (e.g., launching over obstacles).


2.2 Solution2D (2D with Constant Acceleration)

public static int Solution2D(
    Vector2 projectile,
    float speed,
    Vector2 target,
    Vector2 constantAcceleration,
    out Quaternion lowAngle,
    out Quaternion highAngle
)
  • Purpose: 2D equivalent of the above, returning quaternions whose forward vector lies in the XY‐plane.

  • Parameters:

    • projectile, target (Vector2): 2D start and end.

    • constantAcceleration: Typically (0, –gravity).

  • Returns:

    • Number of solutions (0, 1, or 2).

    • lowAngle, highAngle quaternions (their “forward” points in the 2D direction of launch).

  • Usage:

    if (Ballistics.Solution2D(
            new Vector2(barrelX, barrelY),
            launchSpeed,
            new Vector2(enemyX, enemyY),
            new Vector2(0, -9.81f),
            out Quaternion lowQ,
            out Quaternion highQ))
    {
        // Apply lowQ to a 2D sprite’s rotation (using Quaternion.LookRotation)
    }

2.3 Solution (3D with Gravity Scalar)

public static int Solution(
    Vector3 projectile,
    float speed,
    Vector3 target,
    float gravity,
    out Quaternion lowAngle,
    out Quaternion highAngle
)
  • Purpose: Classic 3D ballistic‐trajectory solver assuming vertical gravity of magnitude gravity. Returns quaternions for low/high launch angles.

  • Parameters:

    • projectile, target: World‐space positions.

    • speed: Initial speed (> 0).

    • gravity: Gravity magnitude (> 0).

  • Returns:

    • 0 if no real solutions (target out of range), 1 if tangent, or 2 if two distinct arcs.

    • lowAngle = flatter arc; highAngle = steeper arc.

  • Usage:

    int solutions = Ballistics.Solution(
        muzzlePos, muzzleSpeed, enemyPos,
        Physics.gravity.y * -1f,  // Provide positive gravity scalar
        out Quaternion low, out Quaternion high
    );
    if (solutions > 0) turret.rotation = low;

2.4 Solution2D (2D with Gravity Scalar)

public static int Solution2D(
    Vector2 projectile,
    float speed,
    Vector2 target,
    float gravity,
    out Quaternion lowAngle,
    out Quaternion highAngle
)
  • Purpose: 2D analog of the 3D‐gravity solver.

  • Returns: Low/high quaternions whose forward axis is (0,0,1) and “up” is the 2D launch vector in XY.

  • Usage:

    int sols = Ballistics.Solution2D(
        new Vector2(barrelX, barrelY),
        launchSpeed,
        new Vector2(enemyX, enemyY),
        9.81f,
        out Quaternion lowQ,
        out Quaternion highQ
    );
    if (sols > 0) sprite.transform.rotation = lowQ;

3. Aiming Solutions (Moving Targets)

When the target moves with a constant velocity, these methods solve a quartic equation for time of intercept and compute the corresponding launch directions. They support both 3D and 2D.


3.1 Solution (3D, Moving Target)

public static int Solution(
    Vector3 projectile,
    float speed,
    Vector3 target,
    Vector3 targetVelocity,
    float gravity,
    out Quaternion lowAngle,
    out Quaternion highAngle
)
  • Purpose: Finds up to two valid launch rotations that intercept a target moving at targetVelocity under scalar vertical gravity.

  • Algorithm:

    1. Build quartic coefficients for intercept time t based on relative positions and velocities (derived from “lib_fts” formulas).

    2. Solve quartet for positive roots.

    3. For each positive root t, compute required launch velocity vector.

    4. Convert those direction vectors into quaternions (Quaternion.LookRotation(...)).

  • Parameters:

    • projectile, target: Initial positions.

    • speed: Launch speed.

    • targetVelocity: Constant world‐space velocity of the target.

    • gravity: Gravity magnitude (> 0).

  • Returns:

    • Count count of valid launch‐vectors (0, 1, or 2).

    • lowAngle = first solution; highAngle = second solution if present, otherwise same as lowAngle.

  • Usage:

    int n = Ballistics.Solution(
        muzzlePos, launchSpeed, enemyPos, enemyVel,
        9.81f, out Quaternion aimLow, out Quaternion aimHigh
    );
    if (n > 0) turret.rotation = aimLow;

3.2 Solution2D (2D, Moving Target)

public static int Solution2D(
    Vector2 projectile,
    float speed,
    Vector2 target,
    Vector2 targetVelocity,
    float gravity,
    out Quaternion lowAngle,
    out Quaternion highAngle
)
  • Purpose: 2D counterpart for a moving target on the X/Y plane under vertical gravity.

  • Returns:

    • Number of valid solutions (0, 1, 2).

    • Quaternions whose forward is (0,0,1) and up‐vector corresponds to the required 2D launch vector.

  • Usage:

    int solutions = Ballistics.Solution2D(
        new Vector2(barrelX, barrelY),
        launchSpeed,
        new Vector2(enemyX, enemyY),
        new Vector2(enemyVelX, enemyVelY),
        9.81f,
        out Quaternion lowQ,
        out Quaternion highQ
    );
    if (solutions > 0) my2DSprite.rotation = lowQ;

4. Arc‐Ceiling Solutions (Fixed and Moving Targets)

These methods compute the initial velocity vector and required gravity to satisfy a specified “maximum height” (arc ceiling) along the trajectory, solving a system of equations that force the apex of the parabola to reach arcCeiling. Both 3D and 2D variants exist, for stationary and moving targets.


4.1 Solution (3D, Prescribed Arc Ceiling, Stationary Target)

public static bool Solution(
    Vector3 projectile,
    float linearSpeed,
    Vector3 target,
    float arcCeiling,
    out Vector3 firingVelocity,
    out float gravity
)
  • Purpose: Given a desired apex height (arcCeiling) and constant horizontal speed (linearSpeed), finds the vertical component of the initial velocity and gravity value needed to pass through that apex and land at target.

  • Parameters:

    • projectile, target: World‐space start and end.

    • linearSpeed: Speed along the horizontal plane (XZ).

    • arcCeiling: Desired maximum height (absolute Y value) of the trajectory, must be > projectile.y.

  • Outputs:

    • firingVelocity: Vector3 launch velocity (combining horizontal direction and vertical component).

    • gravity: Negative gravity scalar required to achieve that apex.

  • Returns: true if a valid solution exists; false otherwise (e.g., projectile == target, arcCeiling ≤ projectile.y, or zero horizontal distance).

  • Usage:

    if (Ballistics.Solution(
            muzzlePos, 10f, targetPos,
            15f,         // apex at Y = 15
            out Vector3 launchVel,
            out float neededGravity))
    {
        // Use launchVel as initial velocity; apply gravity = neededGravity downward
    }

4.2 Solution2D (2D, Prescribed Arc Ceiling, Stationary Target)

public static bool Solution2D(
    Vector2 projectile,
    float linearSpeed,
    Vector2 target,
    float arcCeiling,
    out Vector2 firingVelocity,
    out float gravity
)
  • Purpose: Same as above, but in 2D (X/Y).

  • Usage:

    if (Ballistics.Solution2D(
            new Vector2(barrelX, barrelY),
            8f,                                      // horizontal speed
            new Vector2(enemyX, enemyY),
            barrelY + 5f,                            // apex 5 units above barrel
            out Vector2 launchVel2D,
            out float neededG2D))
    {
        // Use launchVel2D.y and apply gravity = neededG2D
    }

4.3 Solution (3D, Prescribed Arc Ceiling, Moving Target)

public static bool Solution(
    Vector3 projectile,
    float linearSpeed,
    Vector3 target,
    Vector3 targetVelocity,
    float arcCeiling,
    out Vector3 firingVelocity,
    out float gravity,
    out Vector3 impactPoint
)
  • Purpose: Computes initial firingVelocity and gravity so the projectile intercepts a moving target at a trajectory whose apex is arcCeiling above max(startY, targetY). Also returns the computed impactPoint accounting for movement.

  • Parameters:

    • projectile: Launch position.

    • linearSpeed: Horizontal speed on the XZ plane (no vertical component).

    • target, targetVelocity: Initial position and velocity of the moving target.

    • arcCeiling: Desired apex height above “ground”—calculated as max(projectile.y, impactPoint.y) + arcCeiling.

  • Outputs:

    • firingVelocity (Vector3): Initial velocity (both horizontal and vertical components).

    • gravity (float): Negative gravity scalar needed.

    • impactPoint (Vector3): World‐space point where the projectile collides, given the target’s motion.

  • Returns: true if a valid intercept solution exists; false otherwise.

  • Usage:

    if (Ballistics.Solution(
            muzzlePos, 12f,
            enemyPos, enemyVel,
            10f,                    // apex 10 units above
            out Vector3 launchVel3D,
            out float neededG3D,
            out Vector3 intercept))
    {
        // Apply launchVel3D and set gravity = neededG3D
        // You can also visualize intercept
    }

4.4 Solution2D (2D, Prescribed Arc Ceiling, Moving Target)

public static bool Solution2D(
    Vector2 projectile,
    float linearSpeed,
    Vector2 target,
    Vector2 targetVelocity,
    float arcCeiling,
    out Vector2 firingVelocity,
    out float gravity,
    out Vector2 impactPoint
)
  • Purpose: 2D version of the moving‐target, prescribed apex solver.

  • Usage:

    if (Ballistics.Solution2D(
            new Vector2(barrelX, barrelY),
            7f,
            new Vector2(enemyX, enemyY),
            new Vector2(enemyVelX, 0),  // only horizontal velocity matters
            5f,
            out Vector2 launchVel2D,
            out float g2D,
            out Vector2 intercept2D))
    {
        // Fire with launchVel2D and apply gravity = g2D
    }

5. Flight‐Time Specified Solutions

When you know exactly how long you want the projectile to be in flight (e.g., for timing or syncing purposes), these methods compute the required initial velocity to land at target after a fixed flightTime under a constant gravity.


5.1 Solution (3D, Flight Time Specified)

public static Vector3 Solution(
    Vector3 projectile,
    Vector3 target,
    float gravity,
    float flightTime
)
  • Purpose: Returns the initial velocity vector that sends a projectile from projectile to target in exactly flightTime, under vertical gravity of magnitude gravity.

  • Parameters:

    • projectile, target: World positions.

    • gravity: Gravity scalar (negative or positive? It uses gravity as is, so typically pass a negative value, e.g., -9.81f).

    • flightTime: Desired time to impact (> 0).

  • Returns:

    • A Vector3 whose horizontal components (x,z) equal horizontalDistance / flightTime, and whose vertical component solves y0 + vy*t + 0.5*gravity*t^2 = y1.

  • Usage:

    Vector3 requiredVel = Ballistics.Solution(
        startPos, endPos,
        -9.81f,    // negative gravity
        2.5f       // hit target in 2.5 seconds
    );
    // Use requiredVel as the projectile’s initial velocity

5.2 Solution2D (2D, Flight Time Specified)

public static Vector2 Solution2D(
    Vector2 projectile,
    Vector2 target,
    float gravity,
    float flightTime
)
  • Purpose: 2D analog (X/Y) for fixed flightTime.

  • Returns: Vector2(horizontalVelocity, verticalVelocity).

  • Usage:

    Vector2 launchVel2D = Ballistics.Solution2D(
        new Vector2(barrelX, barrelY),
        new Vector2(enemyX, enemyY),
        -9.81f,
        1.8f    // seconds
    );

6. Speed‐Given‐Angle Solutions

These methods compute the necessary launch speed (magnitude) to hit a target from projectile when the launch direction is constrained to a fixed angle angleDegrees above the horizontal.


6.1 Solution (3D, Speed Given Angle)

public static bool Solution(
    Vector3 projectile,
    Vector3 target,
    float angleDegrees,
    float gravity,
    out float speed
)
  • Purpose: With a fixed elevation angleDegrees (above the horizontal plane), computes the required scalar speed so the projectile reaches target under vertical gravity of magnitude gravity.

  • Parameters:

    • projectile, target: Start and end positions.

    • angleDegrees: Launch angle from horizontal (0–90).

    • gravity: Gravity magnitude (> 0).

  • Outputs:

    • speed: Required launch speed.

  • Returns: true if a valid (real) solution exists; false otherwise (e.g., denominator ≥ 0 or range = 0).

  • Usage:

    if (Ballistics.Solution(
            turretPos, enemyPos,
            30f,      // 30° elevation
            9.81f, 
            out float neededSpeed))
    {
        // Fire with muzzle velocity = neededSpeed, pointing at angleDegrees above the horizontal
    }

6.2 Solution2D (2D, Speed Given Angle)

public static bool Solution2D(
    Vector2 projectile,
    Vector2 target,
    float angleDegrees,
    float gravity,
    out float speed
)
  • Purpose: 2D version for a fixed launch angle in X/Y.

  • Returns:

    • Required speed magnitude, combining horizontal component z and vertical component y.

  • Usage:

    if (Ballistics.Solution2D(
            new Vector2(barrelX, barrelY),
            new Vector2(enemyX, enemyY),
            45f,
            9.81f,
            out float speed2D))
    {
        // Fire from barrel with speed2D at 45° up
    }

7. Trajectory Marching (Raycast & SphereCast)

These methods allow you to “march” a projectile along its path—applying constant acceleration at each step—and perform either raycasts or spherecasts to detect collisions. They return both the impact (if any) and a sampled path of (position, velocity, time) tuples.


7.1 Raycast (3D)

public static bool Raycast(
    Vector3 start,
    Vector3 velocity,
    Vector3 constantAcceleration,
    float resolution,
    float maxLength,
    LayerMask collisionLayers,
    out RaycastHit hit,
    out List<(Vector3 position, Vector3 velocity, float time)> path,
    out float distance
)
  • Purpose: Step through a parabolic path, using a symmetric ray at each segment of length resolution, to detect the first collision.

  • Parameters:

    • start: Starting position (Vector3).

    • velocity: Initial launch vector.

    • constantAcceleration: Gravity or other acceleration.

    • resolution: Step length between raycasts (e.g., 0.1f).

    • maxLength: Maximum total arc‐length to march.

    • collisionLayers: LayerMask for collision detection.

  • Outputs:

    • hit: The RaycastHit if collision occurred (otherwise hit.transform == null).

    • path: A List of tuples (position, velocity, time), starting with (start, velocity, 0f), then each sampled point until impact or until exceeding maxLength.

    • distance: Total distance traveled along the curve before impact (or maxLength if no hit).

  • Returns: true if a collision was detected; false otherwise.

  • Usage:

    if (Ballistics.Raycast(
            muzzlePos,
            launchVel,
            Physics.gravity,
            0.2f,                  // resolution
            50f,                   // maxLength
            LayerMask.GetMask("Walls"),
            out RaycastHit info3D,
            out var sampledPath3D,
            out float traveledDist
    ))
    {
        // sampledPath3D contains the positions & velocities at each step,
        // info3D.point is the impact point, and traveledDist is the arc length.
    }
  • Designer Tips:

    • Use for custom trajectory visualizers or to spawn effects at predicted impact.

    • Remember that smaller resolution values yield smoother curves and more accurate collision detection at higher CPU cost.


7.2 SphereCast (3D)

public static bool SphereCast(
    Vector3 start,
    Collider startCollider,
    Vector3 velocity,
    Vector3 constantAcceleration,
    float radius,
    float resolution,
    float maxLength,
    LayerMask collisionLayers,
    QueryTriggerInteraction queryTriggerInteraction,
    out RaycastHit hit,
    out List<(Vector3 position, Vector3 velocity, float time)> path,
    out float distance
)
  • Purpose: Similar to Raycast(...), but uses a sphere of radius radius to detect collisions, checking against collisionLayers with optional trigger inclusion. Temporarily disables startCollider at the very beginning to avoid self‐hits.

  • Parameters:

    • startCollider: The Collider to disable at launch until the projectile moves beyond its radius, preventing immediate self‐collision. May be null.

    • All others match Raycast(...) with the addition of radius and queryTriggerInteraction.

  • Usage:

    if (Ballistics.SphereCast(
            muzzlePos,
            muzzleCollider,
            launchVel,
            Physics.gravity,
            0.1f,                  // sphere radius
            0.2f,                  // resolution
            50f,
            LayerMask.GetMask("Obstacles"),
            QueryTriggerInteraction.Ignore,
            out RaycastHit sphereHit,
            out var spherePath,
            out float sphereDist
    ))
    {
        // path includes the hit point; sphereHit provides normal, collider, etc.
    }

7.3 Raycast2D (2D)

public static bool Raycast2D(
    Vector2 start,
    Vector2 velocity,
    Vector2 constantAcceleration,
    float resolution,
    float maxLength,
    LayerMask collisionLayers,
    out RaycastHit2D hit,
    out List<(Vector2 position, Vector2 velocity, float time)> path,
    out float distance
)
  • Purpose: Marches a 2D projectile along its XY path via Physics2D.Raycast at each step of length resolution, accumulating (position, velocity, time) samples until impact or until the traveled distance ≥ maxLength.

  • Usage:

    if (Ballistics.Raycast2D(
            new Vector2(barrelX, barrelY),
            launchVel2D,
            new Vector2(0, -9.81f),
            0.05f,                  // resolution
            30f,                    // maxLength
            LayerMask.GetMask("Platform"),
            out RaycastHit2D hit2D,
            out var path2D,
            out float dist2D
    ))
    {
        // path2D holds sampled points; hit2D has collision info.
    }

7.4 CircleCast (2D)

public static bool CircleCast(
    Vector2 start,
    Collider2D startCollider,
    Vector2 velocity,
    Vector2 constantAcceleration,
    float radius,
    float resolution,
    float maxLength,
    LayerMask collisionLayers,
    out RaycastHit2D hit,
    out List<(Vector2 position, Vector2 velocity, float time)> path,
    out float distance
)
  • Purpose: 2D analog of SphereCast(...). At each incremental step of length resolution, performs Physics2D.CircleCast with radius radius (temporarily disabling startCollider to avoid self‐hit).

  • Usage:

    if (Ballistics.CircleCast(
            new Vector2(barrelX, barrelY),
            barrelCollider2D,
            launchVel2D,
            new Vector2(0, -9.81f),
            0.2f,                   // radius
            0.05f,                  // resolution
            30f,
            LayerMask.GetMask("Enemy"),
            out RaycastHit2D circleHit,
            out var circlePath,
            out float circleDist
    ))
    {
        // circlePath contains the sampled trajectory, ending with the impact point.
    }

7.5 SphereCast (Simplified Overload, 3D)

public static bool SphereCast(
    Vector3 start,
    Collider startCollider,
    Vector3 velocity,
    float radius,
    float resolution,
    float maxLength,
    LayerMask collisionLayers,
    QueryTriggerInteraction queryTriggerInteraction,
    out RaycastHit hit,
    out List<(Vector3 position, Vector3 velocity, float time)> path,
    out float distance
)
  • Purpose: A single‐spherecast version that marches only in one long cast of length maxLength (rather than incremental steps). It still disables startCollider briefly to prevent self‐collision.

  • Behavior:

    1. Disable startCollider.

    2. Perform a single Physics.SphereCast(ray, radius, maxLength, collisionLayers, queryTriggerInteraction).

    3. If hit, compute hitTime = (hitPoint – start).magnitude / velocity.magnitude, add (hitPoint, velocity, hitTime) to path, set distance = (hitPoint – start).magnitude, and return true.

    4. If no hit, restore startCollider, set distance = maxLength, return false.

  • Usage:

    if (Ballistics.SphereCast(
            startPos,
            myCollider,
            initVel,
            0.1f, 
            0.01f,
            20f,
            LayerMask.GetMask("Terrain"),
            QueryTriggerInteraction.Collide,
            out RaycastHit hitInfo,
            out var simplePath,
            out float simpleDist
    ))
    {
        // simplePath contains only two entries: start and impact point.
    }
    else
    {
        // No collision within maxLength.
    }

Usage Scenarios & Tips

  1. Quick Range Checks

    • Use MaxRange(speed, gravity, height) to decide if a target is out of theoretical range before attempting a more expensive solution.

  2. Single‐Frame Aim

    • For a turret that does not account for target motion:

      if (Ballistics.Solution(
              turretPos, turretSpeed, targetPos,
              Physics.gravity.y * -1f, 
              out Quaternion low, out Quaternion high))
      {
          turret.rotation = low;
      }
  3. Moving Target Intercept

    • To lead a moving enemy, call the 3D “moving target” solver:

      int n = Ballistics.Solution(
          turretPos, turretSpeed,
          enemyPos, enemyVelocity,
          9.81f,
          out Quaternion lowLead, out Quaternion highLead
      );
      if (n > 0) turret.rotation = lowLead;
  4. Trajectory Visualization

    • To draw a predictive line or spawn tracer particles along the path:

      Ballistics.SphereCast(
          launchPos, shooterCollider, launchVel,
          gravityVector,
          sphereRadius,
          sampleResolution,
          maxArcLength,
          layerMask,
          QueryTriggerInteraction.Ignore,
          out RaycastHit collisionInfo,
          out var fullPath,
          out float arcDist
      );
      // fullPath is a List<(position, velocity, time)>—use position for gizmos.
  5. Planned Bounce Calculations

    • Combine SphereCast(...) with Ballistics.Solution(...) for successive bounces:

      // 1. Initial arc (maybe no bounce):
      Ballistics.SphereCast(start, myCollider, vel, grav, radius, res, maxLen, layers,
          QueryTriggerInteraction.Ignore, out var hit0, out var path0, out var dist0);
      
      // 2. If hit0.transform != null:
      Vector3 reflectVel = Vector3.Reflect(path0[^1].velocity, hit0.normal) * 0.8f;
      Vector3 newStart = hit0.point;
      Ballistics.SphereCast(newStart, myCollider, reflectVel, grav, radius, res, maxLen2, layers,
          QueryTriggerInteraction.Ignore, out var hit1, out var path1, out var dist1);
    • Append path1 to path0 if you wish to visualize or feed into a “follow‐path” component.

  6. Custom Gravity or Other Constant Forces

    • Any method that takes constantAcceleration (Vector3/Vector2) can simulate wind, buoyancy, or magnetic forces by changing constantAcceleration from (0, –9.81f, 0) to something else (e.g., (2f, –5f, 0)).

  7. Prescribed Apex Height

    • When you want a projectile’s highest point to be at a specific Y, use the arc‐ceiling solvers. This is especially useful for:

      • Curved arrow shots over cover.

      • Jump arcs for AI characters (treat them as “projectiles”).

  8. Fixed Flight Time

    • If you need the projectile to take exactly t seconds to reach the target (e.g., synchronized explosion), use Solution(start, target, gravity, flightTime).

  9. Error Handling

    • Always check return booleans or solution counts. If a solver returns false or 0, either the target is out of range, the angle/speed combination is impossible, or parameters are invalid (e.g., zero speed or zero gravity).

PreviousBallisticsNextBallistics Aim

Last updated 2 days ago