Answers for "Formula to calculate a position to fire at?"
http://answers.unity.com/questions/296949/how-to-calculate-a-position-to-fire-at.html
The latest answers for the question "Formula to calculate a position to fire at?"Answer by PoyrazGoksel
http://answers.unity.com/answers/1705729/view.html
This is what i did using simple maths and physics end result is 100% precise
/// <summary>
/// <para>Since Laser speed is constant no need to calculate relative speed of laser to get interception pos!</para>
/// <para>Calculates interception point between two moving objects where chaser speed is known but chaser vector is not known(Angle to fire at * LaserSpeed"*Sort of*")</para>
/// <para>Can use System.Math and doubles to make this formula NASA like precision.</para>
/// </summary>
/// <param name="PC">Turret position</param>
/// <param name="SC">Speed of laser</param>
/// <param name="PR">Target initial position</param>
/// <param name="VR">Target velocity vector</param>
/// <returns>Interception Point as World Position</returns>
public Vector3 CalculateInterceptionPoint3D(Vector3 PC, float SC, Vector3 PR, Vector3 VR)
{
//! Distance between turret and target
Vector3 D = PC - PR;
//! Scale of distance vector
float d = D.magnitude;
//! Speed of target scale of VR
float SR = VR.magnitude;
//% Quadratic EQUATION members = (ax)^2 + bx + c = 0
float a = Mathf.Pow(SC, 2) - Mathf.Pow(SR, 2);
float b = 2 * Vector3.Dot(D, VR);
float c = -Vector3.Dot(D, D);
if ((Mathf.Pow(b, 2) - (4 * (a * c))) < 0) //% The QUADRATIC FORMULA will not return a real number because sqrt(-value) is not a real number thus no interception
{
return Vector2.zero;//TODO: HERE, PREVENT TURRET FROM FIRING LASERS INSTEAD OF MAKING LASERS FIRE AT ZERO!
}
//% Quadratic FORMULA = x = ( -b+sqrt( ((b)^2) * 4*a*c ) ) / 2a
float t = (-(b) + Mathf.Sqrt(Mathf.Pow(b, 2) - (4 * (a * c)))) / (2 * a);//% x = time to reach interception point which is = t
//% Calculate point of interception as vector from calculating distance between target and interception by t * VelocityVector
return ((t * VR) + PR);
}Sun, 08 Mar 2020 03:55:33 GMTPoyrazGokselAnswer by mouurusai
http://answers.unity.com/answers/299920/view.html
http://wiki.unity3d.com/index.php/Calculating_Lead_For_ProjectilesSat, 11 Aug 2012 06:39:53 GMTmouurusaiAnswer by Bunny83
http://answers.unity.com/answers/299922/view.html
Ok, I finally converted my CalculateInterceptCourse function from c++ to c#, simplified it a bit and fixed a problem so it always picks the best course when there are two available.
public static Vector3 CalculateInterceptCourse(Vector3 aTargetPos, Vector3 aTargetSpeed, Vector3 aInterceptorPos, float aInterceptorSpeed)
{
Vector3 targetDir = aTargetPos - aInterceptorPos;
float iSpeed2 = aInterceptorSpeed * aInterceptorSpeed;
float tSpeed2 = aTargetSpeed.sqrMagnitude;
float fDot1 = Vector3.Dot(targetDir, aTargetSpeed);
float targetDist2 = targetDir.sqrMagnitude;
float d = (fDot1 * fDot1) - targetDist2 * (tSpeed2 - iSpeed2);
if (d < 0.1f) // negative == no possible course because the interceptor isn't fast enough
return Vector3.zero;
float sqrt = Mathf.Sqrt(d);
float S1 = (-fDot1 - sqrt) / targetDist2;
float S2 = (-fDot1 + sqrt) / targetDist2;
if (S1 < 0.0001f)
{
if (S2 < 0.0001f)
return Vector3.zero;
else
return (S2) * targetDir + aTargetSpeed;
}
else if (S2 < 0.0001f)
return (S1) * targetDir + aTargetSpeed;
else if (S1 < S2)
return (S2) * targetDir + aTargetSpeed;
else
return (S1) * targetDir + aTargetSpeed;
}
Additionally here's another function which might be useful: FindClosestPointOfApproach
public static float FindClosestPointOfApproach(Vector3 aPos1, Vector3 aSpeed1, Vector3 aPos2, Vector3 aSpeed2)
{
Vector3 PVec = aPos1 - aPos2;
Vector3 SVec = aSpeed1 - aSpeed2;
float d = SVec.sqrMagnitude;
// if d is 0 then the distance between Pos1 and Pos2 is never changing
// so there is no point of closest approach... return 0
// 0 means the closest approach is now!
if (d >= -0.0001f && d <= 0.0002f)
return 0.0f;
return (-Vector3.Dot(PVec, SVec) / d);
}
I've made a [small test application][1] which shows the difference between the "true" interception point / course and the approximation of cassius. You can change the speed of the target and the speed of your bullet. When you have at least a 5 times higher bulletspeed the result of the simple prediction is enough.
Usually the speeds don't differ that much. In Quakelife for example the player's runspeed is 320 and the rocketspeed is 1000 --> x3.125 The original Quake3 had even less: rocketspeed 800 --> x2.5 On top of that in Quake it's possible to move even faster than the rocket can fly ;)
***edit***
I've exported [a package][2] of the sample application. The script is quite messy. Most stuff is just there for the visualization or to distinguish the two different methods ;)
[1]: https://bunny83.github.io/UnityWebExamples/InterceptExample/
[2]: https://github.com/Bunny83/UnityWebExamples/blob/master/InterceptExample/Intercept.unitypackageSat, 11 Aug 2012 02:46:33 GMTBunny83Answer by cassius
http://answers.unity.com/answers/298839/view.html
Actually I wrote a script that does almost exactly what you want. [Unity3D Enemy AI Script to Anticipate Playerâ€™s Future Position][1]. Basically it will calculate the player's speed (though you could change it to whatever) and takes into account the speed of the enemy's bullet. It then shoots the bullet towards where the player would be once the bullet reaches that distance.
I'm sure it can be streamlined better but hope it helps. It's javascript.
[1]: http://www.superspacetrooper.com/2012/06/unity3d-enemy-ai-script-to-anticipate-players-future-position/Thu, 09 Aug 2012 00:11:57 GMTcassiusAnswer by Seth-Bergman
http://answers.unity.com/answers/297026/view.html
void CalculateAimPos(Vector3 targetPos, Quaternion targetRot, int targetSpeed, Vector3 myPos)
{
Vector3 aimPos = (targetPos + myPos) * .9;
desiredRotation = Quaternion.LookRotation(aimPos);
}
I believe it's as simple as that
of course as far as I can see here you are not passing the (aimPos) to the bullet yet, to know where to end up.. I assume you are planning this..
Bigger problem though, is that all your declarations are in javascript! but this looks to be a c# script..
to declare your vars, change it to:
Vector3 targetPos = myTarget.position;
//Find target's rotation
Quaternion targetRot = Quaternion.LookRotation (myTarget.position - transform.position, Vector3.up);
//Find target's speed
int targetSpeed = (int) myTarget.gameObject.GetComponent().mySpeed;
//Find tower's position
Vector3 myPos = transform.position;
hope this helpsMon, 06 Aug 2012 06:50:00 GMTSeth-Bergman