【Unity】射线检测
2D射线检测
Collider2D
无法被3D射线检测,必须使用Physics2D
射线检测不是特别方便Debug,无法看到射线的范围,则可以使用Collider
协助:
- 创建一个
BoxCollider2D
- 勾选
IsTrigger
,这样就不会有碰撞了 - 设置
Layer
层级
1 | private void ButtressCheck(BoxCollider2D coll) |
如此一来,这个Box检测就与coll的位置、大小一摸一样,scene中coll的绿色范围就代表着BoxCase的位置和大小
创建并使用射线
射线检测:从某个初始点开始,沿着特定的方向发射一条不可见且无限长的射线,通过此射线检测是否有任何模型添加了Collider碰撞器组件。一旦检测到碰撞,停止射线继续发射。
Collider组件中Is Trigger选项的开关并不影响射线检测
! 对了还有一个参数,写在Raycast末尾,QueryTriggerInteraction(指定该射线是否应该命中触发器),上面我说过Is Trigger选项的开关不影响射线检测,但是前提是QueryTriggerInteraction该参数设置为检测触发器了,你也可以将该参数设置为仅对碰撞器进行检测,这个参数可以全局设置。
举两个常用的例子
- 根据物体的指向确定射线的方向
Ray ray = new Ray(transform.position, transform.forward);
- 根据鼠标的位置确定射线的方向
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
1 | [private float eventDistance = 3f; ] |
显示射线
Uniyt中通过使用
Debug.DrawLine()
和Debug.DrawRay()
都可以让射线现出原形。
但是!需要特别注意的是,这里画出的线其实跟射线毫无关联的,因为就算没有射线,这里也能画出线来。两点一线,只要确定两个点就行了。所以这里的线只是辅助开发者而已。
但是!又需要特别注意的是,如果你的射线不显示的话,估计是因为!我就是刚刚不小心把它关了,然后挠头找不到原因,我已经犯了好几次这样的错误了!!!!!这个按钮主要是用于显示和关闭场景中的辅助图形之类的(如灯光,射线、摄像机等)!
两种方法的区别
DrawLine
:真正的两点确定一条线DrawRay
:从初始点出发画一条线,所以需要一个初始点,加上一个具有方向和长度的向量,就得到一条射线
一般使用DrawRay
,比较贴合射线的性质。而DrawRay
也有两种常用方法
1 | // 直接了当的设置射线的起点和方向 |
实际运用
筛选能击中的物体
可以通过物体的Layer
控制射线需要击中的物体
如果有两种物体A,B,则可以将其的Layer设置为对应的LayerA和LayerB。
射线只想要击中A,而不受B的影响,可以将LayerMask设置为LayerA
1 | [private float eventDistance = 3f; ] |
让射线穿透
如果有两个A在一条线上,发出射线时永远只会返回离玩家最近的那个A,如何返回后面的A呢?
可以将前面的A的Layer设置为成为LayerB,这样射线就不会返回前面的A了。
1 | hit.collider.gameObject.layer = 10; // 这里数字10代表的是Layer的第10层 |
让射线检测多个
通过上面的学习我们知道可以通过RaycastHit结构体获得检测到的碰撞体,但似乎每次只能返回一个,如何一次返回在该条射线上所有符合标准的物体呢?
1 | [private float eventDistance = 3f; ] |
拓展
LayerMask的介绍
LayerMask 实际上是一个位码操作,在Unity3D中一共有32个Layer层,并且不可增加。
位运算符
按位运算符:~、|、&、^。位运算符主要用来对二进制位进行操作。
逻辑运算符:&&、||、!。逻辑运算符把语句连接成更复杂的复杂语句。
按位运算符:左移运算符<<,左移表示乘以2,左移多少位表示乘以2的几次幂。
例如:var temp = 14 << 2; 表示十进制数14转化为二进制后向左移动2位。
temp最后计算的值为 14乘以2的平方,temp = 56;
同理,右移运算符>>,移动多少位表示除以2的几次幂。
LayerMask的使用
1 | LayerMask mask = 1 << 3; // 表示开启Layer3。 |
1 | LayerMask mask = ~(1<<2|1<<8); // 表示关闭Layer2和Layer8。 |
1 | LayerMask mask = 1 << LayerMask.NameToLayer(“TestLayer”); // 表示开启层名“TestLayer” 的层 。 |
RaycastHit的point属性
该point的属性表达的是射线与碰撞体的交点,一般运用在moba游戏人物的移动等。