Unity中如何实现带偏移量与角度的Ray.GetPoint()方法?
自定义Unity Ray的带偏移和角度的GetPoint方法
嘿,作为Unity新手能想到扩展Ray的功能真的很棒!你想要的这种GetPoint(distance, padding, angle)方法完全可以自己实现,我来一步步给你拆解怎么做。
核心思路
首先明确需求:我们需要先获取射线上距离起点distance的基础点,然后在垂直于射线方向的平面上,以这个基础点为中心,偏移padding单位的距离,偏移方向由angle参数决定(0°对应某个基准方向,90°则旋转90度)。
实现的关键是找到两个垂直于射线方向的正交向量,用来定义这个偏移平面的坐标系,再通过角度计算出具体的偏移方向。
完整代码实现
我们可以给Ray写一个扩展方法,这样调用起来就和原生的GetPoint一样方便:
using UnityEngine; public static class RayExtensions { /// <summary> /// 获取射线上指定距离的点,并在垂直于射线的平面上偏移指定距离和角度 /// </summary> /// <param name="ray">目标射线</param> /// <param name="distance">沿射线的距离</param> /// <param name="padding">偏离射线的距离(垂直方向)</param> /// <param name="angle">偏移的角度(0°为基准方向,顺时针/逆时针旋转)</param> /// <returns>偏移后的目标点</returns> public static Vector3 GetPointWithOffset(this Ray ray, float distance, float padding, float angle) { // 1. 获取射线上的基础点c Vector3 basePoint = ray.GetPoint(distance); // 2. 找到第一个垂直于射线方向的基准向量 Vector3 perpendicular1; // 避免射线方向和Vector3.up平行的情况(比如射线向上/向下) if (Mathf.Abs(Vector3.Dot(ray.direction, Vector3.up)) > 0.99f) { perpendicular1 = Vector3.Cross(ray.direction, Vector3.right).normalized; } else { perpendicular1 = Vector3.Cross(ray.direction, Vector3.up).normalized; } // 3. 找到第二个垂直于射线和perpendicular1的向量(构成平面坐标系) Vector3 perpendicular2 = Vector3.Cross(ray.direction, perpendicular1).normalized; // 4. 根据角度计算偏移方向 float radian = angle * Mathf.Deg2Rad; Vector3 offsetDirection = Mathf.Cos(radian) * perpendicular1 + Mathf.Sin(radian) * perpendicular2; // 5. 计算最终偏移后的点 return basePoint + offsetDirection * padding; } }
参数说明与示例
- distance:和原生
Ray.GetPoint(distance)一样,是沿射线起点到基础点的距离,比如你说的3就是距离起点3单位的点c。 - padding:偏离射线的垂直距离,比如
2就是从点c向垂直方向移动2单位。 - angle:偏移方向的角度,0°对应我们计算的
perpendicular1方向,90°则对应perpendicular2方向(也就是你说的“后方/上方”,具体方向取决于射线朝向)。
举个你提到的例子:
- 调用
ray.GetPointWithOffset(3, 2, 0):返回点c沿perpendicular1方向偏移2单位的点d。 - 调用
ray.GetPointWithOffset(3, 2, 90):返回点c沿perpendicular2方向偏移2单位的点d。
注意事项
- 角度的正负:如果想要顺时针旋转,角度用负值即可,比如
-90°就是逆时针转90度的反方向。 - 当射线方向接近垂直(向上/向下)时,代码会自动切换基准向量,避免计算出零向量导致偏移失效。
内容的提问来源于stack exchange,提问作者Fredrik Johansson
相关产品推荐
相关产品推荐

