Comments and 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 comments and 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 GMTPoyrazGokselComment by cassius on cassius's answer
http://answers.unity.com/comments/301785/view.html
@Bunny83
Right-on. I see what you're saying about this script vs mine. I guess the way my game works the shots are always accurate, but I can clearly see in your example why it wouldn't have worked for the OPs needs.Tue, 14 Aug 2012 14:23:43 GMTcassiusComment by Bunny83 on Bunny83's answer
http://answers.unity.com/comments/301513/view.html
I've edited my answer and added a package which contains the sample scene. Good luck ;)Tue, 14 Aug 2012 02:05:32 GMTBunny83Comment by Alex_Gray on Alex_Gray's answer
http://answers.unity.com/comments/301310/view.html
It's not working the way it did on your application :(
Edit: Do you think you'd be able to upload your project so I can see how you set everything up please?Mon, 13 Aug 2012 21:44:20 GMTAlex_GrayComment by Alex_Gray on Alex_Gray's answer
http://answers.unity.com/comments/301197/view.html
I like your application, and I also want to mention, u shouldn't worry about the path direction changing, because it moves in a straight line from waypoint to waypoint... so it will work! But I have a question about the code... I can't get it to work... I've never dealt with creating a Vector3 that takes arguments... how do I do it, I keep getting an errorMon, 13 Aug 2012 19:38:29 GMTAlex_GrayAnswer 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 GMTBunny83Comment by Bunny83 on Bunny83's answer
http://answers.unity.com/comments/299876/view.html
@cassius: Your method is never 100% correct, sorry ;) You calculate time you need to the target from the actual position of you and of the target, but the time until you reach the target can be more or less than that depending on if the object moves away or comes closer.
Your approach will improve when you do your steps multiple times.
Again, if the speed difference is big (so the projectile is times faster than the enemy) the error is almost neglectable, but when it's just double the speed or less your method fails. I've made an example. I will post an answer myself. It just takes some more time ;)Fri, 10 Aug 2012 23:56:34 GMTBunny83Comment by cassius on cassius's answer
http://answers.unity.com/comments/299626/view.html
@Bunny83: I'm not sure what you mean by my script becoming inaccurate. It works 100% of the time in my game exactly as expected. But of course understanding that Alex_Gray is looking for something that changes direction, I think you're right that it's almost impossible to write a formula for.
Wouldn't the iterative approach you mentioned basically result in a heat-seeking missile-style action? Or maybe that's what Alex_Gray is actually after?Fri, 10 Aug 2012 16:55:42 GMTcassiusComment by Bunny83 on Bunny83's answer
http://answers.unity.com/comments/299400/view.html
@cassius: This is actually very inaccurate. When the bullet is very fast it's almost neglectable, but when they move at around the same speed or just 2 or 3 times different it might get very inaccurate depending on the angle.
@Alex_Gray: What do you mean by **not in a straight line**? Do you mean you have a tower defence game and an arbitrary path the enemies will follow? in this case it's almost impossible to create a formula that calculates this. In such a case it's really better to use something like cassius said, but with two changes:
- You need to be able to calculate the position of the enemy at a specific time in the future.
- You have to use an iterative approach.
So you calculate the distance to the target and then you get the time the bullet would take. now move the enemy ahead of time to the position it will be after that time and then repeat.
Each iteration it will get closer to the real interception point.
---
If your enemy moves in one direction, you can calculate an interception course. I've written
<a href="https://dl.dropbox.com/u/7761356/UnityAnswers/Code/Interception.cpp" rel="nofollow">such a function a while ago in C++</a> and wasn't in need to convert it to C#. If you're interested i can convert it, or do it yourself ;)
Actually I shouldn't post the code it since it's the evil code that enables bot programmers to create aimbots for projectile weapons like rocket launchers ;)Fri, 10 Aug 2012 02:23:07 GMTBunny83Comment by Alex_Gray on Alex_Gray's answer
http://answers.unity.com/comments/299380/view.html
Unfortuantly, I couldn't use it... It would work if it moved in straight line, but it won't help to calculate it's movement on a 2D grid :( I can't figure out the part that was left out... I'm still trying to find the right formulaFri, 10 Aug 2012 01:42:27 GMTAlex_GrayComment by Alex_Gray on Alex_Gray's answer
http://answers.unity.com/comments/299372/view.html
Well that sounds like what I am looking for, of course it's the opposite way :) but that shouldn't be a problem, and I use C# but I'm sure I can recode it! I'll check it out!Fri, 10 Aug 2012 01:04:34 GMTAlex_GrayAnswer 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 GMTcassiusComment by Alex_Gray on Alex_Gray's answer
http://answers.unity.com/comments/298834/view.html
Yes I changed all of the "var" but the problem with the first part:
> void CalculateAimPos(Vector3 targetPos, Quaternion targetRot, int targetSpeed, Vector3 myPos)
{
Vector3 aimPos = (targetPos + myPos) * .9;
desiredRotation = Quaternion.LookRotation(aimPos);
}
well first off it'd be (targetPos - myPos), but the enemy has a set speed, so if it went higher, the bullet wouldn't hit the enemy on time... and the bullet has a speed that can change as well. so what I'm asking is there a formula to find the Postion an enemy will be at given it's own speed and direction while also taking in consideration the bullet's speed?Wed, 08 Aug 2012 23:50:47 GMTAlex_GrayAnswer 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