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

Unity中计算ScreenPointToRay获取的两点夹角,预期90度得26度求排查

问题分析与解决方案

首先,你的核心问题是误解了ScreenPointToRay()的返回值:
camera.ScreenPointToRay().origin返回的始终是相机的世界位置,所以你的pointa和pointb其实是同一个点(相机的位置)——用两个相同的点计算夹角,结果自然是错误的。

为什么你得到了26度?

虽然理论上两个相同点的向量差是零向量,但可能你的相机位置的Z轴不为0,或者代码中存在微小的数值误差,导致pointb.y - pointa.y和pointb.x - pointa.x出现了极小的非零值,从而让Atan2返回了一个无意义的奇怪角度。

正确的实现方式

根据你的需求,分两种场景给出解决方案:

场景1:计算两个屏幕点对应的射线方向之间的夹角

如果你想知道从相机出发,指向两个屏幕点的射线之间的夹角,直接使用射线的direction向量即可:

var newraya = camera.ScreenPointToRay(new Vector3(200, 250, 5));
Vector3 dirA = newraya.direction;

var newrayb = camera.ScreenPointToRay(new Vector3(300, 200, 5));
Vector3 dirB = newrayb.direction;

// 直接用Unity内置方法计算夹角(返回0-180度的结果)
float angleDeg = Vector3.Angle(dirA, dirB);

场景2:计算两个屏幕点在某平面上的投影点之间的夹角

如果你需要的是两个屏幕点投射到某个平面(比如地面、UI平面)上的点之间的夹角,需要先计算射线与平面的交点:
比如,计算射线与XY平面(Z=0)的交点:

var newraya = camera.ScreenPointToRay(new Vector3(200, 250, 5));
// 计算射线到Z=0平面的距离
float distanceA = -newraya.origin.z / newraya.direction.z;
// 获取交点
Vector3 worldPointA = newraya.GetPoint(distanceA);

var newrayb = camera.ScreenPointToRay(new Vector3(300, 200, 5));
float distanceB = -newrayb.origin.z / newrayb.direction.z;
Vector3 worldPointB = newrayb.GetPoint(distanceB);

// 计算两个点相对于相机的夹角(或者你需要的其他参考点)
Vector3 fromCameraToA = worldPointA - camera.transform.position;
Vector3 fromCameraToB = worldPointB - camera.transform.position;
float angleDeg = Vector3.Angle(fromCameraToA, fromCameraToB);

额外提示

你之前用Mathf.Atan2计算角度时,混用了Math.PI(C#标准库的double类型)和Mathf的方法,建议统一使用Unity的Mathf.PI避免类型转换问题:

// 正确的写法(仅当你需要用Atan2计算向量与X轴的夹角时)
float angleDeg = Mathf.Atan2(vector.y, vector.x) * Mathf.Rad2Deg;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:43:10