In-depth understanding of Unity’s Physics class: a detailed technical guide (7) (Part 2)

Following the previous article's in-depth understanding of Unity's Physics class (Part 1) , we continue to explain the remaining properties and methods of the Physics class.


  1. Collision detection and ignoring:
    (These methods and properties are involved in querying and handling collisions between objects)
    Physics.CheckBox: Checks whether the box at the given position is in contact with or inside any collider.
    Physics.CheckCapsule: Checks if the capsule at the given position is in contact with or inside any collider.
    Physics.CheckSphere: Checks if the sphere at the given position is in contact with or inside any collider.
    Physics.ClosestPoint: Find the closest point to the specified position and return the point on the surface of the collider that is closest to the given position.
    Physics.IgnoreCollision: Causes the physics engine to ignore all collisions between two colliders.
    Physics.IgnoreLayerCollision: Makes the physics engine ignore all collisions between specific layers.
    Physics.GetIgnoreLayerCollision: Checks whether the physics engine ignores all collisions between specific layers.
    Physics.GetIgnoreCollision: Checks if the physics engine ignores all collisions between specific objects
    Physics.ComputePenetration: Method for calculating the penetration vector and distance between two overlapping colliders
    Physics.OverlapBox: Returns all colliders covered by the box at the given position.
    Physics.OverlapBoxNonAlloc:Returns all colliders covered by the box at the given position, but no new memory is allocated to return the colliders. Filling the results into a pre-existing array avoids frequent memory allocations and collections, which can help optimize performance.
    Physics.OverlapCapsule: Returns all colliders covered by the capsule at the given position.
    Physics.OverlapCapsuleNonAlloc:Returns all colliders covered by the capsule at a given position and stores these colliders in a predefined array.
    Physics.OverlapSphere: Returns all colliders covered by the sphere at the given position.
    Physics.OverlapSphereNonAlloc:Returns all colliders covered by the sphere at a given position and stores these colliders in a predefined array.

Physics.CheckBox()

Used to detect the presence of any collider within a given box-shaped area. This kind of detection is useful in many scenarios, such as checking whether the player is in a specific space, or testing whether the position before placing the object is empty.

 
parameter:

  • center: The center position of the box.
  • halfExtents: half size of the box. In other words, it is the distance from the center of the box to the edge.
  • orientation: (optional parameter) The rotation of the box. Defaults to Quaternion.identity, which means no rotation.
  • layerMask: (optional parameter) is used to filter the object layer to be tested. Defaults to -1, which will include all layers.
  • queryTriggerInteraction: (optional parameter) Specifies how to handle trigger colliders. Default is QueryTriggerInteraction.UseGlobal.

Return value:
Returns true if there is a collider within the box area; otherwise returns false.

Example:
Suppose you want to check if there is any object inside a box centered at (0, 0, 0) with dimensions (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("盒子里有东西");
}

Physics.CheckCapsule()

Used to detect the presence of any collider within a specified capsule-shaped area. The capsule shape can be thought of as a shape consisting of two spheres with a cylinder between them. This method is often used for collision detection on character controllers, as the capsule shape tends to be a good approximation of the shape of many game characters.

 
parameter:

  • point1: An endpoint of the capsule.
  • point2: the other endpoint of the capsule.
  • radius: The radius of the capsule.
  • layerMask: (optional parameter) is used to filter the object layer to be tested. Defaults to -1, which will include all layers.
  • queryTriggerInteraction: (optional parameter) Specifies how to handle trigger colliders. Default is QueryTriggerInteraction.UseGlobal.

Return value:
Returns true if there is a collider within the capsule area; otherwise returns false.

Example:
Suppose you want to check whether a capsule with a radius of 0.5 from (0, 0, 0) to (0, 2, 0) has an object:

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("胶囊里有东西");
}

Physics.CheckSphere()

This function checks whether the sphere at the specified position is in contact with or overlapping any collider. It is often used to test whether there are obstacles in an area, such as before entity placement, player movement, or object spawning.

 
parameter:

  • center: The center position of the sphere.
  • radius: The radius of the sphere.
  • layerMask (optional): A LayerMask that allows you to filter specific layers that interact with the sphere. By default this interacts with all layers.
  • queryTriggerInteraction (optional): Describes how to handle trigger colliders. Default is QueryTriggerInteraction.UseGlobal.

Return value:
bool: Returns true if the sphere overlaps any collider, false otherwise.

Example:
Suppose you want to check if a sphere with radius 0.5 overlaps any object at coordinates (0, 1, 0):

Vector3 sphereCenter = new Vector3(0, 1, 0);
float sphereRadius = 0.5f;
if (Physics.CheckSphere(sphereCenter, sphereRadius))
{
    
    
    Debug.Log("球体里有东西");
}

Physics.ClosestPoint()

Used to find the closest point on a given collider to a specified point. This is useful in many scenarios, such as in ray tracing, object interaction, or distance measurement.

 
parameter:

  • Vector3 position: The position of the collider on which you want to find the closest point.
  • Collider collider: Collider instance on which you want to find the closest point.
  • Vector3 point: A position point, and you want to find the point on the collider that is closest to it.

Return value:
Vector3: Represents the position of the closest point to the given point on the collider.

To explain it in a more intuitive way :
imagine you have an apple in your hand (this is our Collider or Collider). Now, you want to know, if you point at a certain point on this apple, which part of the apple will your finger end up touching. The part that comes into contact with your finger first is the ClosestPoint.

Example:
Let's say we have a scene with a spherical character (using a spherical collider) and a pointer that can be moved. As the pointer approaches the spherical character, we want to display a small marker on the ball to indicate which part is closest to the pointer.

    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;
    }

In this code, as the pointer moves, the marker moves on the spherical character so that it always points to the part closest to the pointer. This is a simple example of using Physics.ClosestPoint() to add visual effects or user feedback to your game.


Physics.IgnoreCollision

Allows you to set whether two colliders should ignore all collisions between them

 
parameter:

  • collider1: The first collider.
  • collider2: The second collider.
  • ignore: If true, collisions between the two will be ignored. If false, collision between them will be enabled. The default is true.

Purpose:
Use this method to control whether physical interaction occurs between two colliders. For example, you might want to prevent the player from colliding with a specific object under certain circumstances, or you might have two objects that always penetrate each other and never collide with each other.

Example:
Let's say you have a player character. When the player gains a certain ability, you want the player to be able to walk through the wall, not collide with it. At this point, you can use Physics.IgnoreCollision to achieve this effect:

    public Collider playerCollider;
    public Collider wallCollider;

    // 当玩家获得穿越墙壁的能力时调用此方法
    public void GainWallPassAbility()
    {
    
    
        // 让玩家和墙壁之间的碰撞被忽略
        Physics.IgnoreCollision(playerCollider, wallCollider, true);
    }

    // 如果玩家失去了穿越墙壁的能力,你可以再次启用碰撞
    public void LoseWallPassAbility()
    {
    
    
        Physics.IgnoreCollision(playerCollider, wallCollider, false);
    }

注意: Physics.IgnoreCollision only affects physics collision detection, not trigger events. If one or both of the two colliders have triggers, the interaction between them will still generate trigger events.


Physics.IgnoreLayerCollision

Allows you to set a global rule for collision between specified layers, deciding whether or not they should collide with each other. In Unity, using layers is a way of organizing and managing game objects. By using layers, you can easily define which objects should interact with other objects and how.

 
parameter:

  • layer1: Index of the first layer.
  • layer2: Index of the second layer.
  • ignore: If true, the collision between layer1 and layer2 will be ignored. If false, collision between them will be enabled. The default is true.

Purpose:
This method is ideal for a large number of objects in the game, which may need to avoid collisions with certain other objects in some situations, but need to collide with these objects in other situations.

Example:
Suppose your game has a player, enemies, and bullets fired by the player. You don't want the bullet fired by the player to hit the player itself, but you want it to hit the enemy. To do this, you would set up a layer for the player (e.g. "Player"), a layer for the bullet (e.g. "PlayerBullet"), and then use Physics.IgnoreLayerCollision to ensure there is no collision between "Player" and "PlayerBullet":

private void Start()
{
    
    
    int playerLayer = LayerMask.NameToLayer("Player");
    int playerBulletLayer = LayerMask.NameToLayer("PlayerBullet");

    // 忽略 "Player" 和 "PlayerBullet" 之间的碰撞
    Physics.IgnoreLayerCollision(playerLayer, playerBulletLayer, true);
}

This means that when the player fires a bullet, the bullet will not collide with the player, but can collide with objects on other layers, such as enemies.


Physics.GetIgnoreLayerCollision

Method for checking whether a collision ignore rule exists between two specified layers. This helps you dynamically query collision settings between two layers at runtime.

 
parameter:

  • layer1: Index of the first layer.
  • layer2: Index of the second layer.

Return value:
Return true: indicating that the collision between the two layers has been ignored.
Return false: indicating that collision between these two layers is enabled.

Purpose:
You may need to query the collision status between two layers at some point, such as during debugging or in some game logic. This method allows you to check the collision ignore status without changing the actual settings.

Example:
Let's say you have two layers in a scene: "Player" and "Enemy". You've set up collision ignore rules for both layers, but at some point you want to check the collision status between the two layers:

void Start()
{
    
    
    int playerLayer = LayerMask.NameToLayer("Player");
    int enemyLayer = LayerMask.NameToLayer("Enemy");
    if (Physics.GetIgnoreLayerCollision(playerLayer, enemyLayer))
    {
    
    
        Debug.Log("“玩家与敌人之间的碰撞被忽略了");
    }
}

This script will output the current collision status, telling you whether collisions between the player and the enemy are ignored.

Tips:This method is particularly useful in complex scenes, especially when you have multiple layers and collision rules. It allows you to get collision information between these layers at runtime, which is very valuable for both debugging and game logic.


Physics.GetIgnoreCollision

Allows you to query whether a collision ignore rule exists between two specific colliders. This is for individual colliders, not for the entire layer. This method can help you determine whether collision ignore rules have been set for these two specific colliders.

 
parameter:

  • collider1: The first collider.
  • collider2: The second collider.

Return value:
Returns true if the collision between these two colliders has been ignored.
Returns false if collision between these two colliders is enabled.

Purpose:
Sometimes, you may not want two specific game objects to physically interact (for example, perhaps because they are team members and shouldn't hurt each other). In this case, you can use Physics.IgnoreCollision to set collision ignore rules. Afterwards, you can use Physics.GetIgnoreCollision to check whether the collision between these two colliders is actually ignored.

Example:
Suppose you have two game objects, "Player" and "Teammate", both of which have colliders. You've set up rules to ignore collisions between them, but you want to check the collision status between these two objects:

public Collider playerCollider;
public Collider teammateCollider;

void Start()
{
    
    
    if (Physics.GetIgnoreCollision(playerCollider, teammateCollider))
    {
    
    
        Debug.Log("玩家和队友之间的碰撞被忽略!");
    }
}

This script will check the collision status between "Player" and "Teammate" and output relevant information.


Physics.ComputePenetration

A method for calculating the penetration vector and distance between two overlapping colliders. When two object colliders penetrate each other (e.g. due to rapid movement or other reasons), this function can help determine the size and direction of this penetration so that you can take appropriate steps to correct it.

 
parameter:

  • colliderA and colliderB: The two colliders to check for penetration.
  • positionA and positionB: The positions of collider A and collider B.
  • rotationA and rotationB: the rotation of collider A and collider B.
  • direction (output parameter): If there is a penetration, this will return the direction of the penetration.
  • distance (output parameter): If penetration exists, this returns the distance of penetration.

Return value:
Return true: two colliders have penetrated.
Returns false: no penetration occurs between the two colliders.

Purpose:
This method is primarily used in advanced physics simulations or custom collision response systems that require precise control over how collisions are resolved. For example, you might want to push two objects apart in a specific way when they overlap, rather than just relying on Unity's physics engine to handle them.

Example:
Let's say you have two game objects, "ObjectA" and "ObjectB", both of which have colliders. You want to check and handle any penetration between them:

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进行操作
       // 例如,将对象分开移动。
   }
}

In this example, if penetration occurs between the "colliderA" and "colliderB" colliders, the script will output relevant information and allow you to take appropriate actions based on the penetrationDirection and penetrationDistance.


Physics.OverlapBox

A method that detects all colliders that overlap a given box area. It returns an array of colliders representing all objects that intersect or overlap the specified box area.

 
parameter:

  • center: Specifies the world coordinate position of the center of the box.
  • halfExtents: Specifies half the dimensions of the box in each direction. Therefore, the full size of the box is twice this value.
  • orientation (optional): Defines the rotation of the box. The default value is Quaternion.identity, which means the box is not rotated.
  • layerMask (optional): This is a layer mask used to filter the objects considered in the query. The default value considers all layers.
  • queryTriggerInteraction (optional): Defines how triggers are taken into account. Defaults to QueryTriggerInteraction.UseGlobal, which means it uses global settings.

Return value:
Returns a Collider[] array containing the colliders of all objects that intersect or overlap the specified box.

Purpose:
This method is mainly used to detect objects within a given box area, such as detecting whether the player is in a certain room in a shooting game, or detecting all entities in a certain area in a simulated environment.

Example:
Suppose you want to check all colliders inside a box of size (2, 2, 2) located at (0, 0, 0):

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 + "“在盒子里!”");
   }
}

This example script will list all objects within a specified box. You can attach it to any game object and it will check the objects inside the box at game start and print out their names.


Physics.OverlapCapsule 和 Physics.OverlapSphere

These two methods are similar to the Physics.OverlapBox above. They are also methods used to detect all colliders that overlap with a given collision area. I will not give an example here. You can refer to the above example.
  1. Simulation and scene interaction:
    (these methods involve the simulation and processing of physics scenes)
    Physics.BakeMesh: allows to calculate collision information for a mesh
    Physics.RebuildBroadphaseRegions: reconstruct its wide-stage collision detection area
    Physics.Simulate: manually perform physics simulation
    Physics.SyncTransforms: synchronize transformation information in the physics system with Unity The data of the transform component.

Physics.BakeMesh

A relatively special method that allows you to calculate collision information for a mesh in advance. This can be very useful in certain scenarios, especially when you generate the mesh dynamically at runtime and want to use it for physics collision detection.

 
Function description:
Physics.BakeMesh is used to calculate the collision data of a mesh. When you dynamically generate a mesh and intend to use it as a collider, you can use this method to calculate its collision data in advance to ensure the accuracy of the physics simulation.

parameter:

  • meshID: This is the unique identifier of the mesh to be baked. Typically, when you create a new mesh or modify an existing mesh,
    the GetInstanceID() method provided by the Mesh class can be used to obtain this ID.
  • convex: This boolean determines whether the baked collision information should be convex. Convex colliders have a performance advantage because their collision detection is simpler, but they cannot represent concave or holey shapes. If this parameter is set to true, Unity will attempt to generate a convex collision representation for the given mesh.

Usage scenario:
When you create a mesh dynamically at runtime, especially a mesh generated using scripts or calculations, and you want the mesh to participate in physical collision detection, you can use Physics.BakeMesh. It ensures that the necessary collision data is precomputed for these meshes, making collision detection more accurate and efficient.

Example:
Suppose you dynamically create a mesh and assign a mesh collider to it:

Mesh myMesh = new Mesh();
// ... 填充网格的顶点、三角形等数据 ...

GameObject myObject = new GameObject("DynamicObject");
MeshCollider meshCollider = myObject.AddComponent<MeshCollider>();
meshCollider.sharedMesh = myMesh;

// 烘焙网格的碰撞数据
Physics.BakeMesh(myMesh.GetInstanceID(), true);

注意:The main use of this method is to bake collision data for mesh colliders. If you do not intend to dynamically modify or generate the mesh, and you have assigned a static mesh in the editor, then you generally do not need to use this method.


Physics.RebuildBroadphaseRegions

A method dedicated to advanced physics simulation optimization. It is mainly related to the broadphase detection of the physics engine, which is used to quickly determine which objects are likely to collide, thus optimizing further accurate collision detection.

 
Function description:
This method allows you to force the physics engine to rebuild its wide-stage collision detection area for a given world range and number of sub-areas.

parameter:

  • worldBounds (Bounds): This is a Bounds structure that represents the range of world space you want the physics engine to consider. Only objects within this range will be considered in the wide-stage collision detection.

  • subdivisions (int): An integer indicating how many subregions you want to divide worldBounds into. This can be used to optimize collision detection at a wide stage, especially when you know the distribution of objects in the world and want to optimize based on that distribution.

Usage scenario:
If there are many objects within a specific worldBounds range, and you want the physics engine to manage collision detection within this range more efficiently, you can use this method. By choosing the number of subregions wisely, you can better balance performance and accuracy.

Example:
Suppose you have a game world whose main activity range is from (-50, -50, -50) to (50, 50, 50). There are many objects in this range and you want to divide it into 8 sub-regions to optimize collision detection.

Bounds myWorldBounds = new Bounds(Vector3.zero, new Vector3(100, 100, 100));
Physics.RebuildBroadphaseRegions(myWorldBounds, 2); // 2^3 = 8 细分

注意:Use this feature with caution, as improperly setting worldBounds and subdivisions may cause unexpected performance issues. Additionally, if objects are moved outside the specified worldBounds, they may not participate in collision detection.


Physics.Simulate

Allows manual physics simulation. Unity's physics system automatically performs physical simulation according to a fixed time step (FixedUpdate) by default, but in some specific cases, you may need to manually control the progress of physical simulation in the game logic.

 
Parameters:
step (float): Length of time to simulate (in seconds).

Usage scenarios:
Preview or predict physical effects: for example, predict the landing point of a thrown object.
Non-real-time simulation: Physical calculations are performed in the background, such as simulating the outcome of multi-round battles in a strategy game.
Custom Time Scaling: In certain situations, it may be necessary to decouple the physics simulation speed from the game's main loop speed.

Precautions:

  • When using the Physics.Simulate method, you must ensure that the Physics.SyncTransforms method is called before
    to ensure that the physics system is synchronized with the position and rotation information of the game object.
  • Consecutive calls to Physics.Simulate without allowing the main game loop to progress can cause rendering and game logic to lag or get out of sync.
    Although this method allows you to control the progress of the physics simulation, frequently running simulations with small time steps may degrade performance.

Example:
Suppose you want to predict the movement path of an object in the next 5 seconds:

float simulationTime = 5.0f;

// 先保存物体的当前状态
Vector3 originalPosition = myObject.transform.position;
// 进行仿真
Physics.Simulate(simulationTime);
// 获取仿真后的位置
Vector3 predictedPosition = myObject.transform.position;

// 恢复物体的原始状态
myObject.transform.position = originalPosition;

In this example, we simulate the movement of an object for the next 5 seconds and obtain its predicted position, and then we restore its state to the state before the simulation.


Physics.SyncTransforms

Used to synchronize transformation information in the physical system with data from Unity's Transform component. In most cases, the Unity physics system willSync automatically, but after certain operations, such as manual simulation using the Physics.Simulate method, you may need to explicitly call Physics.SyncTransforms to ensure synchronization.
 
Why synchronization is needed:
In Unity, physics simulation is separated from rendering or other game logic. When an object moves in the physics system, its physical representation may deviate from its actual representation in the scene (i.e., the Transform component). Physics.SyncTransforms ensures synchronization between the two.

scenes to be used:

  1. If you use Physics.Simulate for manual physics simulation, you usually need to call Physics.SyncTransforms afterwards
    to ensure that the physics changes are correctly reflected in the game object's Transform.
  2. After quick modifications to the object's position or rotation: Calling this method can help keep the physics consistent after making rapid position or rotation changes to a large number of objects in a short period of time.

Note:
Calling this method too frequently may cause performance overhead, so it is recommended to only use it when necessary.

Example:

// 假设我们有一个物体,我们想快速地改变其位置,然后立即进行物理仿真
myObject.transform.position = newPosition;
// 由于我们直接改变了物体的位置,现在同步物理系统的变换信息
Physics.SyncTransforms();
// 现在进行物理仿真,例如预测物体的下一秒位置
Physics.Simulate(1.0f);

In this example, we first moved an object, then called Physics.SyncTransforms to ensure that the transformation in the physics system was synchronized with Unity's transformation component, and finally performed a physics simulation.


The above is an explanation of all the properties and methods of the Physics class.

Note the use of this class, especially the part involving physical simulation, requires an understanding of the basic principles of physics. Without an adequate understanding of physics, you may encounter unexpected results. In general, try to avoid creating unrealistic physical conditions (like zero friction, infinite forces, etc.).

Guess you like

Origin blog.csdn.net/qq_33795300/article/details/132203824