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 にあるとします。速度 U で P から発射されたミサイルが時間 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

「シューター」が回転せず、発射体を発射してターゲットを迎撃するだけでよい場合は、この投稿のジェフリー・ハンティンによる優れた回答をご覧になることをお勧めします。

一方、体が回転してから発砲し、発射物がターゲットを迎撃したい場合...それは非常に別の問題です. 要するに、上記の投稿で見つけたのと同じ 2 つの方程式から始まりますが、射手の向きのベクトルと目標とする最終的な位置との間の角度の弧を表す別の方程式を追加します。これは、やや厄介な非線形で非二次的な方程式のセットにつながります。私はそれらを解決しませんでしたが、バイナリ検索を使用して答えを「絞り出しました」(または失敗しました)。

ブログ投稿には、写真とビデオの良さとともに、はるかに長く詳細な説明がありますが、ここに関数を (寛大なコメントと共に) 投稿します。

これが、私が思いついた基本的な説明を含む関数です。

/* 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 に答える