- Home /
Math Genius NEEDED! Algorithm problem with parabola
Hi all, I am trying to make a targeting system with an artillery turret in which there is a set distance, velocity, and gravity acceleration. This targeting system is supposed to calculate the angle in which the turret should fire at to hit the target. I am having some trouble as it is either undershooting or overshooting the target, and am wondering if I have the ratios of real world values like Unity velocity to Real World velocity mixed up or if the equation is wrong. Here is my code:
public class test : MonoBehaviour {
public float angle;
public float g = Physics.gravity.y;
public float v = 1f;
public float d;
public Transform firePoint;
public Transform target;
public TestAAT3 obj;
// Use this for initialization
void Start () {
obj = FindObjectOfType<TestAAT3>();
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.Alpha1))
{
CalculateAngle();
}
}
//d = distance between firepoint and target
//g = gravitational acceleration
//v = given velocity
//angle = theta
public void CalculateAngle()
{
d = Vector3.Distance(firePoint.position, target.position);
angle = (1/2) * Mathf.Asin((g * d) / (Mathf.Pow(v_, 2)));
Debug.Log(d);
obj.Fire(d);
}
}
Any and ALL help is appreciated. I've looked at wikipedia, khan academy videos, etc. Nothing helps!
Your angle seems to be calculated correctly, unless the firePoint and target are in different elevations (different z values). The formula you use is correct, but only for objects of the same elevation. $$anonymous$$aybe the problem is with your obj.Fire function?
Answer by Bunny83 · Jul 22, 2017 at 08:54 PM
Well first of all "g" should be the value of the acceleration. This should be positive. There is no direction information in a single value. You seem to use the y component of the Physics gravity vector which is usually negative.
Next thing is the formula you use only works when both your firePoint as well as your target are on the exact same height. Also keep in mind when you rely on Unity's physics engine for the actual simulation that this assumes no drag at all.
You also need to check if the term inside ASin is not lower than "-1" or greater than "1", In that case the target can't be reached at all. Also ASin would return a NaN in that case.
If the height of the two points can be different you have to use this one instead. Of course here a similar check has to be done. You can only reach the target when the root has a real value (i.e. the value inside the root has to be 0 or positive). If the root is a complex root the target can't be reached,
Finally what do you actually pass to your "Fire" method? Currently you pass the distance between you and the target. Shouldn't you somehow pass the angle?
ps: Never use "pow" for simple powers. This (Mathf.Pow(v_, 2))
should be simply
(v_ * v_)
Is there a disadvantage for using $$anonymous$$athf.Pow(v_, 2)
ins$$anonymous$$d of (v_ * v_)
for a simple power?
Yes, about a factor of "10". First of all $$anonymous$$athf.Pow is (like almost all methods of $$anonymous$$athf) just a wrapper for System.$$anonymous$$ath.Pow just casted to float. All System.$$anonymous$$ath methods work with double. It's literally defined as:
public static float Pow(float f, float p)
{
return (float)$$anonymous$$ath.Pow((double)f, (double)p);
}
Though the slight casting overhad is not the worst. A simple native floating point multiplication will be carried out directly inline by FPU opcodes while Pow is an actual method call. The main problem is that Pow does work with non-integer powers as well. That means the method has to decompose the power into an integer part and a fractional part.
I ran a quick test and did 1$$anonymous$$ Pow with "2" as power in a loop and it took 733k ticks on my machine. By doing a simple "manual square" (i.e. "x * x") it took only 66k ticks. It roughly translated to about 70 ms vs 6 ms.
ps: decompose means if you have a power of "3.2" it would have to split that power into "3" and "0.2". It can then do a simple integer power with the 3 and in addition calculate the 5th root of the base ((1 / 0.2) --> 5th root). As you might know multiplying two numbers with the same base but different exponent is the same as when you just add the two exponents together. So (B^x * B^y)
is the same as B^(x+y)
.
Your answer
Follow this Question
Related Questions
Find angle between two gameobjects? 1 Answer
Angle calculation not working?? 2 Answers
Vertical Angle Between two game objects 2 Answers
Quaternion using global values instead of local. Please help :( 0 Answers
Drawing a Mandelbrot Set problem 0 Answers