0

所以这是我的代码大致

Distance = Vector3.Distance(transform.position,Target.transform.position);
float timeToTarget; 
float burnDistance =  Projectile.MetersPerSecond * 2f * 2f * 0.5f;

if (Distance < burnDistance)
{
    timeToTarget = Mathf.Sqrt(2 * Distance / Projectile.MetersPerSecond);
}
else
{
    float velocity = Projectile.MetersPerSecond * 2;
    TimeToTarget = 2 + (Distance - burnDistance) / velocity;
}
AimPoint = Target.transform.position + (Target.transform.rigidbody.velocity * TimeToTarget) + (Random.insideUnitSphere * Accuracy);
Distance = Vector3.Distance(transform.position,AimPoint);
TimeToTarget = Mathf.Sqrt(2 * Distance / Projectile.MetersPerSecond);

我正在尝试用射弹拦截目标。

我认为问题是找到合适的目标时间。

基本上,当我找到目标距离时,然后使用它来找到目标时间,它将我的目标点更改为目标在时间秒内的位置。但现在距离变了。现在我距离目标的距离更长,我距离目标点的距离远离我想要击中的目标。

基本上,当目标远离我时,弹丸击中目标所需的时间比到目标的距离预测的要长。所以我可以通过再次运行算法来解决这个问题。仅使用瞄准点作为目标并获得更接近的近似值。我可以继续这样做以非常接近,但这似乎非常低效。有没有更好的办法?

4

2 回答 2

1

如果你知道目标的速度向量 V,你可以计算出导弹的速度和拦截时间,如下所示:

假设你在 P 并且目标在 Q。对于从 P 以速度 U 发射的导弹在时间 t 击中目标,我们必须有

P + t*U = Q + t*V

所以

U = V + (Q-P)/t

假设导弹速度——U的长度——固定在s,所以

s*s = V.V + 2*(Q-P).V/t + (Q-P).(Q-P)/(t*t)

或者,重新排列)

(s*s - V.V)*t*t - 2*(Q-P).V*t - (Q.P).(Q-P) = 0

这是 t 的二次方程。如果有一个正解 t0,那么你可以发射一枚导弹,速度 U 由下式给出

U = V + (Q-P)/t0

在时间 t0 击中目标

于 2013-07-19T14:59:25.703 回答
0

如果您的“射手”不旋转,而您只需要发射弹丸以拦截目标,我建议您查看 Jeffery Hantin 在这篇文章中的出色回答。

另一方面,如果您的身体旋转然后射击并且您希望弹丸拦截目标......这是一个非常不同的问题。简而言之,它从您在上面的帖子中找到的两个方程式开始,但是您添加了另一个方程式,用于射手的面向矢量和您瞄准的最终位置之间的角度的弧度。这导致了一些令人讨厌的非线性和非二次方程组。我没有解决它们,但我确实使用了二进制搜索来“挤出”答案(或失败)。

在博客文章中有更长更详细的描述,以及图片和视频的优点,但我会在此处发布该功能(带有慷慨的评论)。

这是我想出的带有基本描述的功能:

/* 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;
}
于 2014-10-26T21:43:47.563 回答