Physics.ComputePenetration

Switch to Manual
public static bool ComputePenetration (Collider colliderA, Vector3 positionA, Quaternion rotationA, Collider colliderB, Vector3 positionB, Quaternion rotationB, out Vector3 direction, out float distance);

Parameters

colliderA第一个碰撞体。
positionA第一个碰撞体的位置。
rotationA第一个碰撞体的旋转。
colliderB第二个碰撞体。
positionB第二个碰撞体的位置。
rotationB第二个碰撞体的旋转。
direction将碰撞体分开所需的最小平移所沿的方向。
distance沿该方向将碰撞体分开所需的距离。

Returns

bool 如果碰撞体在给定姿势下重叠,则返回 true。

Description

计算在指定姿势下将给定碰撞体分开所需的最小平移。

如果函数返回 true,则将第一个碰撞体平移方向 * 距离将使两个碰撞体分开。否则,方向和距离未定义。

其中一个碰撞体必须为 BoxCollider、SphereCollider、CapsuleCollider 或凸面 MeshCollider。另一个可以是任何类型。

Note that you aren't restricted to the position and rotation the colliders have at the moment of the call. Passing position or rotation that is different from the currently set one doesn't have an effect of physically moving any colliders thus has no side effects on the Scene.

不要求先更新任何空间结构,因此也可以在 FixedUpdate 时间范围以外使用。

Ignores backfaced triangles and doesn't respect Physics.queriesHitBackfaces.

在编写自定义 depenetration 函数时,该函数很有用。一个具体示例是实现需要对与周围物理对象的碰撞作出特定反应的角色控制器。在这种情况下,您可以先使用 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); } } } }