You need to enable JavaScript to run this app. 游戏Bot开发中Pitch与Yaw特殊计算代码的运行原理疑问
优惠活动
大模型
产品
解决方案
定价
更多

游戏Bot开发中Pitch与Yaw特殊计算代码的运行原理疑问

问题背景

我最近在研究如何开发简易游戏Bot,了解到有两种实现视角转向的方法,其中一种是使用atan2、sin等函数计算pitch(俯仰角)和yaw(偏航角),该方法我已完全理解,对应示意图:
我完全理解的计算方法
但我还看到很多人在使用另一种计算方法,不清楚其运行逻辑,代码如下:

void CalcAngle(float *src, float *dst, float *angles)
{
    double delta[3] = {(src[0] - dst[0]), (src[1] - dst[1]), (src[2] - dst[2])};

    int x = 0;
    int y = 1;
    int z = 2;

    float hyp = delta[x] * delta[x] + delta[y] * delta[y];
    angles[0] = asinf(delta[z] / hyp) * 180 / pi;
    angles[1] = atanf(delta[y] / delta[x]) * 180 / pi;

    if(angles[0] > 0.0)
    {
        angles[1] += 180;
    }
}

我对第二种方法的推导猜想对应示意图:
我无法理解的第二种计算方法
我的疑问如下:

  • atanf(delta[y]/delta[x])本身无法正确计算第二、第三象限的角度,这段代码为何能输出有效结果?
  • 代码中计算角度时为何用邻边和对边运算而非对边与斜边?

角度象限参考示意图:
角度象限参考示意图


问题解答

关于atanf象限问题的解释

这段代码的delta计算逻辑是源坐标减目标坐标,得到的delta向量是从目标指向自身的反向偏移,而非常规视角转向逻辑里的从自身指向目标的正向偏移。
常规atan2(dy, dx)可以直接覆盖全象限,而这段代码里的if(angles[0] > 0.0) angles[1] += 180本质就是在做象限修正:

  • 当delta[x]为正(对应常规第一、第四象限)时,atanf返回值范围为[-90°, 90°],此时如果delta[z]为正(即俯仰角为正,目标位于自身下方),就给yaw加180°,把第一象限结果转到第三象限、第四象限结果转到第二象限,刚好匹配反向delta的实际朝向。
  • 当delta[x]为负(对应常规第二、第三象限)时,dy/dx的比值和第一、第四象限的同符号值一致,atanf返回的角度天然偏移180°,结合上面的俯仰角判断补正后,刚好可以覆盖所有象限的正确yaw值。

注:这段代码存在边界漏洞,当delta[x]为0时会触发除零错误,只是绝大多数游戏场景不会刚好触发这个极端位置,所以可以正常运行。

关于邻边对边运算的解释

首先要注意你贴出的代码存在一处常见的复制疏漏:计算得到hyp的平方和后没有做开平方运算,正确可运行的写法应该是float hyp = sqrt(delta[x] * delta[x] + delta[y] * delta[y]);,否则delta[z]/hyp的取值范围会超出asinf的合法输入区间[-1,1],实际使用的版本都补上了开平方操作。
接下来解释运算逻辑:

  1. yaw角是三维向量在xy平面上的投影和x轴的夹角,本身只需要用到x、y两个分量,用对边比邻边计算tan值是该角度的标准定义,不需要用到斜边参与运算,所以写法完全合理。
  2. 俯仰角的计算属于工程简化写法:常规正确的俯仰角计算应该是asinf(delta[z] / 三维向量总模长),但绝大多数FPS类游戏的视角俯仰角被限制在[-89°, 89°]的小范围内,此时三维向量总模长和xy平面的模长hyp差值极小,误差玩家完全感知不到,省略z分量的平方计算可以减少一次运算,属于性能优化的取舍。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 00:36:02