Unity 物理引擎:刚体、碰撞器与关节

FreeGuideOnline 最新 2026-06-17

Unity 物理引擎完全指南:刚体、碰撞器与关节

在游戏开发中,物理模拟决定了物体如何移动、碰撞和交互。Unity 内置的 NVIDIA PhysX 引擎提供了强大而高效的工具,让开发者无需编写复杂的数学公式即可实现真实的物理行为。本教程面向零基础初学者,系统讲解 Unity 物理引擎的核心三要素:刚体(Rigidbody)碰撞器(Collider)关节(Joint)。你将学会使用它们构建可控的物理世界,并掌握性能优化技巧。

一、刚体:让物体接受物理法则

刚体是赋予 GameObject 物理属性的核心组件。没有刚体的物体是静态的,不会受重力或力影响。

1.1 刚体关键属性

属性 功能说明 常用场景
Mass 质量(单位任意,相对值)。质量越大,推动它需要的力越大。 轻重物体差异化表现
Drag 移动阻力。数值越高,物体线性减速越快。 模拟空气阻力
Angular Drag 旋转阻力。控制角速度衰减。 让旋转的物体慢慢停下
Use Gravity 是否受重力影响。关闭后物体浮空。 太空环境、飞行道具
Is Kinematic 运动学模式。开启后物体不受物理力影响,仅通过 Transform 或脚本移动,但仍能碰撞其他物体。 移动平台、玩家角色控制
Interpolate 运动平滑模式(None / Interpolate / Extrapolate)。消除高速物体画面抖动。 快速移动的子弹
Collision Detection 碰撞检测精度:Discrete(离散)、Continuous(连续)、Continuous Dynamic(连续动态)。 防止高速物体穿透

1.2 刚体运动控制方式

刚体上的 Rigidbody 组件是控制运动的入口。强烈建议通过刚体接口而非直接修改 Transform 来移动物体,否则会干扰物理状态。

  • AddForce:施加持续力,模拟推力或拉力,适用于自然加速度。
  • velocity:直接设置速度,适用于瞬间达到目标速度(如弹射)。
  • MovePosition:向目标位置移动,遵守碰撞规则,常用于 kinematic 物体或需要穿墙停止的情况。

代码示例:推动箱子

using UnityEngine;

public class PushBox : MonoBehaviour
{
    public Rigidbody rb;
    public float forceMagnitude = 10f;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        if (Input.GetKey(KeyCode.W))
        {
            // 在世界坐标前方施加力
            rb.AddForce(Vector3.forward * forceMagnitude);
        }
    }
}

关键提示:所有物理相关操作必须在 FixedUpdate 中执行,以保证与物理步长同步。

1.3 刚体休眠机制

为优化性能,PhysX 会让低速且无外力作用的刚体进入“休眠”。休眠后的物体不会进行物理计算,直到再次被碰撞或施力唤醒。可通过 Rigidbody.Sleep() 强制休眠,或设置 Sleep Threshold 调整灵敏度。

二、碰撞器:定义物体的物理形状

碰撞器是物体在物理世界中“碰撞体积”的描边。没有碰撞器,刚体之间会直接穿过。

2.1 常见碰撞器类型

碰撞器类型 特点 适合用途
Box Collider 长方体,性能最优 墙壁、箱子、触发区域
Sphere Collider 球体,滚动天然稳定 球、轮子、滚动道具
Capsule Collider 胶囊形,底部平滑 角色控制器、树干
Mesh Collider 基于网格精确形状,性能开销大 静态环境、复杂地形
Terrain Collider 专用于地形对象,自动匹配高度图 自然场景地面
Wheel Collider 专为车辆轮胎设计,内置悬挂与摩擦力 车辆系统

2.2 触发器与物理碰撞

碰撞器上的 Is Trigger 复选框决定了它的行为:

  • 取消勾选(默认):产生物理碰撞,物体会被阻挡。可使用 OnCollisionEnterOnCollisionStayOnCollisionExit 回调。
  • 勾选 Is Trigger:不阻挡物体,仅用于检测“进入范围”。使用 OnTriggerEnterOnTriggerStayOnTriggerExit 回调。

触发器常用于实现检查点、拾取道具、伤害区域等非阻挡性检测。

2.3 碰撞矩阵与层级屏蔽

在项目设置 Physics Settings 中可以通过碰撞矩阵控制哪些层之间会发生碰撞,剔除不必要的计算。例如,将“玩家子弹”层与“敌人”层设为相互碰撞,而“玩家子弹”与“玩家自身”层则屏蔽。合理设置能显著降低物理开销。

2.4 复合碰撞器与物理材质

  • 复合碰撞器:为一个对象添加多个不同形状的碰撞器(例如角色使用胶囊体+球形手脚),精确拟合轮廓,但比单个 Mesh Collider 高效。
  • 物理材质 (Physic Material):赋予碰撞器表面属性 Dynamic Friction(动摩擦)、Static Friction(静摩擦)、Bounciness(弹性)。通过创建 Physic Material 资源并拖入碰撞器的 Material 槽位生效。

2.5 碰撞事件代码示例

private void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("Player"))
    {
        Debug.Log("被玩家碰撞了!");
    }
}

private void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("Coin"))
    {
        Destroy(other.gameObject);
        // 加分逻辑
    }
}

注意:触发回调函数中的参数是 Collider,物理碰撞回调中是 Collision,后者包含更多信息(如接触点、相对速度)。

三、关节:连接两个物体的物理约束

关节组件可以将两个刚体以特定方式连接,模拟真实世界的机械结构。所有关节都需要至少一方拥有刚体组件。

3.1 常用关节类型速查

关节 功能 经典用例
Fixed Joint 完全固定两个物体,像粘合在一起 拾取物品、碎片粘附
Hinge Joint 绕单一轴旋转(如门铰) 门、钟摆、杠杆
Spring Joint 像弹簧一样弹性连接 弹簧绳、软性连接
Character Joint 为人形角色设计的复杂关节,模拟骨骼约束 布娃娃系统
Configurable Joint 可定制程度最高,自由设置线性与角度限制 高级机械臂、自定义约束

3.2 Hinge Joint 深度解析

铰链关节是最常用的旋转关节,关键属性:

  • Axis:旋转轴(世界或自身坐标)。
  • Use Limits:限制旋转角度,设置 Min/Max。
  • Use Motor:驱动旋转,可设定目标速度与力。
  • Use Spring:弹性恢复到目标角度。
  • Break Force / Break Torque:超过设定阈值关节自动断裂。

示例:制作一扇自动关闭的门

// 挂在有HingeJoint的门上
public class AutoCloseDoor : MonoBehaviour
{
    private HingeJoint hinge;
    void Start() => hinge = GetComponent<HingeJoint>();

    void OnTriggerExit(Collider other)
    {
        if (other.CompareTag("Player"))
        {
            JointMotor motor = hinge.motor;
            motor.targetVelocity = -80; // 反向速度使之关闭
            motor.force = 100;
            hinge.motor = motor;
            hinge.useMotor = true;
        }
    }
}

3.3 Spring Joint 应用

弹簧关节使两物体间保持动态弹性距离。调节 Spring(刚度)和 Damper(阻尼)创建柔韧的绳子或晃动效果。常用于:

  • 悬挂的灯受撞击摇摆
  • 牵引磁铁效果

3.4 关节的 Break Force 陷阱

Break ForceBreak Torque 设为 Infinity 时关节永不破坏。当断裂时,关节组件会被自动移除,并调用 OnJointBreak(float breakForce) 回调。利用此特性可实现:

  • 绳索断裂效果
  • 可破坏的机械结构

提示:多个关节连接形成链时,物理稳定性会下降。尽量避免过长的关节链,必要时使用 Configurable Joint 实现单关节替代多关节。

四、性能优化与最佳实践

物理模拟可能成为性能瓶颈,务必遵守以下原则:

4.1 精简碰撞器数量与复杂度

  • 静态环境尽量使用 Box/Sphere 等原型碰撞器组合,避免使用复杂 Mesh Collider。
  • 对于必须使用 Mesh Collider 的地形,勾选 Convex 限制为凸壳以加速计算(虽然形状会简化)。
  • 为动态对象设置 Collision DetectionContinuous Speculative 而非 Continuous Dynamic,后者开销极大。

4.2 固定时间步长设置

Edit > Project Settings > Time > Fixed Timestep 决定了物理更新频率。默认 0.02 秒(50 Hz)。对于需要高精度物理的游戏(如竞技射击),可适当减小该值,但需注意 CPU 负荷。

4.3 巧用物理层与忽略碰撞

在代码中动态忽略特定物体间的碰撞:

Physics.IgnoreCollision(colliderA, colliderB, true);

或预设层矩阵,避免大量运行时判断。

4.4 休眠与运动学物体的平衡

  • 大量静止刚体应允许它们自然休眠,不要频繁唤醒。
  • 移动平台等反复运动的物体,勾选 Is Kinematic 并由脚本控制,避免每帧物理计算。

4.5 关注 Rigidbody 数量

同场景激活的刚体数尽量控制在数百以内。如果确实需要成千上万个独立物理物体,考虑使用 ECS + Unity Physics 或转为特效动画模拟。

五、常见问题与排错

物体穿透地面/墙壁

  • 确保两个物体都有 Collider(静态物体至少需要 Collider 才能碰撞,可以没有 Rigidbody)。
  • 高速物体:将 Collision Detection 设为 Continuous Dynamic(动态)或 Continuous Speculative(快速动态),并注意刚体的质量比不宜过大。

关节抖动或旋转异常

  • 检查连接的两个物体是否都正确设置了 Rigidbody(非运动学)且质量差不过分悬殊。
  • 适当提高 Solver Iterations(Project Settings > Physics > Default Solver Iterations),增加关节解算精度。

触发事件不触发

  • 确认其中至少一方附有 Rigidbody(通常是移动的一方)。
  • 确认碰撞矩阵中两层允许交互。

六、总结与进阶之路

通过掌握刚体、碰撞器和关节的配合使用,你已能构建出可靠的物理交互。接下来建议深入学习:

  • Rigidbody 的 MovePosition 与插值 实现流畅的玩家移动。
  • 可配置关节 打造自定义绳索、拉链等复杂约束。
  • Physics.Raycast 与物理查询,实现无碰撞的检测。
  • DOTS Physics 获得超高实体数量的物理表现。

物理引擎是世界规则的引擎,合理运用它能以极低的代码量实现令人信服的游戏体验。现在,打开 Unity 开始你的第一个物理实验吧。