Physics.CheckBox
: 检查给定位置的盒子是否与任何碰撞器接触或者位于任何碰撞器内部。Physics.CheckCapsule
: 检查给定位置的胶囊是否与任何碰撞器接触或者位于任何碰撞器内部。Physics.CheckSphere
: 检查给定位置的球体是否与任何碰撞器接触或者位于任何碰撞器内部。Physics.ClosestPoint
: 寻找指定位置最近的点,返回碰撞体表面上最接近给定位置的点。Physics.IgnoreCollision
: 使物理引擎忽略两个碰撞器之间的所有碰撞。Physics.IgnoreLayerCollision
: 让物理引擎忽略特定层之间的所有碰撞。Physics.GetIgnoreLayerCollision
: 检查物理引擎是否忽略特定层之间的所有碰撞。Physics.GetIgnoreCollision
:检查物理引擎是否忽略特定物体之间的所有碰撞Physics.ComputePenetration
:用于计算两个重叠碰撞器之间的穿透向量和距离的方法Physics.OverlapBox
: 返回在给定位置盒子覆盖的所有碰撞器。Physics.OverlapBoxNonAlloc
:返回在给定位置盒子覆盖的所有碰撞器,但不会分配新的内存来返回碰撞器。将结果填充到一个预先存在的数组中,从而避免了频繁的内存分配和收集,这可以帮助优化性能。Physics.OverlapCapsule
: 返回在给定位置胶囊覆盖的所有碰撞器。Physics.OverlapCapsuleNonAlloc
:返回在给定位置胶囊覆盖的所有碰撞器,并将这些碰撞器存放在预定义的数组中。Physics.OverlapSphere
: 返回在给定位置球体覆盖的所有碰撞器。Physics.OverlapSphereNonAlloc
:返回在给定位置球体覆盖的所有碰撞器,并将这些碰撞器存放在预定义的数组中。
参数:
返回值:
返回 true,如果在盒子区域内有碰撞器;否则返回 false。
示例:
假设你想要检查一个中心在 (0, 0, 0),尺寸为 (1, 1, 1) 的盒子内是否有任何物体:
Vector3 boxCenter = new Vector3(0, 0, 0);
Vector3 halfExtents = new Vector3(0.5f, 0.5f, 0.5f);
if (Physics.CheckBox(boxCenter, halfExtents))
{
Debug.Log("盒子里有东西");
}
参数:
返回值:
返回 true,如果在胶囊区域内有碰撞器;否则返回 false。
示例:
假设你想要检查一个从 (0, 0, 0) 到 (0, 2, 0),半径为 0.5 的胶囊是否有物体:
Vector3 point1 = new Vector3(0, 0, 0);
Vector3 point2 = new Vector3(0, 2, 0);
float radius = 0.5f;
if (Physics.CheckCapsule(point1, point2, radius))
{
Debug.Log("胶囊里有东西");
}
参数:
返回值:
bool:如果球体与任何碰撞器重叠,则返回 true,否则返回 false。
示例:
假设你想在坐标 (0, 1, 0) 上检查一个半径为 0.5 的球体是否与任何物体重叠:
Vector3 sphereCenter = new Vector3(0, 1, 0);
float sphereRadius = 0.5f;
if (Physics.CheckSphere(sphereCenter, sphereRadius))
{
Debug.Log("球体里有东西");
}
参数:
返回值:
Vector3:表示在碰撞器上与给定点最近的点的位置。
用更直观的方式来解释:
假设你手里有一个苹果(这就是我们的Collider或碰撞器)。现在,你想知道,如果你指向这个苹果的某一点,你的手指最终会碰到苹果的哪个部分。这个与你的手指最先接触的部分就是ClosestPoint 即最近点。
示例:
假设我们有一个场景,其中包含一个球形角色(使用球形碰撞器)和一个可以移动的指针。当指针接近这个球形角色时,我们想要在球上显示一个小的标记,以指示哪个部分是距离指针最近的。
public Transform sphere; // 球形角色的Transform
public Transform pointer; // 指针的Transform
public GameObject marker; // 标记物体,可以是一个小球或其他指示器
private Collider sphereCollider;
void Start()
{
// 获取球形角色的碰撞器
sphereCollider = sphere.GetComponent<Collider>();
}
void Update()
{
// 使用Physics.ClosestPoint()获取与指针最近的球面上的点
Vector3 closestPoint = Physics.ClosestPoint(pointer.position, sphereCollider, sphere.position, sphere.rotation);
// 将标记设置为那个点的位置
marker.transform.position = closestPoint;
}
在这个代码中,当指针移动时,标记(marker)会在球形角色上移动,以始终指向与指针最接近的部分。这是使用 Physics.ClosestPoint() 为游戏添加视觉效果或用户反馈的一个简单示例。
参数:
用途:
使用此方法可以控制两个碰撞器之间是否发生物理交互。例如,你可能希望在某些情况下防止玩家与特定对象发生碰撞,或者你可能有两个物体总是相互穿透并且不互相碰撞。
示例:
假设你有一个玩家角色。当玩家获得某种能力时,你希望玩家能够穿越墙壁,而不是与其碰撞。此时,你可以使用 Physics.IgnoreCollision 来达到这个效果:
public Collider playerCollider;
public Collider wallCollider;
// 当玩家获得穿越墙壁的能力时调用此方法
public void GainWallPassAbility()
{
// 让玩家和墙壁之间的碰撞被忽略
Physics.IgnoreCollision(playerCollider, wallCollider, true);
}
// 如果玩家失去了穿越墙壁的能力,你可以再次启用碰撞
public void LoseWallPassAbility()
{
Physics.IgnoreCollision(playerCollider, wallCollider, false);
}
注意:
Physics.IgnoreCollision 只影响物理碰撞检测,而不影响触发器事件。如果两个碰撞器中的一个或两者都有触发器,那么它们之间的交互仍然会生成触发器事件。
参数:
用途:
此方法非常适用于游戏中的大量对象,这些对象可能需要在某些情境下避免与某些其他对象的碰撞,但在其他情境下又需要与这些对象发生碰撞。
示例:
假设你的游戏中有玩家、敌人和由玩家发射的子弹。你不希望玩家发射的子弹能够打击玩家本身,但希望它能够打击敌人。为此,你可以为玩家设置一个层(例如 “Player”),为子弹设置一个层(例如 “PlayerBullet”),然后使用 Physics.IgnoreLayerCollision 来确保 “Player” 和 “PlayerBullet” 之间不会发生碰撞:
private void Start()
{
int playerLayer = LayerMask.NameToLayer("Player");
int playerBulletLayer = LayerMask.NameToLayer("PlayerBullet");
// 忽略 "Player" 和 "PlayerBullet" 之间的碰撞
Physics.IgnoreLayerCollision(playerLayer, playerBulletLayer, true);
}
这意味着当玩家发射子弹时,子弹不会与玩家碰撞,但可以与其他层的对象碰撞,例如敌人。
参数:
返回值:
返回 true:表示这两个层之间的碰撞已经被忽略。
返回 false:表示这两个层之间的碰撞是启用的。
用途:
你可能会在某些时刻需要查询某两个层之间的碰撞状态,例如在调试过程中或在某些游戏逻辑中。此方法允许你在不更改实际设置的情况下检查碰撞忽略状态。
示例:
假设你在一个场景中有两个层:“Player” 和 “Enemy”。你已经为这两个层设置了碰撞忽略规则,但你希望在某个时刻检查这两个层之间的碰撞状态:
void Start()
{
int playerLayer = LayerMask.NameToLayer("Player");
int enemyLayer = LayerMask.NameToLayer("Enemy");
if (Physics.GetIgnoreLayerCollision(playerLayer, enemyLayer))
{
Debug.Log("“玩家与敌人之间的碰撞被忽略了");
}
}
此脚本将会输出当前的碰撞状态,告诉你玩家和敌人之间的碰撞是否被忽略。
Tips:
这个方法特别有用于复杂的场景,尤其是当你有多个层和碰撞规则时。它允许你在运行时获得这些层之间的碰撞信息,这对于调试和游戏逻辑都非常有价值。
参数:
返回值:
返回 true:如果这两个碰撞器之间的碰撞已经被忽略。
返回 false:如果这两个碰撞器之间的碰撞是启用的。
用途:
有时,你可能不希望两个特定的游戏对象发生物理交互(例如,可能是因为它们是团队成员并且不应该相互伤害)。在这种情况下,你可以使用 Physics.IgnoreCollision 设置碰撞忽略规则。之后,你可以使用 Physics.GetIgnoreCollision 检查这两个碰撞器之间是否真的忽略了碰撞。
示例:
假设你有两个游戏对象,“Player” 和 “Teammate”,它们都有碰撞器。你已经设置了为它们之间的碰撞忽略规则,但你希望检查这两个对象之间的碰撞状态:
public Collider playerCollider;
public Collider teammateCollider;
void Start()
{
if (Physics.GetIgnoreCollision(playerCollider, teammateCollider))
{
Debug.Log("玩家和队友之间的碰撞被忽略!");
}
}
此脚本将检查"Player"和"Teammate"之间的碰撞状态,并输出相关信息。
参数:
返回值:
返回 true:两个碰撞器发生了穿透。
返回 false:两个碰撞器没有发生穿透。
用途:
该方法主要在需要精确控制如何解决碰撞的高级物理模拟或自定义碰撞响应系统中使用。例如,你可能希望在两个对象重叠时以特定的方式将它们推开,而不仅仅是依赖Unity的物理引擎来处理它们。
示例:
假设你有两个游戏对象,“ObjectA” 和 “ObjectB”,它们都有碰撞器。你希望检查并处理它们之间的任何穿透情况:
public Collider colliderA;
public Collider colliderB;
void Update()
{
Vector3 penetrationDirection;
float penetrationDistance;
if (Physics.ComputePenetration(
colliderA, colliderA.transform.position, colliderA.transform.rotation,
colliderB, colliderB.transform.position, colliderB.transform.rotation,
out penetrationDirection, out penetrationDistance))
{
Debug.Log("“渗透检测!");
// 您可以根据penetrationDirection和penetrationDistance进行操作
// 例如,将对象分开移动。
}
}
在这个示例中,如果"colliderA"和"colliderB"碰撞器发生穿透,脚本会输出相关信息,并允许你根据penetrationDirection和penetrationDistance采取适当的措施。
参数:
返回值:
返回一个 Collider[] 数组,该数组包含与指定盒子相交或重叠的所有物体的碰撞器。
用途:
此方法主要用于检测在给定盒子区域内的物体,例如在射击游戏中检测玩家是否在某个房间内,或在模拟环境中检测某个区域内的所有实体。
示例:
假设你想检查位于(0, 0, 0)处的一个大小为(2, 2, 2)的盒子内的所有碰撞器:
void Start()
{
Vector3 boxCenter = new Vector3(0, 0, 0);
Vector3 boxHalfSize = new Vector3(1, 1, 1); // 对应盒子的完整尺寸是 2x2x2
Collider[] collidersInsideBox = Physics.OverlapBox(boxCenter, boxHalfSize);
foreach (Collider col in collidersInsideBox)
{
Debug.Log("物体" + col.name + "“在盒子里!”");
}
}
这个示例脚本会列出所有在指定盒子内的物体。你可以将它附加到任何游戏对象上,它会在游戏开始时检查盒子内的物体,并打印出它们的名称。
Physics.BakeMesh
:允许为一个网格计算碰撞信息Physics.RebuildBroadphaseRegions
:重新构建其广阶段的碰撞检测区域Physics.Simulate
:手动进行物理仿真Physics.SyncTransforms
:同步物理系统中的变换信息与Unity的变换组件的数据。
功能描述:
Physics.BakeMesh 用于计算一个网格的碰撞数据。当你动态生成一个网格并打算将其用作碰撞体时,可以使用此方法提前计算其碰撞数据,以确保物理模拟的准确性。
参数:
使用场景:
当你在运行时动态创建网格,尤其是使用脚本或计算生成的网格,并且希望该网格参与物理碰撞检测,这时你可以使用 Physics.BakeMesh。它确保为这些网格预计算了必要的碰撞数据,从而使碰撞检测更为准确和高效。
示例:
假设你动态创建了一个网格,并且为其分配了一个网格碰撞器:
Mesh myMesh = new Mesh();
// ... 填充网格的顶点、三角形等数据 ...
GameObject myObject = new GameObject("DynamicObject");
MeshCollider meshCollider = myObject.AddComponent<MeshCollider>();
meshCollider.sharedMesh = myMesh;
// 烘焙网格的碰撞数据
Physics.BakeMesh(myMesh.GetInstanceID(), true);
注意:
此方法的主要用途是为网格碰撞器烘焙碰撞数据。如果你不打算动态修改或生成网格,并且在编辑器中已经分配了静态网格,那么通常不需要使用此方法。
功能描述:
此方法允许你强制物理引擎针对给定的世界范围和子区域数量,重新构建其广阶段的碰撞检测区域。
参数:
worldBounds (Bounds):这是一个Bounds结构,代表了你希望物理引擎考虑的世界空间的范围。只有在这个范围内的物体才会被考虑进广阶段的碰撞检测。
subdivisions (int): 一个指示你想将worldBounds划分为多少子区域的整数。这可以用来优化广阶段的碰撞检测,特别是当你知道物体在世界中的分布并希望根据该分布来进行优化时。
使用场景:
如果在一个特定的worldBounds范围内有很多物体,并且你希望物理引擎更有效地管理这个范围内的碰撞检测,那么可以使用此方法。通过合理地选择子区域数量,你可以更好地平衡性能和精度。
示例:
假设你有一个游戏世界,其主要活动范围是从(-50, -50, -50)到(50, 50, 50)。在这个范围内有很多物体,你希望将其划分为8个子区域以优化碰撞检测。
Bounds myWorldBounds = new Bounds(Vector3.zero, new Vector3(100, 100, 100));
Physics.RebuildBroadphaseRegions(myWorldBounds, 2); // 2^3 = 8 细分
注意:
要谨慎使用这个功能,因为不恰当地设置worldBounds和subdivisions可能会导致不预期的性能问题。此外,如果物体移出了指定的worldBounds,它们可能不会参与碰撞检测。
参数:
step (float): 要仿真的时间长度(以秒为单位)。
使用场景:
预览或预测物理效果: 例如,预测一个抛出的物体的着陆点。
非实时仿真: 在后台进行物理计算,例如在策略游戏中模拟多回合的战斗结果。
自定义时间缩放: 在特定情境下,可能需要使物理仿真速度与游戏的主循环速度脱钩。
注意事项:
示例:
假设你想预测一个物体在未来5秒内的移动路径:
float simulationTime = 5.0f;
// 先保存物体的当前状态
Vector3 originalPosition = myObject.transform.position;
// 进行仿真
Physics.Simulate(simulationTime);
// 获取仿真后的位置
Vector3 predictedPosition = myObject.transform.position;
// 恢复物体的原始状态
myObject.transform.position = originalPosition;
在这个例子中,我们仿真了物体在未来5秒的移动,并获取了它的预测位置,然后我们将其状态恢复为仿真之前的状态。
用于同步物理系统中的变换信息与Unity的变换组件(Transform component)的数据。在大多数情况下,Unity物理系统会自动进行同步,但在某些特定的操作后,比如使用 Physics.Simulate 方法进行手动仿真,你可能需要明确地调用 Physics.SyncTransforms 以确保同步。
为何需要同步:
在Unity中,物理模拟与渲染或其它游戏逻辑是分开的。当物体在物理系统中移动时,它的物理表示与在场景中的实际表现(即Transform组件)可能会有所偏差。Physics.SyncTransforms 确保这两者之间的同步。
使用场景:
注意事项:
过于频繁地调用此方法可能会导致性能开销,因此建议只在必要的时候使用。
示例:
// 假设我们有一个物体,我们想快速地改变其位置,然后立即进行物理仿真
myObject.transform.position = newPosition;
// 由于我们直接改变了物体的位置,现在同步物理系统的变换信息
Physics.SyncTransforms();
// 现在进行物理仿真,例如预测物体的下一秒位置
Physics.Simulate(1.0f);
在这个例子中,我们首先移动了一个物体,然后调用 Physics.SyncTransforms 来确保物理系统中的变换与Unity的变换组件是同步的,最后进行了物理仿真。
注意使用这个类,特别是涉及物理模拟的部分,需要理解物理学的基本原理。如果对物理学的理解不足,可能会遇到预期外的结果。一般来说,尽量避免创建不真实的物理条件(如零摩擦力,无限大的力等)。