Search Unity

Projectile Range Formula?

Discussion in 'Scripting' started by Iron-Warrior, Jan 8, 2011.

  1. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    Howdy Unityers,

    Been trying to work it out for about an hour or so, but just can't seem to remember how to calculate projectile range (Physics 12 was alot longer ago than I remember I guess). Basically what I want is the ability to fire a projectile at Angle X, calculate how long it's going to stay in the air and where it's going to land. Values I have are the: Y acceleration (-9.81), the landing position, the initial velocity (I can just set it directly through rigidbody.velocity), initial position. What I need is the angle to fire it at in order to hit the landing position. My game map is completely flat, so that makes it a bit easier, and I don't intend to have any drag on the projectile. I'm guessing that this can be solved in 2 Dimensions...but for the life of me I can't figure it out. Does anyone have any experience with this?

    Thanks for any help!
     
  2. Clydeicus

    Clydeicus

    Joined:
    Feb 21, 2010
    Posts:
    5
    You break it down into X and Y velocities first, by taking the sine and cosine of your angle. You then use the equation
    d = v + 0.5 * at^2 where v is the initial Y velocity, a is your gravity value, and d is the distance which you'd set to 0 to solve for t

    rearranging this, you get sqrt(-2v / a) = t

    t here is the time it will take for the projectile to reach its high point. you can double that to get the total air time of the projectile, and then multiply by your initial X velocity, (no drag makes this nice and easy!) to get the range

    so your formula would be 2 * cos(angle) * V * sqrt(2 * sin(angle) * V / 9.81) = range of projectile
    and V is the initial velocity of your projectile
     
  3. K97

    K97

    Joined:
    Mar 24, 2016
    Posts:
    10
    This is giving me an error : transform.position assign attempt for 'mushroom2(Clone)' is not valid. Input position is { NaN, -3.650000, 0.000000 }.
    Any idea how to resolve it? @ClydeicusRex
     
  4. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    This is my ballistics class, there's a bit of commented out code because i have problems with target at different elevations and i'm trying to iron it out.

    should be fine for your needs, if i broke it with fiddling tell me and i'll post the previous version.

    hope it helps ;)

    edit: uhh, necro much? next time open a new thread and please explain your problem with you code snippet.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public static class Ballistics {
    4.  
    5.     // Note, doesn't take drag into account.
    6.  
    7.     /// <summary>
    8.     /// Calculates the trajectory.
    9.     /// </summary>
    10.     /// <returns>The trajectory.</returns>
    11.     /// <param name="start">Start.</param>
    12.     /// <param name="end">End.</param>
    13.     /// <param name="muzzleVelocity">Muzzle velocity.</param>
    14.     public static BallisticPath CalculateTrajectory(Vector3 start, Vector3 end, float muzzleVelocity){
    15.  
    16.        
    17.         float vSqr = muzzleVelocity * muzzleVelocity;
    18.  
    19.         //float xx = end.x - start.x;
    20.         //float xz = end.z - start.z;
    21.         //float x = Mathf.Sqrt(xx * xx + xz * xz);
    22.         float x = new Vector3(end.x - start.x, 0, end.z - start.z).magnitude;
    23.  
    24.         float y = start.y - end.y;
    25.         float g = Physics.gravity.magnitude;
    26.  
    27.         float uRoot = (vSqr * vSqr) - (g * (g * (x * x) + (2 * y * vSqr)));
    28.  
    29.         if (uRoot < 0.0f)
    30.             return null;
    31.  
    32.         float root = Mathf.Sqrt (uRoot);
    33.         float bottom = g * x;
    34.         //Debug.Log (string.Format ("Height:{0}, Gravity:{1}, Distance:{2}", y, g, x));
    35.  
    36.         return new BallisticPath (
    37.             (Mathf.Atan2 (bottom, vSqr + root) * Mathf.Rad2Deg),
    38.             (Mathf.Atan2 (bottom, vSqr - root) * Mathf.Rad2Deg)
    39.         );
    40.     }
    41.  
    42.     /// <summary>
    43.     /// Gets the ballistic path.
    44.     /// </summary>
    45.     /// <returns>The ballistic path.</returns>
    46.     /// <param name="startPos">Start position.</param>
    47.     /// <param name="forward">Forward direction.</param>
    48.     /// <param name="velocity">Velocity.</param>
    49.     /// <param name="maxTime">Total time to simulate.</param>
    50.     /// <param name="timeResolution">Time from frame to frame.</param>
    51.     public static Vector3[] GetBallisticPath(Vector3 startPos, Vector3 forward, float velocity, float maxTime, float timeResolution){
    52.  
    53.         Vector3[] positions = new Vector3[Mathf.CeilToInt(maxTime / timeResolution)];
    54.         Vector3 velVector = forward * velocity;
    55.         int index = 0;
    56.         Vector3 curPosition = startPos;
    57.         for (float t = 0.0f; t < maxTime; t += timeResolution) {
    58.          
    59.             if (index >= positions.Length)
    60.                 break;//rounding error using certain values for maxTime and timeResolution
    61.          
    62.             positions [index] = curPosition;
    63.             curPosition += velVector * timeResolution;
    64.             velVector += Physics.gravity * timeResolution;
    65.             index++;
    66.         }
    67.         return positions;
    68.     }
    69.     /// <summary>
    70.     /// Checks the ballistic path.
    71.     /// </summary>
    72.     /// <returns><c>false</c>, if ballistic path was blocked by an object on the Layermask, <c>true</c> otherwise.</returns>
    73.     /// <param name="arc">Arc.</param>
    74.     /// <param name="allyLM">Anything in this layer will block the path.</param>
    75.     public static bool CheckBallisticPath(Vector3[] arc, LayerMask allyLM){
    76.      
    77.         RaycastHit hit;
    78.         for (int i = 1; i < arc.Length; i++) {
    79.          
    80.             if (Physics.Raycast (arc [i - 1], arc [i] - arc [i - 1], out hit, (arc [i] - arc [i - 1]).magnitude) && GameMaster.IsInLayerMask(hit.transform.gameObject.layer, allyLM)) {
    81.                 Debug.DrawRay (arc [i - 1], arc [i] - arc [i - 1], Color.red, 10f);
    82.                 return false;
    83.             } else {
    84.                 Debug.DrawRay (arc [i - 1], arc [i] - arc [i - 1], Color.green, 10f);
    85.             }
    86.         }
    87.         return true;
    88.     }
    89.      
    90.  
    91.     public static float CalculateMaxRange(float muzzleVelocity){
    92.         return (muzzleVelocity * muzzleVelocity) / -Physics.gravity.y;
    93.     }
    94.      
    95. }
    96.  
    97. public class BallisticPath{//FIXME convert to struct;
    98.  
    99.     public float lowAngle;
    100.     public float highAngle;
    101.  
    102.     public BallisticPath (float lowAngle, float highAngle){
    103.  
    104.         this.lowAngle = lowAngle;
    105.         this.highAngle = highAngle;
    106.     }
    107.  
    108.     public override string ToString ()
    109.     {
    110.         return string.Format ("Low angle:{0}, High angle:{1}",lowAngle, highAngle);
    111.     }
    112. }
     
  5. Iron-Warrior

    Iron-Warrior

    Joined:
    Nov 3, 2009
    Posts:
    838
    hippocoder likes this.