Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by JtheSpaceC · Oct 25, 2014 at 03:25 PM · shooting2d-physics

Solve Intercept Point calculations c#, 2D top-down shooter (target leading)

Let me start by saying I'm looking for serious and specific help on this. I've Googled extensively and spent all week going over Answers, the Forum, and soloing the fundamental maths, quadratic equations, etc, and I can't come up with a usable answer, though I've felt close a bunch of times, I'm throwing in the towel. I know variations of this question have been asked multiple times before, but the best I can find are incomplete Java answers that I either can't complete or can't convert to c# correctly.

You can probably guess the problem. I want enemies (and allies) to lead their targets by an amount that considers their trajectory, speed, distance, and bullet speed. My workaround has been to just shoot at a spot 6 units in front of their targets, but this results in odd behaviour up close or far away.

  • I know the position of the shooter (a moving ship, if that matters. Frame to frame we can consider it stationary at its position, can't we?) .

  • I can give a value for bullet speed (it's actually the shooter's velocity + an Added force once on Enable, so it varies, but for simplicity I can say its velocity.magnitude averages 21).

  • I know the position, vector, and velocity of my target.

  • I can make the shooter look at any point I like, but I need to work out the appropriate point of intercept to feed this into my LookAtTarget() function.

I can't solve the maths for the Intercept Point, though. I figure you can solve any problem if there's just one unknown, but as far as I can see, I've two. I don't know the point my shooter is facing (because I don't know what the intercept point is) and I don't know the Time (t) until the shot and the target reach said point.

The equation of a circle and equation of a line are the routes I've been pursuing to find the intercept point, but I keep running into the problem of having 2 unknowns. Games everywhere have this feature though, so I know it must be solvable easily enough. Need specifics though, as you can hopefully see I do grasp most of the basic concepts and have spent a week working on it without success.

Thanks Kevin

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by incorrect · Oct 25, 2014 at 04:06 PM

Well, I've been searching for solution too and found this method. Also I think it is possible to solve this problem with a few steps:

  1. Find time a bullet will travel the distance between shooter and target.

  2. Find distance the target will travel in this time.

  3. Compare that distance with allowable error. If it is less than error - ok, you've found your intercept point else go to step 1, but this time calculate the time bullet will travel distance between shooter and previously found intercept point.

The idea of approach is that if you will define allowable error less than half of target's size, your bullet will hit it, just not right in the center. The number of steps depends on speeds of target and bullet. And it's not hard to take into account shooters speed, you just need to add it to the bullets speed during calculations described above.

Although I did not given you any code, I hope it will help you and give some new ideas.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image JtheSpaceC · Oct 25, 2014 at 04:57 PM 0
Share

The link you provided is one I'd spent a day tinkering with but I couldn't clear it of errors, or when I could, have it result in a working target lead. The maths and scripting is a bit beyond my understanding. I'm only at this 2 months.

Thanks for the suggestion. It's got the brain thinking in another direction, but I can't work out how your 3 steps results in a point. I think I see how you could say the distance in 1 & 2 is or isn't equal, but not how it results in a point when they are equal. Is step 2 meant to result in a Vector 3 point,perhaps?

avatar image incorrect · Oct 25, 2014 at 06:01 PM 0
Share

Ok, I'm going to code my approach tomorrow and will post it here, if you want. I'll better explain my approach with pictures, i guess.

avatar image JtheSpaceC · Oct 25, 2014 at 06:29 PM 0
Share

It would be extremely well appreciated if you were to do that. Thanks for the help.

avatar image JtheSpaceC · Oct 26, 2014 at 09:50 PM 0
Share

The best that I've come up with based on that idea is below, but it constantly results in a firing solution of the origin point (0,0,0). I'm sure there's many answers to my asking, what have I done wrong?

 //VARIABLES for FIRING SOLUTION
 
 public float accuracy = 0.6f;
 private float bulletToTargetTime;
 private float shooterToTargetDistance;
 private float targetTravelDistance;
 private Vector3 targetHeading;
 private float targetVelocity;
 private Vector3 newTargetPosition;
 private Vector3 firingSolution;
 private float shotSpeedAvg = 21f;
 
 void GetFiringSolution()
 {
 //step 1
 shooterToTargetDistance = (target.position -transform.position).normalized.magnitude;
 bulletToTargetTime = shooterToTargetDistance / shotSpeedAvg;
 
 //step2
 targetHeading = target.rigidbody2D.velocity;
 targetVelocity = target.rigidbody2D.velocity.magnitude;
 newTargetPosition = new Vector3 (targetHeading.x * targetVelocity * bulletToTargetTime, targetHeading.y * targetVelocity * bulletToTargetTime);
 
 //step3
 while(firingSolution == null)
 {
 if(Vector2.Distance(newTargetPosition, target.position) <=1/accuracy)
     {
     firingSolution = newTargetPosition;
     }
     else
     {
     shooterToTargetDistance = (newTargetPosition - transform.position).magnitude;
     bulletToTargetTime = shooterToTargetDistance / shotSpeedAvg;
     newTargetPosition = new Vector3 (targetHeading.x * targetVelocity * bulletToTargetTime, targetHeading.y * targetVelocity * bulletToTargetTime);
     return;
         }
 }
 Debug.Log (firingSolution);
 }
avatar image
0

Answer by FuzzyBunnySlippers · Oct 27, 2014 at 12:15 AM

There are two kinds of "intercept" problems in 2-D (at least normally).
(1) You want to fire a projectile at a position so that a target moving with constant velocity will intercept it. This is the basic "leading the target" problem.

(2) Same as (1), except your body has to rotate to the position you wish to fire at.

There are several sources for (1) on the web, just type "2d projectile intercept" into google and you will find several. One of my favorites is by Jeffrey Hantin and is located on Stack Overflow.

For (2) the problem is MUCH more difficult. If this is the problem you are trying to solve, then I share your pain in searching for an answer. I could not find one on the web, so I wrote one and posted it. The code/solution for it is written in C++, but I suspect that will not limit you using it in Unity (I develop for iPad/iPhone). The basic idea is the same as the solution for (1), but you need to take into account the additional rotation time as part of the equations, using the dot product of the facing vectors.

The basic idea works like this:

Assume your "entity" will rotate from its current facing position to face the intercept position and then fire immediately.

The Algorithm:

  • Pick a time of impact.

  • Calculate the final position of the target at that time given it is moving at constant velocity.

  • Calculate how long it would have taken the projectile to travel to that position.

  • Calculate how long it would take your entity to rotate to face the intercept position.

  • Calculate the difference of the impact time and the rotation/travel times.

  • Adjust the time of impact up/down so that the difference gets smaller each time (e.g. binary search).

  • When you get close enough, you are done. Otherwise, start the calculations again.

In the simple case, you could know from the discriminant of the quadratic if you had 0, 1, or 2 solutions and pick the best one. I don't think you can guarantee that here, but you can bound the time range you are willing to search over and how many iterations you will search. This works very well in practice.

The Code:

 /* Calculate the future position of a moving target so that 
  * a turret can turn to face the position and fire a projectile.
  *
  * This algorithm works by "guessing" an intial time of impact
  * for the projectile 0.5*(tMin + tMax).  It then calculates
  * the position of the target at that time and computes what the 
  * time for the turret to rotate to that position (tRot0) and
  * the flight time of the projectile (tFlight).  The algorithms
  * drives the difference between tImpact and (tFlight + tRot) to 
  * zero using a binary search. 
  *
  * The "solution" returned by the algorithm is the impact 
  * location.  The shooter should rotate towards this 
  * position and fire immediately.
  *
  * The algorithm will fail (and return false) under the 
  * following conditions:
  * 1. The target is out of range.  It is possible that the 
  *    target is out of range only for a short time but in
  *    range the rest of the time, but this seems like an 
  *    unnecessary edge case.  The turret is assumed to 
  *    "react" by checking range first, then plot to shoot.
  * 2. The target is heading away from the shooter too fast
  *    for the projectile to reach it before tMax.
  * 3. The solution cannot be reached in the number of steps
  *    allocated to the algorithm.  This seems very unlikely
  *    since the default value is 40 steps.
  *
  *  This algorithm uses a call to sqrt and atan2, so it 
  *  should NOT be run continuously.
  *
  *  On the other hand, nominal runs show convergence usually
  *  in about 7 steps, so this may be a good 'do a step per
  *  frame' calculation target.
  *
  */
 bool CalculateInterceptShotPosition(const Vec2& pShooter,
                                     const Vec2& vShooter,
                                     const Vec2& pSFacing0,
                                     const Vec2& pTarget0,
                                     const Vec2& vTarget,
                                     float64 sProjectile,
                                     float64 wShooter,
                                     float64 maxDist,
                                     Vec2& solution,
                                     float64 tMax = 4.0,
                                     float64 tMin = 0.0
                                     )
 {
    cout << "----------------------------------------------" << endl;
    cout << " Starting Calculation [" << tMin << "," << tMax << "]" << endl;
    cout << "----------------------------------------------" << endl;
    
    float64 tImpact = (tMin + tMax)/2;
    float64 tImpactLast = tImpact;
    // Tolerance in seconds
    float64 SOLUTION_TOLERANCE_SECONDS = 0.01;
    const int MAX_STEPS = 40;
    for(int idx = 0; idx < MAX_STEPS; idx++)
    {
       // Calculate the position of the target at time tImpact.
       Vec2 pTarget = pTarget0 + tImpact*vTarget;
       // Calulate the angle between the shooter and the target
       // when the impact occurs.
       Vec2 toTarget = pTarget - pShooter;
       float64 dist = toTarget.Length();
       Vec2 pSFacing = (pTarget - pShooter);
       float64 pShootRots = pSFacing.AngleRads();
       float64 tRot = fabs(pShootRots)/wShooter;
       float64 tFlight = dist/sProjectile;
       float64 tShot = tImpact - (tRot + tFlight);
       cout << "Iteration: " << idx
       << " tMin: " << tMin
       << " tMax: " << tMax
       << " tShot: " << tShot
       << " tImpact: " << tImpact
       << " tRot: " << tRot
       << " tFlight: " << tFlight
       << " Impact: " << pTarget.ToString()
       << endl;
       if(dist >= maxDist)
       {
          cout << "FAIL:  TARGET OUT OF RANGE (" << dist << "m >= " << maxDist << "m)" << endl;
          return false;
       }
       tImpactLast = tImpact;
       if(tShot > 0.0)
       {
          tMax = tImpact;
          tImpact = (tMin + tMax)/2;
       }
       else
       {
          tMin = tImpact;
          tImpact = (tMin + tMax)/2;
       }
       if(fabs(tImpact - tImpactLast) < SOLUTION_TOLERANCE_SECONDS)
       {  // WE HAVE A WINNER!!!
          solution = pTarget;
          return true;
       }
    }
    return false;
 }

There is a lot more detail located here. There is also a demonstration program on github, located here.

There is also a video showing it in action here. You can skip about 45 seconds into the video to see it in action.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

2D Aiming and Shooting at the mouse 3 Answers

How to make my space ship shooting (2D Game)? 0 Answers

shooting object from from multiple locations 1 Answer

Spin a non-kinematic 2d object ? 0 Answers

Cannon2d rotation control and ball shooting 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges