射线简介
射线检测在unity中使用的非常广泛,不管是2D还是3D都有很多的用途,像是判定鼠标点击的位置还有动作游戏的攻击范围的判定。
最近在实现一个传送的功能:传送一个固定的距离,如果中间有物体阻挡就传到碰撞的物体上。
整体功能难度不高
//这个方法本身就是发射一条射线,写起来快所以最早就先这么干了
if (selfRigidbody.SweepTest(dir, out hit, length))
{
//通过命中点和自身的坐标处理使本体不会穿墙
var hitpoint = hit.point;
//这里获取自身距离碰撞点最近的坐标
var selClosesthitPoint = selfRigidbody.ClosestPointOnBounds(hitpoint);
//这里得到该点和自身坐标的差,获取自身的厚度
var closestPoint = selClosesthitPoint - trans.position;
//击中点和厚度相减保证不会卡墙
selfRigidbody.MovePosition(hitpoint - closestPoint);
}
else
{
//为击中时的情况
trans.position = telPoint;
}*/
但在实际运行中总是会出现一个问题,总是会穿过贴着的物体传到碰撞体里面去,一开始觉得会不会是因为靠太近了导致物体外侧网格碰撞面被自身挡住了,因为射线在没更改设置的情况下只能检测到物体的网格碰撞体的外层,内部是检测不到的,必须开启这个设置才行,
这也是为什么设置源点射线位置在自身时不会检测到自己。所以去搜了一下怎么在内侧检测到碰撞体,然后大不了把自身给去掉就行了。
找确实找到了https://github.com/yangruihan/blog/issues/29,反转射线就可以了,拿这个再检测一次就行了。
/// <summary>
/// 反转射线
/// </summary>
public static Ray Reverse(this Ray ray, float distance)
{
return new Ray(
ray.origin + ray.direction * distance,
-ray.direction);
}
不过仔细想了一下这个功能需求和我要的不一样,这个只能是检测该方向上有物体(实际试了一下确实也没有用)。
之后想不出来,就改了代码调试一下看看到底使用射线时获取到了啥玩意
RaycastHit[] hits;
Ray ray = new Ray(position, dir);
//RaycastNonAlloc的参数数组是提前分配的大小
//RaycastAll是动态获取分配的数组,内存资源比上面的消耗大
//hits = Physics.RaycastAll(ray,length);
//Debug.DrawLine(position,endPoint,Color.red,5f);
hits = Physics.RaycastAll(ray,length);
if(hits.Length > 0)
{
var targetPoint = hits[0].point;
var selfClosedPoint = selfRigidbody.ClosestPointOnBounds(targetPoint);
//获取自身厚度的坐标差
var closetPoint = selfClosedPoint - _mTrans.position;
//这个是最后移动的坐标长
selfRigidbody.MovePosition(targetPoint - closetPoint);
}
else
{
_mTrans.position = telPoint;
}
还是没用,试着获取数量看看
6,获取了两个物体,好了破案了,写个比较函数丢给Array.List排序委托就行了
public int Compare(RaycastHit hit1, RaycastHit hit2)
{
var pos = _mTrans.position;
var dis1 = Vector3.Distance(hit1.point, pos);
var dis2 = Vector3.Distance(hit2.point, pos);
if (dis1 > dis2)
{
return 1;
}
else
return -1;
return 0;
}
不知道为什么近的物体反而会排在第二位了,之前直接拿SweepTest测试没得到的原因也知道了,第一个获取的是地板的点,当然不会测到Cube的碰撞体了。
+++
bug是解决了,就是不知道为什么近的点会排到后面去,应该是unity的问题