Search Unity

  1. Dismiss Notice
  2. All Pro and Enterprise subscribers: find helpful & inspiring creative, tech, and business know-how in the new Unity Success Hub. Sign in to stay up to date.
    Dismiss Notice
  3. Dismiss Notice

Calculating trajectory angle to hit target position - Angle always -90?

Discussion in 'Physics' started by SovietSpartan, Dec 11, 2015.

  1. SovietSpartan

    SovietSpartan

    Joined:
    May 2, 2014
    Posts:
    17
    Hello, i've been breaking my head the last few nights trying to get an aiming system for a World of warships-esque game.

    The main idea is that the player points through a crosshair to a target destination (These sometimes can exceed 3000+ meters) and the character he/she is using must point torwards the necessary angle to hit the target position in 3D space.

    Since the character always turns torwards the target destination, the former is always in the line of fire so the trajectory of the projectile is a 2D parabola.

    I tried to implement the equation found here https://en.wikipedia.org/wiki/Traje...#Angle_required_to_hit_coordinate_.28x.2Cy.29 but the angle always comes out as -90 Degrees. I checked the code countless times but i just can't find anything wrong.

    If its any help, my projectile has a mass of 2, and it's fired at a speed of 570 m/s (which is assigned by doing a rigidody.velocity = shootPosition.transform.forward*570).

    Here's the code:

    Code (CSharp):
    1.     float getAngle(){
    2.         float x = Vector3.Distance(endPos,startPos);
    3.         float y = endPos.y;
    4.         float z = endPos.z;
    5.         float vel = speed;
    6.  
    7.         float angle01;
    8.         float angle02;
    9.         float angleResult;
    10.  
    11. // Calculate the angles, then pick the lowest one so we don't end up pointing at 90 degrees
    12.         angle01 = Mathf.Atan((Mathf.Pow (vel, 2) + Mathf.Sqrt (Mathf.Pow (vel, 4) - (Physics.gravity.y * (Physics.gravity.y * Mathf.Pow (x, 2) + (2 * y) * Mathf.Pow (vel, 2))))) / (Physics.gravity.y * x));
    13.  
    14.         print ("Angle 01 : " + angle01);
    15.  
    16.         angle02 = Mathf.Atan((Mathf.Pow (vel, 2) - Mathf.Sqrt (Mathf.Pow (vel, 4) - (Physics.gravity.y * (Physics.gravity.y * Mathf.Pow (x, 2) + (2 * y) * Mathf.Pow (vel, 2))))) / (Physics.gravity.y * x));
    17.  
    18.         print ("Angle 02 : " + angle02);
    19.  
    20.         angleResult = Mathf.Min (angle01,angle02);
    21.  
    22.         print ("Angle : " + angleResult*Mathf.Rad2Deg);
    23.         return angleResult * Mathf.Rad2Deg;
    24.     }

    Thanks in advance for any help!!
     
  2. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,615
    You realise you picked the lob formula over the easier to implement and more likely intended angle of reach formula.

    The formula you picked would be used if you wanted the projectile to come down on top of the target, rather than angle of reach which fires directly at the target, putting enough angle to counter distance/gravity.

    I have working code for lob around. not here. can post if you cant get it right. I ended up breaking it down into multiple parts rather than doing it one line of code. I suspect you missed some braces, but I cbf getting my head around it...
     
  3. SovietSpartan

    SovietSpartan

    Joined:
    May 2, 2014
    Posts:
    17
    Seems like angle of reach is the right path for me, haha.
    I tried the Angle of reach formula from the wiki page i posted up there. However now the angle is always 0 degrees.
    I forgot to mention that there's a height difference between the shooting position and the target position which i'm believing has something to do with it.
    Here's the code so far:
    Code (CSharp):
    1.     float getAngle(){
    2.         float gravity = Physics.gravity.y;
    3.         float distance = Vector3.Distance (endPos, startPos);
    4.         float angle = (1/2)*Mathf.Asin ((gravity * distance) / (speed*speed));
    5.         return angle*Mathf.Rad2Deg;
    6.     }
    What could be wrong now?
     
  4. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,615
    Code (csharp):
    1.  
    2.  
    3.     public static bool CalculateTrajectory(float TargetDistance, float ProjectileVelocity, out float CalculatedAngle)
    4.     {
    5.         CalculatedAngle = 0.5f * (Mathf.Asin ((-Physics.gravity.y * TargetDistance) / (ProjectileVelocity * ProjectileVelocity)) * Mathf.Rad2Deg);
    6.         if(float.IsNaN(CalculatedAngle))
    7.         {
    8.             CalculatedAngle = 0;
    9.             return false;
    10.         }  
    11.         return true;
    12.     }
    13.  
    14.  
     
    Danirey likes this.
  5. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,615
    here's the messy (un-optimised) lob code I wrote a way back as well.
    Code (csharp):
    1.  
    2.  
    3.         float actualDistance = Vector3.Distance(transform.position, TargetCenter);
    4.        
    5.         float v = WeaponSystem.Projectile.Velocity;
    6.         float g = Physics.gravity.y;
    7.         float x = actualDistance;
    8.         float y = 0;
    9.        
    10.         float v2 = v * v;
    11.         float v4 = v * v * v * v;
    12.        
    13.         float gx2 = g * x * x;
    14.         float yv2 = 2 * y * v * v;
    15.         float gx = g*x;
    16.        
    17.         float res =  Mathf.Sqrt(v4 - g * (gx2 + yv2));
    18.         float res1 = v2 + res;
    19.         float res2 = res1 / gx;
    20.        
    21.         float trajectoryAngle = Mathf.Atan(res2) * 180 / Mathf.PI;
    22.        
    23.         if(float.IsNaN(trajectoryAngle))
    24.         {
    25.             trajectoryAngle = 0;
    26.    
    27.         }
    28.  
    29.  
     
    Danirey likes this.
  6. SovietSpartan

    SovietSpartan

    Joined:
    May 2, 2014
    Posts:
    17
    The angle of reach code is the one i need it seems.
    I managed to get it working, however the problem now is that there's a height difference, and the formula doesn't take that into account. I tried investigating on it but i can't find any answers on it.

    Any help on that is totally appreciated! :)
     
  7. JamesLeeNZ

    JamesLeeNZ

    Joined:
    Nov 15, 2011
    Posts:
    5,615
    The formula doesnt need to account for height difference.

    If its not hitting accurately, its more likely that the center of the target/distance you are using isnt quite right.

    The other thing that can cause misses, is the projectile velocity isnt great enough to make the full distance you are trying to cover.
     
  8. SovietSpartan

    SovietSpartan

    Joined:
    May 2, 2014
    Posts:
    17
    Just got it working, haha.
    It seems that the way i was rotating the object was not the right one.
    In my game i need the character to look at a Game Object so that it can point. So i have another object parented to my character that calculates the firing angle and spawns an empty in its forward. I had to change the empty's Z axis position to like 20000 and now my character points almost perfectly to the right angle.

    Aside from that i also needed my angle calculator to look at, at the same time, to the ending position of the projectile (which is where the raycast from the crosshair collides with something).

    Here's the code in case anyone needs something like this in the future:

    Code (CSharp):
    1.     public Vector3 endPos;
    2.     public Vector3 startPos;
    3.     public float speed;
    4.     public float distance;
    5.  
    6. void Update(){
    7.  
    8.         float dist = Vector3.Distance (startPos, endPos);
    9.         distance = dist;
    10.  
    11. //Here we assign the rotation
    12.             Vector3 relativePos = endPos - transform.position;
    13.             Quaternion rotation = Quaternion.LookRotation(relativePos);
    14.             transform.rotation = rotation;
    15.             var tempRot = transform.eulerAngles;
    16.  
    17.                        //This line of code is so that we can point torwards the target position, while also pointing to the                            firing angle
    18.             tempRot.x = transform.eulerAngles.x-getAngle();
    19.             transform.eulerAngles = tempRot;
    20. }
    21. //Here we get the angle
    22.     float getAngle(){
    23.         float gravity = 9.81f;
    24.         float angle = 0.5f*(Mathf.Asin ((gravity * distance) / (speed*speed)));
    25.         return angle*Mathf.Rad2Deg;
    26.      
    27.     }
     
    Last edited: Dec 16, 2015
  9. Panthesilea

    Panthesilea

    Joined:
    May 31, 2013
    Posts:
    11
    Is it possible to calculate the target angle when surface is like a sphere and it has a gravity center?
     
unityunity