所以这是我的代码大致
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);
我试图用射弹拦截目标。
问题在于找到适合我的目标的时间。
基本上当我找到到目标的距离然后用它来找到目标的时间 它将我的瞄准点改变为目标在时间秒内的位置。 但现在距离发生了变化。现在,我现在距离目标越来越远,我距离我想要击中的距离不远。
基本上当目标远离我时,射弹击中瞄准点所需的时间比距目标距离所预测的要长。 所以我可以通过再次运行算法来解决这个问题。仅使用aimpoint作为目标并获得更接近的近似值。我可以继续这样做,以获得非常接近,但这似乎非常低效。还有更好的方法吗?
答案 0 :(得分: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的二次方程。如果对此有正解,那么 你可以发射导弹,速度U由
给出U = V + (Q-P)/t0
在时间t0点击目标
答案 1 :(得分:0)
如果你的射手&#34;不旋转,你只需要发射射弹以拦截目标,我建议你看看Jeffery Hantin在this post中的出色回答。
另一方面,如果你的身体旋转然后射击,你想让射弹拦截目标......这是一个非常不同的问题。简而言之,它从你在上面的帖子中找到的相同的两个方程开始,但是你为射手的面向矢量和你瞄准的最终位置之间的角度的arcos添加了另一个等式。这导致了一些有点令人讨厌的非线性和非二次方程组。我没有解决它们,但我确实使用二进制搜索来“挤压”#34;出答案(或失败)。
我有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;
}