colliderA | 第一个碰撞体。 |
positionA | 第一个碰撞体的坐标。 |
rotationA | 第一个碰撞体的旋转。 |
colliderB | 第二个碰撞体。 |
positionB | 第二个碰撞体的坐标。 |
rotationB | 第二个碰撞体的旋转。 |
direction | 将碰撞体分开所需的移动方向(最小化)。 |
distance | direction 方向上将碰撞体分开的距离。 |
bool 如果碰撞体在给定的姿势下重叠,返回 True。
计算将给定碰撞体在指定姿势下分开所需的最小移动量。
如果函数返回 true,沿着 direction * distance 方向移动第一个碰撞体将使碰撞体分开。否则,不定义 direction 和 distance。
其中一个碰撞体必须是盒子碰撞体、球体碰撞体、胶囊状碰撞体或凸多边形网格碰撞体。另一个可以是任意类型。
请注意,并不限制您对碰撞体进行调用时的位置和旋转。传递的位置或旋转与当前设置的位置或旋转不同,不会对物理上移动任何碰撞体产生影响,因此对场景没有产生副作用。
不依赖于任何要首先更新的空间结构,因此不必只在 FixedUpdate 时间范围内使用。
忽略背面三角形,不遵守 Physics.queriesHitBackfaces。
此函数对于编写自定义穿透判定函数非常有用。一个具体的示例是角色控制器的实现,其中需要对与周围物理对象的碰撞做出特定的反应。在这种情况下,首先应使用 OverlapSphere 查询附近的碰撞体,然后使用 ComputePenetration 返回的数据调整角色的位置。
using UnityEngine;
// Visualises the minimum translation vectors required to separate apart from other colliders found in a given radius // Attach to a GameObject that has a Collider attached. [ExecuteInEditMode()] public class ShowPenetration : MonoBehaviour { public float radius = 3f; // show penetration into the colliders located inside a sphere of this radius public int maxNeighbours = 16; // maximum amount of neighbours visualised
private Collider[] neighbours;
public void Start() { neighbours = new Collider[maxNeighbours]; }
public void OnDrawGizmos() { var thisCollider = GetComponent<Collider>();
if (!thisCollider) return; // nothing to do without a Collider attached
int count = Physics.OverlapSphereNonAlloc(transform.position, radius, neighbours);
for (int i = 0; i < count; ++i) { var collider = neighbours[i];
if (collider == thisCollider) continue; // skip ourself
Vector3 otherPosition = collider.gameObject.transform.position; Quaternion otherRotation = collider.gameObject.transform.rotation;
Vector3 direction; float distance;
bool overlapped = Physics.ComputePenetration( thisCollider, transform.position, transform.rotation, collider, otherPosition, otherRotation, out direction, out distance );
// draw a line showing the depenetration direction if overlapped if (overlapped) { Gizmos.color = Color.red; Gizmos.DrawRay(otherPosition, direction * distance); } } } }