- Home /
How can I solve ballistic angle and velocity to hit a specific point after a specific amount of time?
I have two objects, missile
and target
. I want to launch missile
at target
and have it arrive in exactly X seconds.
I know the locations of both objects, I know the mass of missile
, and I know the value of gravity. Does anyone have a C# method that calculates the angle and force required to hit the target after the exact given duration?
I am using the physics engine in Unity3D, so I don't need to write code to move the projectile. I just need to know how to work out the initial Vector.
Super useful page for this: check out the "time of flight" section, and angle required sections in particular https://en.wikipedia.org/wiki/Trajectory_of_a_projectile
Answer by mrpmorris · Dec 16, 2016 at 02:13 PM
Bah. I can't believe how simple the answer was. My problem was that I assumed using Rigidbody.AddForce on a stationary object would be the equivalent of setting Rigidbody.velocity - it's not.
So, using basic school physics, here is the answer.
void Update()
{
if (Input.GetMouseButton(0))
{
Vector3 vector = CalculateTrajectoryVelocity(transform.position, Target.transform.position, 5);
Rigidbody.velocity = vector;
}
}
Vector3 CalculateTrajectoryVelocity(Vector3 origin, Vector3 target, float t)
{
float vx = (target.x - origin.x) / t;
float vz = (target.z - origin.z) / t;
float vy = ((target.y - origin.y) - 0.5f * Physics.gravity.y * t * t) / t;
return new Vector3(vx, vy, vz);
}
Answer by SpankPack · Dec 15, 2016 at 11:40 PM
You have to experiment with speeds of the projectile OR calculate the speed needed to get the time required. Standard highschool physics. Hint: horizontal velocity is: velocity * cos(a) where a is your cannon angle. Velocity is distance divided by time. You know distance you know time. Calc the angle a.
Then check the below autoaimer. This script is shooting hamburgers on passing players from a barrel of a cannon that turns towards the player real time. It uses the cannonmans rule, but does not correct too much for targets height.
using UnityEngine; using System.Collections;
public class AutoAimer : MonoBehaviour {
public Transform target = null; // The poor object to be aimed at
public float range = 100f; // The range the aimer should start aiming. 100f -ish
public float aimRotationSpeed = 50.0f; // 50f -ish
public Fomp _Fomp; // The script taking care of shooting (fomping Hamburgers at you)
Quaternion targetRotation;
float distance;
Vector3 newDirection;
float theAngle;
float myProjectileSpeed = 30f;
Collider[] targetColliders; // The passing players
bool isTargetFound = false;
void Start(){
//_Fomp may have to be instantiated.
_Fomp = GameObject.FindObjectOfType (typeof(Fomp)) as Fomp;
}
void Update ()
{
if (!isTargetFound && _Fomp != null) {
//Tell the Fomper to stop wasting Hamburgers
_Fomp.Fomper(false);
GetTarget ();
}
else
{
//Tell the fomper to start fomping Hamburgers
if(_Fomp != null){
_Fomp.Fomper(true);
}
//Check if the target is still on range.
if (distance > range && _Fomp !=null)
{
isTargetFound = false;
//Start acquiring other targets
_Fomp.Fomper(false); // Stop fomping too
//Debug.Log ("----->Target out of range.");
}
}
if (_Fomp == null)
{
Debug.LogError("ZOMG! Autoaimer.cs says that _Fomp (Script) has not been instantiated!");
}
if (target != null) {
distance = Vector3.Distance (transform.position, target.position);
theAngle = Mathf.Asin ((9.81f * distance) / Mathf.Pow(myProjectileSpeed, 2.0f)) / 2.0f ;
if (distance <= range)
{
Vector3 newDirection = new Vector3(target.position.x,target.position.y + Mathf.Tan (theAngle) * distance , target.position.z) - transform.position;
//Debug.Log ("Distance is: " + distance + " m" + " Corr Angle: " + theAngle + " target pos:" + target.position);
if (newDirection != Vector3.zero)
{
targetRotation = Quaternion.LookRotation (newDirection, Vector3.up);
transform.rotation = Quaternion.RotateTowards (transform.rotation, targetRotation, aimRotationSpeed * Time.deltaTime);
}
}
}
}
void GetTarget()
{
if (isTargetFound) // We do not have to searc, we have a target
{
return;
}
targetColliders = Physics.OverlapSphere (transform.position, range); // Find any collider in 100m range
foreach (Collider hit in targetColliders) {
if (hit.GetComponent<Rigidbody>() != null)
{
// if(hit.name != "Hamburger" && hit.name != "PunishMe" && hit.name != "Roof") // { // Debug.Log ("----->AutoAimer found these colliders in range: " + hit.name); // } if (hit.name.Contains("Player")) // Network instantiated player with a collider component in the transform. ( Not a specific empty with a collider) { //Debug.Log ("----->AutoAimer found a player in range." + hit.name); isTargetFound = true; target = hit.transform; } } } } }
Your answer
![](https://koobas.hobune.stream/wayback/20220612102815im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Is there way to curve Raycast? 3 Answers
2D 360 degress platformer example needed 0 Answers
Rigid body Help Please 1 Answer
Help with optimize code 1 Answer
How do I solve the Box Collider (3D) Edge / Corner Collisions problem? 5 Answers