自定义transform.LookAt数学原理探究及相机跟随角度问题排查
自定义Unity相机LookAt逻辑问题
我正在探究Unity中transform.LookAt()函数背后的数学原理(三角学与线性代数),尝试修改实现自定义需求但未成功。我需要实现一款3D相机:带自定义偏移跟随玩家,支持缩放且保持Vector3偏移,仅允许X轴旋转、其余轴锁定,但当前脚本角度被限制在45°到90°之间。
我的代码如下:
private void LookAt(Transform t) { Vector3 forward = _camPos - (t.position + new Vector3(0, t.GetComponent<CapsuleCollider>().height / 2, 0)); Debug.DrawRay(forward, -forward, Color.blue); Vector3 right = Vector3.Cross(target.up, forward); Debug.DrawRay(forward, right, Color.magenta); Vector3 newUp = Vector3.Cross(Vector3.forward, right); Debug.DrawRay(forward, newUp, Color.yellow); float angle = Mathf.Atan2(forward.magnitude, newUp.magnitude) * Mathf.Rad2Deg; mainCam.transform.rotation = Quaternion.Euler(angle, 0, 0); }
代码逻辑:
- 获取相机指向目标的forward向量(直角三角形斜边),方向相反不影响;
- 通过目标up向量与forward向量的叉乘计算right向量;
- 通过forward与right向量的叉乘计算newUp向量(直角三角形对边);
- 使用反正切函数(Arcus tangent),以斜边/对边的比值计算X轴旋转角度。
向量计算结果符合预期,但仅当相机拉近(缩放倍率降低)时才能正确对准角色,请问我遗漏了什么?
问题分析与修复
核心问题
三角函数参数逻辑错误
Mathf.Atan2(y, x)的作用是计算y/x对应的反正切值,对应直角三角形中对边/邻边的比值。你用了两个向量的模长(斜边/对边)来计算,完全不符合俯仰角的推导逻辑,这直接导致角度范围被错误限制。向量计算绕路且丢失方向信息
通过多次叉乘得到的newUp向量模长和方向无法准确反映相机的俯仰状态,而且用模长计算会丢失相机相对于目标的上下位置信息,进一步加剧角度计算的偏差。
修复后的代码
直接基于相机到目标的向量投影来计算X轴俯仰角,逻辑简洁且准确:
private void LookAt(Transform t) { // 获取目标头顶的世界位置 Vector3 targetHead = t.position + Vector3.up * t.GetComponent<CapsuleCollider>().height / 2; // 计算相机指向目标头顶的向量(目标到相机的反向) Vector3 lookDir = targetHead - _camPos; // 计算X轴俯仰角:将lookDir投影到Y-Z平面,用Y分量(垂直方向)和Z分量(水平方向)计算 float pitchAngle = Mathf.Atan2(lookDir.y, lookDir.z) * Mathf.Rad2Deg; // 仅应用X轴旋转,锁定Y、Z轴旋转 mainCam.transform.rotation = Quaternion.Euler(pitchAngle, 0, 0); }
额外优化点
- 若要保持自定义偏移跟随,建议将
_camPos设计为基于目标位置的偏移向量(例如_camPos = target.position + followOffset),缩放时只修改followOffset的模长,这样能保证偏移的相对姿态不变。 - 可以给
pitchAngle添加范围限制(比如pitchAngle = Mathf.Clamp(pitchAngle, -45f, 90f)),避免相机出现过度翻转的不合理状态。
内容的提问来源于stack exchange,提问作者Narc0t1CYM
相关产品推荐
相关产品推荐

