🟥 前言
Unity Collider的检测目前接触到的可以分为两种:
🚩OnTrigger、OnCollider
🚩Physics.Overlap
下面我们重点记录下第二种方法的应用。
Physics.Overlap
**功能:**以自身形状,向外,发射设定好长度大小的射线。可获取到射线检测到的物体。
注意:
a、获取到的物体都包含自身。
b、自身可不需要Collider、Rigidbody。是以代码设定好的范围,去检测周围是否有collider。且要检测的collider也不需要有rigidbody。
下面代码要用到collider完全是因为可视化检测区域。
建议:
因为检测不是基于碰撞,但需要可视化检测范围。建议直接将脚本挂载在对应形状的3D物体上。Start时可隐藏MeshRenderer、Collider。
也可将脚本挂载到其他物体上,下面代码transform前加上正确位置的gameObject(检测它的位置)。
🟧 Physics.OverlapCapsule
Collider[] outputCols = Physics.OverlapCapsule(pointTop, pointBottom, radius, LayerMask.GetMask("Ground"));
注意:
a、注意自身物体scale、方向,对检测有影响。
方向已用transform.up修正。
b、本Collider基于默认方向 Direction:Y-Axis、Center为0
c、在缩放该CapsuleCollider时:
当前代码只能整体物体缩放,父物体也必须是整体缩放(预计可增加缩放Y轴操作,如有需要再更新代码)。
可调整Collider Radius、Height,可旋转。
d、可视化的CapsuleCollider就是检测范围。
/// <summary> /// 当前实时检测到的带 碰撞器、Vive_InteractableObject 的物体 /// </summary> public List<Transform> skode_detectObjs = new List<Transform>(); CapsuleCollider capcol = null; private void Start() { capcol = GetComponent<CapsuleCollider>(); } private void Update() { Detection(); } void Detection() { float offset = capcol.height * 0.5f; float radius = capcol.radius; float scale = capcol.transform.localScale.x; Transform tempTrans = capcol.transform.parent; while (tempTrans != null) { scale = scale * tempTrans.localScale.x; tempTrans = tempTrans.parent; } Vector3 pointTop = capcol.transform.position + capcol.transform.up * (radius - offset) * scale; Vector3 pointBottom = capcol.transform.position + (capcol.transform.up * (capcol.height - offset) - capcol.transform.up * radius) * scale; Collider[] outputCols = Physics.OverlapCapsule(pointTop, pointBottom, radius * scale); //只检测Ground层物体。 //outputCols = Physics.OverlapCapsule(pointTop, pointBottom, radius, LayerMask.GetMask("Ground")); skode_detectObjs.Clear(); if (outputCols != null && outputCols.Length > 0) { foreach (var item in outputCols) { if (item.transform != transform && item.GetComponent<Vive_InteractableObject>()) { skode_detectObjs.Add(item.transform); } } } }
🟨 Physics.OverlapBox
//模拟的盒子中心点,x、y、z轴长度的一半 Collider[] outputCols = Physics.OverlapBox(boxCol.transform.position, scale / 2,boxCol.transform.rotation);
注意:
a、可随意缩放自身(从某点发射检测射线的那个物体)、父物体比例,可旋转。
b、若你挂在了cube上,可视化的BoxCollider就是检测范围。
c、下方的Center是0、Size是1.若Size变了,需要更新下方代码。
/// <summary> /// 当前实时检测到的带 碰撞器、Vive_InteractableObject 的物体 /// </summary> public List<Transform> skode_detectObjs = new List<Transform>(); BoxCollider boxCol = null; private void Start() { boxCol = GetComponent<BoxCollider>(); } private void Update() { DetectionBox(); } void DetectionBox() { Vector3 scale = boxCol.transform.localScale; Transform tempTrans = boxCol.transform.parent; while (tempTrans != null) { scale = Skode_Vec3Mul(scale, tempTrans.localScale); tempTrans = tempTrans.parent; } //模拟的盒子中心点,x、y、z轴长度的一半 Collider[] outputCols = Physics.OverlapBox(boxCol.transform.position, scale / 2,boxCol.transform.rotation); skode_detectObjs.Clear(); if (outputCols != null && outputCols.Length > 0) { foreach (var item in outputCols) { if (item.transform != transform && item.GetComponent<Vive_InteractableObject>()) { skode_detectObjs.Add(item.transform); } } } } Vector3 Skode_Vec3Mul(Vector3 value1, Vector3 value2) { return new Vector3(value1.x * value2.x, value1.y * value2.y, value1.z * value2.z); }
🟩 Physics.OverlapSphere
Collider[] outputCols = Physics.OverlapSphere(sphereCol.transform.position, GetComponent<SphereCollider>().radius * scale);
注意:
a、自身物体scale 对检测有影响。
c、在缩放该CapsuleCollider时:
当前代码只能整体物体缩放,父物体也必须是整体缩放
可调整Collider Radius
d、可视化的CapsuleCollider就是检测范围。
/// <summary> /// 当前实时检测到的带 碰撞器、Vive_InteractableObject 的物体 /// </summary> public List<Transform> skode_detectObjs = new List<Transform>(); SphereCollider sphereCol = null; private void Start() { sphereCol = GetComponent<SphereCollider>(); } private void Update() { DetectionSphere(); } void DetectionSphere() { float scale = sphereCol.transform.localScale.x; Transform tempTrans = sphereCol.transform.parent; while (tempTrans != null) { scale = scale * tempTrans.localScale.x; tempTrans = tempTrans.parent; } Collider[] outputCols = Physics.OverlapSphere(sphereCol.transform.position, GetComponent<SphereCollider>().radius * scale); skode_detectObjs.Clear(); if (outputCols != null && outputCols.Length > 0) { foreach (var item in outputCols) { if (item.transform != transform && item.GetComponent<Vive_InteractableObject>()) { skode_detectObjs.Add(item.transform); } } } }