2013-07-18 26 views
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); 

我試圖攔截目標有彈。

問題是找到適當的時機來實現我的想法。

基本上,當我找到距離目標,然後使用它來找到時間目標 它改變我的目標點,在目標將在時間秒。 但現在距離已經改變。現在,我現在距離目標遠,目標遠離我想要擊中的距離。

基本上,當目標從我身上移開時,彈丸撞擊瞄準點需要的時間比通過目標距離預測的時間要長。 所以我可以通過再次運行算法來解決這個問題。只使用瞄準點作爲目標並進行更近似的近似。我可以繼續這樣做以獲得非常接近的效果,但這似乎非常不科學。有沒有更好的辦法?

回答

0

如果你知道目標的速度矢量V,你可以計算出導彈的速度和時間攔截這樣的:

假設你是在P和目標是在問:對於與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 

其是用於噸二次方程。如果有一個正解t0到這一點,那麼 就可以發射導彈,以速度U通過

U = V + (Q-P)/t0 

給擊中目標在t0時刻

0

如果你的「射手」不旋轉你只需要發射一枚彈丸以攔截目標,我建議你看看Jeffery Hantin在this post中的出色答案。另一方面,如果你的身體旋轉然後射擊,並且你希望彈丸攔截目標......這是一個非常不同的問題。簡而言之,它起始於你在上面的帖子中找到的相同的兩個等式,但是你在另一個等式中增加了射手面向矢量與你瞄準的最終位置之間角度的角。這導致了一個有點令人討厭的非線性和非二次方程組。我沒有解決它們,但我確實使用二分查找來「擠出」答案(或失敗)。

我有a much longer and more detailed description on a blog post,以及圖片和視頻的善良,但我會在這裏發佈功能(慷慨的評論)。

下面是函數,基本的描述,我想出了:

/* 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; 
} 
相關問題