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
相关产品推荐
相关产品推荐

