射线碰撞检测+LayerMask的使用
射线的定义
射线是3D世界中从一个点向一个特定方向发射的一条无终点的线。当射线在发射轨迹中与其他物体发生碰撞时,它将停止发射。
射线的用途
在Unity中,射线的应用范围较为广泛,主要用于碰撞检测(例如,判断子弹飞行时是否击中目标)、角色移动等场景。
相关API介绍
1. Ray Camera.main.ScreenPointToRay(Vector3 pos)
该方法返回一条射线 Ray,此射线从摄像机出发,指向屏幕上指定的一个点。
2. Ray Camera.main.ViewportPointToRay(Vector3 pos)
该方法返回一条射线 Ray,此射线从摄像机出发,指向视口(视口之外无效)指定的一个点。
3. Ray 射线类
Ray 类用于表示射线,可通过它来定义射线的起始点和方向。
4. RaycastHit 光线投射碰撞信息
RaycastHit 结构体用于存储光线投射碰撞的详细信息,如碰撞点、碰撞物体等。
5. Physics.Raycast 系列方法
bool Physics.Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask)
当光线投射与任何碰撞器交叉时返回 true,否则返回 false。
bool Physics.Raycast(Ray ray, Vector3 direction, RaycastHit out hit, float distance, int layerMask)
在场景中投下一条可与所有碰撞器碰撞的光线,并返回碰撞的细节信息。
bool Physics.Raycast(Ray ray, float distance, int layerMask)
当光线投射与任何碰撞器交叉时返回 true,否则返回 false。
bool Physics.Raycast(Vector3 origin, Vector3 direction, RaycastHit out hit, float distance, int layerMask)
当光线投射与任何碰撞器交叉时返回 true,否则返回 false。
注意:如果从一个球型体的内部到外部用光线投射,返回为 false。
参数理解
origin:在世界坐标中射线的起始点。direction:射线的方向。distance:射线的长度。hit:使用C#中out关键字传入一个空的碰撞信息类,碰撞后会对其赋值。通过该参数可以得到碰撞物体的transform、rigidbody、point等信息。layerMask:只选定LayerMask层内的碰撞器,其它层内的碰撞器将被忽略,实现选择性的碰撞。
6. RaycastHit[] RaycastAll(Ray ray, float distance, int layerMask)
投射一条光线并返回所有碰撞信息,返回值是一个 RaycastHit[] 结构体数组。
射线碰撞检测示例代码
using UnityEngine;
using System.Collections;
public class RayTest : MonoBehaviour {
// Use this for initialization
void Start () {
mainCrma = Camera.main;
}
private Camera mainCrma;
private RaycastHit objhit;
private Ray _ray;
void Update () {
if (Input.GetMouseButtonDown(0)) {
_ray = mainCrma.ScreenPointToRay(Input.mousePosition); // 从摄像机发出一条射线,到点击的坐标
Debug.DrawLine(_ray.origin, objhit.point, Color.red, 2); // 显示一条射线,只有在Scene视图中才能看到
if (Physics.Raycast (_ray, out objhit, 100)) {
GameObject gameObj = objhit.collider.gameObject;
Debug.Log("Hit objname:" + gameObj.name + " Hit objlayer:" + gameObj.layer);
}
}
}
}
LayerMask 参数详解
Raycast 方法的 layerMask 参数用于控制射线只与特定层的碰撞器发生交互。以下是一些常见的 layerMask 使用方式:
1 << 10:打开第10层。~(1 << 10):打开除了第10层之外的所有层。~(1 << 0):打开所有的层。(1 << 10) | (1 << 8):打开第10层和第8层。
LayerMask 使用示例代码
using UnityEngine;
using System.Collections;
public class LayerMaskTest : MonoBehaviour {
// Use this for initialization
void Start () {
mainCrma = Camera.main;
mask = 1 << (LayerMask.NameToLayer("cube")); // 实例化mask到cube这个自定义的层级之上。
}
private LayerMask mask;
private Camera mainCrma;
private RaycastHit objhit;
private Ray _ray;
void Update () {
if (Input.GetMouseButtonDown(0)) {
_ray = mainCrma.ScreenPointToRay(Input.mousePosition); // 从摄像机发出一条射线,到点击的坐标
Debug.DrawLine(_ray.origin, objhit.point, Color.red, 2); // 划出射线,只有在Scene视图中才能看到
if (Physics.Raycast (_ray, out objhit, 100, mask.value)) {
GameObject gameObj = objhit.collider.gameObject;
Debug.Log("Hit objname:" + gameObj.name + "--Hit objlayerName:" + LayerMask.LayerToName (10));
}
}
}
}
测试说明
创建两个 Cube,一个 layer 设置为 cube,另一个 layer 设置为 Default,运行上述代码进行测试。