You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用线性速度、位置数据精准射击移动目标?C#实现咨询

精准击杀移动目标的计算方案与代码优化

问题场景

我方飞船(黑色右箭头)与敌方目标(红色圆圈,半径1.2)均做无加速运动,需仅通过位置、线性速度、半径数据实现精准击杀。

备注:子弹生命周期0.5秒,速度40,半径0.2。

当前实现代码

用户尝试用C#实现该功能,代码如下:

public static Vector3 CalculatePreciseShootDirection(Vector3 shipPosition, Vector3 shipVelocity,
                                                     Vector3 targetPosition, Vector3 targetVelocity,
                                                     float bulletLifetime, float bulletSpeed)
{
    Vector3 shipFuturePosition = shipPosition + bulletLifetime * shipVelocity;
    Vector3 targetFuturePosition = targetPosition + bulletLifetime * targetVelocity;
    Vector3 relativeDisplacement = targetFuturePosition - shipFuturePosition;
    float timeToTarget = Vector3Magnitude(relativeDisplacement) / bulletSpeed;
    Vector3 adjustedTargetPosition = targetPosition + timeToTarget * targetVelocity;
    Vector3 shootingDirection = adjustedTargetPosition - shipPosition;
    float shootingDistance = Vector3Magnitude(shootingDirection);
    float maxDistance = bulletLifetime * bulletSpeed;
    if (shootingDistance <= maxDistance)
    {
        return Vector3.Normalize(shootingDirection);
    }
    else
    {
        return Vector3.Zero;
    }
}

private static float Vector3Magnitude(Vector3 v)
{
    return (float)Math.Sqrt(v.X * v.X + v.Y * v.Y + v.Z * v.Z);
}

现有问题与改进方案

1. 核心逻辑偏差

当前代码先假设子弹飞行满生命周期来计算双方未来位置,再反推飞行时间,这个逻辑存在循环矛盾——正确的做法是直接建立子弹飞行轨迹与目标移动轨迹的交汇方程,求解子弹击中目标的合法时间。

设:

  • 我方位置:$S_0$,速度:$V_s$
  • 敌方位置:$T_0$,速度:$V_t$
  • 子弹速度:$V_b$(标量),飞行时间:$t$
  • 敌方半径:$R_t$,子弹半径:$R_b$

子弹发射后,我方位置随时间变化为 $S(t) = S_0 + V_s \cdot t$,敌方位置为 $T(t) = T_0 + V_t \cdot t$。子弹从我方当前位置发射,飞行方向为单位向量 $\vec{d}$,则子弹位置为 $B(t) = S_0 + V_b \cdot \vec{d} \cdot t$。

击中条件为:$|B(t) - T(t)| \leq R_t + R_b$(考虑双方体积的碰撞判定),同时 $0 < t \leq t_{max}$($t_{max}$为子弹生命周期)。

代入位置整理后,可得到关于 $t$ 的二次方程:
$$(\Delta V \cdot \Delta V - V_b^2) t^2 + 2 (\Delta S \cdot \Delta V) t + (\Delta S \cdot \Delta S - (R_t + R_b)^2) = 0$$
其中:

  • 初始相对位移 $\Delta S = T_0 - S_0$
  • 相对速度 $\Delta V = V_t - V_s$

求解该方程,筛选出合法的正实数时间(不超过子弹生命周期),再代入计算击中时的目标位置,即可得到准确射击方向。

2. 代码优化点

  • 用Unity内置的Vector3.Magnitude/Vector3.SqrMagnitude替代自定义的Vector3Magnitude,提升性能
  • 加入碰撞半径的判定,避免忽略目标和子弹体积导致的误差
  • 修正核心逻辑,通过求解二次方程得到准确击中时间

优化后的代码示例

public static Vector3 CalculatePreciseShootDirection(Vector3 shipPos, Vector3 shipVel,
                                                     Vector3 targetPos, Vector3 targetVel,
                                                     float bulletLifetime, float bulletSpeed,
                                                     float targetRadius, float bulletRadius)
{
    float combinedRadius = targetRadius + bulletRadius;
    Vector3 deltaPos = targetPos - shipPos;
    Vector3 deltaVel = targetVel - shipVel;

    // 二次方程参数:a*t² + b*t + c = 0
    float a = Vector3.Dot(deltaVel, deltaVel) - bulletSpeed * bulletSpeed;
    float b = 2 * Vector3.Dot(deltaPos, deltaVel);
    float c = Vector3.Dot(deltaPos, deltaPos) - combinedRadius * combinedRadius;

    // 求解判别式,无实根则无法击中
    float discriminant = b * b - 4 * a * c;
    if (discriminant < 0)
    {
        return Vector3.zero;
    }

    float sqrtDiscriminant = Mathf.Sqrt(discriminant);
    float t1 = (-b + sqrtDiscriminant) / (2 * a);
    float t2 = (-b - sqrtDiscriminant) / (2 * a);

    // 筛选合法时间:正且不超过子弹生命周期,优先取最短时间
    float validTime = float.MaxValue;
    if (t1 > 0 && t1 <= bulletLifetime)
    {
        validTime = t1;
    }
    if (t2 > 0 && t2 <= bulletLifetime && t2 < validTime)
    {
        validTime = t2;
    }

    if (validTime == float.MaxValue)
    {
        return Vector3.zero;
    }

    // 计算击中时的目标位置,生成射击方向
    Vector3 hitTargetPos = targetPos + targetVel * validTime;
    Vector3 shootDir = hitTargetPos - shipPos;
    return shootDir.sqrMagnitude < 0.001f ? Vector3.zero : shootDir.normalized;
}

说明

  • 该方案考虑了目标与子弹的体积碰撞,通过数学方程求解得到精准的击中时间,避免了原逻辑的循环假设问题
  • 返回Vector3.zero表示当前条件下无法在子弹生命周期内击中目标

内容的提问来源于stack exchange,提问作者PerduGames

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 11:24:51