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

如何计算任意头部旋转下眼睛看向目标的Yaw与Pitch值

计算任意旋转头部的眼睛看向目标的Yaw/Pitch值

要解决这个问题,核心是把世界空间中的目标方向转换为头部局部坐标系下的方向,再从局部向量推导相对头部的Yaw和Pitch角度——这样不管头部怎么旋转(颠倒、向后),角度值都能精准对应眼睛相对于头部的转动需求,完全适配2D面部纹理的眼睛移动逻辑。

步骤1:计算头部到目标的世界方向向量

先算出目标相对于头部的位置偏移,归一化后得到方向向量(归一化不影响角度计算,可选但推荐):

Vector3 worldTargetDir = targetPosition - headPosition;
worldTargetDir.Normalize();

步骤2:转换到头部局部坐标系

头部的旋转(四元数)定义了世界空间到头部局部空间的转换逻辑,我们需要逆旋转来把世界向量转成局部向量——这样得到的向量方向是相对于头部自身的前方(Z轴)、上方(Y轴)的:

Vector3 localTargetDir = Quaternion.Inverse(headRotation) * worldTargetDir;

比如头部上下颠倒时,局部Y轴和世界Y轴相反,此时世界中向下的方向在头部局部就是向上,正好对应需求中“眼睛向上看(世界视角向下)时Pitch为正”的情况。

步骤3:计算Yaw(偏航)角度

Yaw是局部向量在X-Z平面(头部水平平面)的左右偏移角度,用atan2(X, Z)计算(X在前、Z在后对应绕Y轴的旋转),再转成角度:

float yawRad = atan2(localTargetDir.x, localTargetDir.z);
float yawDeg = rad2deg(yawRad);
  • 正值表示眼睛看向头部自身的右侧,负值表示左侧,完全贴合头部当前朝向。

步骤4:计算Pitch(俯仰)角度

Pitch是局部向量相对于X-Z平面的上下偏移角度,先算出X-Z平面的向量长度,再用atan2(Y, XZ长度)计算:

float xzLength = sqrt(localTargetDir.x * localTargetDir.x + localTargetDir.z * localTargetDir.z);
float pitchRad = atan2(localTargetDir.y, xzLength);
float pitchDeg = rad2deg(pitchRad);
  • 正值表示眼睛看向头部自身的上方,负值表示下方,不管头部是否颠倒,这个值都对应眼睛相对于头部的上下转动。

步骤5:钳制角度到指定范围

最后把计算出的Yaw和Pitch限制在你需要的区间(比如-30°到30°):

float clampedYaw = clamp(yawDeg, -30f, 30f);
float clampedPitch = clamp(pitchDeg, -30f, 30f);

完整伪代码示例(Unity风格)

public (float Yaw, float Pitch) CalculateEyeRotation(Vector3 headPosition, Quaternion headRotation, Vector3 targetPosition)
{
    // 计算世界空间方向向量
    Vector3 worldTargetDir = targetPosition - headPosition;
    worldTargetDir.Normalize();

    // 转换到头部局部空间
    Vector3 localTargetDir = Quaternion.Inverse(headRotation) * worldTargetDir;

    // 计算偏航角Yaw
    float yawRad = Mathf.Atan2(localTargetDir.x, localTargetDir.z);
    float yawDeg = Mathf.Rad2Deg * yawRad;

    // 计算俯仰角Pitch
    float xzLength = Mathf.Sqrt(localTargetDir.x * localTargetDir.x + localTargetDir.z * localTargetDir.z);
    float pitchRad = Mathf.Atan2(localTargetDir.y, xzLength);
    float pitchDeg = Mathf.Rad2Deg * pitchRad;

    // 钳制角度范围
    float clampedYaw = Mathf.Clamp(yawDeg, -30f, 30f);
    float clampedPitch = Mathf.Clamp(pitchDeg, -30f, 30f);

    return (clampedYaw, clampedPitch);
}

关键注意事项

  • 逆旋转的必要性:只有把世界方向转到头部局部空间,才能得到相对于头部的真实偏移角度,否则角度会和世界空间绑定,无法适配头部的任意旋转状态。
  • Pitch计算细节:用X-Z平面长度而非向量总长度,是因为Pitch只关注上下方向与水平平面的夹角,避免向量长度干扰角度计算。
  • 引擎适配:不同引擎的三角函数、四元数操作可能有细微差异(比如Unreal的FRotator或FQuat),但核心逻辑完全通用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:02:05