- Home /
How do I calculate the arc of a throw, given two positions and an angle of attack?
I want to save you many hours of research and hours going through physics calculations 
 PROBLEM:
 I have a player on the screen and he moves around a cross-hair target across the ground to the location where he wants to attack another object/player. All I want to tell the ball is where the destination is and what the degree-angle into the air I want to throw the ball and I want the ball do to the rest of the calculations.
 SETUP:
 Create a script called "ThrowArcBehavior", then create a sphere and apply this script to that sphere..... That's it!!!
 You could of course, adjust the gravity, the angle, or anything else, but this should help to get you started!
 SPECIAL THANKS TO:
 ShervinM, who helped to provide the basis for this code in 3d geometry. Original 2d code and the conversation can be found here: Link To Webpage 
 CODE:
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class ThrowArcBehavior : MonoBehaviour
 {
     //Gravity of the simulation
     public float gravity = 9.8f;
     // save CPU resources by only running the code when InFlight=true
     public bool inFlight;
     // the angle thrown into the air
     public float targetInclination;    
     // the destination of our target
     public Vector3 targetDestination;
     
     // IF RUNNING COLLISSIONS ie: if you want to trigger something like "send a message to the player if the ball or rock hits him"
     // the radius to send the collission message
     public float radiusToTrigger;
     // the layerMask to check for collissions.
     private LayerMask layerToCheck;
 
     private Vector3 startPosition;
     private float xVelocity;
     private float yVelocity;
     private float flightDuration;
     private float elapsedTime;
 
     
     // Start is called before the first frame update
     void Start()
     {
         // IF THIS is a Stand-Alone test then run this code below....
         // Vector3 testDestination = new Vector3 (5f,1f,5f);
         // Initialize (45f, testDestination, 5f, LayerMask.GetMask("default"));
         inFlight = true;
         startPosition = transform.position;
         elapsedTime = 0f;
         CalculateVariables();
     }
 
     // Update is called once per frame
     void Update()
     {
         if (inFlight) 
         {
             UpdateProjectilePosition();
         }
         
     }
 
     public void Initialize(float inclination, Vector3 destination, float radiusOfTrigger, LayerMask layerToCheckAgainst) 
     {
         targetInclination = inclination;
         targetDestination = destination;
         radiusToTrigger = radiusOfTrigger;
         layerToCheck = layerToCheckAgainst;
         inFlight = true;
     }
 
     public void CalculateVariables() 
     {
 
         // CALCULATIONS if there are DIFFERENT START and END HEIGHTS
 
         // Calculate the range from the projectile to the target by zero-ing each out in their y-axis
         Vector3 zeroedOrigin = new Vector3(startPosition.x, 0, startPosition.z);
         Vector3 zeroedTarget = new Vector3(targetDestination.x, 0, targetDestination.z);
         Vector3 zeroedDirection = (zeroedTarget - zeroedOrigin).normalized;
 
         float angleRad = targetInclination * Mathf.Deg2Rad;
         float heightDifference = startPosition.y - targetDestination.y;
         float targetDistance = Vector3.Distance(transform.position, targetDestination);
         float targetRange = Vector3.Distance(zeroedOrigin, zeroedTarget);
 
         // Calculate the velocity needed to throw the object to the target at specified angle.
         // Velocity can be solved by re-arranging the general equation for parabolic range:
         // https://en.wikipedia.org/wiki/Range_of_a_projectile
         float projectile_Velocity
             = (Mathf.Sqrt(2) * targetRange * Mathf.Sqrt(gravity) * Mathf.Sqrt(1 / (Mathf.Sin(2 * angleRad)))) /
               (Mathf.Sqrt((2 * targetRange) + (heightDifference * Mathf.Sin(2 * angleRad) * (1 / Mathf.Sin(angleRad)) * (1 / Mathf.Sin(angleRad)))));
 
         // Extract the X  Y componenent of the velocity
         xVelocity = projectile_Velocity * Mathf.Cos(angleRad);
         yVelocity = projectile_Velocity * Mathf.Sin(angleRad);
 
         // Calculate flight time.
         flightDuration = targetRange / xVelocity;
 
         // Rotate projectile to face the target.
         transform.rotation = Quaternion.LookRotation(zeroedDirection);
     }
 
 
     public void UpdateProjectilePosition() 
     {
         if (elapsedTime >= flightDuration) 
         {
             // if we finished our our flight/trajectory of the item thrown, then lets end it
             ProjectileLanded();
             return;
         }
         // However if NOT enough time has elapsed to complete the arc throw....
         
         float x = 0f;
         float y = (yVelocity - (gravity * elapsedTime)) * Time.deltaTime;
         float z = xVelocity * Time.deltaTime;
         // May need to switch around Z and X axis depending on the "forward-direction" of the object
         this.transform.Translate(x, y, z);
         elapsedTime += Time.deltaTime;
     }
 
     public void ProjectileLanded() 
     {
         Debug.Log("This Projectile Landed");
         inFlight = false;
         //Physics.OverlapSphere ()
     }
 }
 
Your answer
 
 
              koobas.hobune.stream
koobas.hobune.stream 
                       
               
 
			 
                