How to Develop a Game
Rigidbody
PublishDate: 2025-06-01 | CreateDate: 2025-06-01 | LastModify: 2025-06-01 | Creator:ljf12825

在Unity中,Rigidbody是一个用于实现物理行为的组件,它允许你的游戏对象受力、重力、碰撞等真实世界的物理规则影响

Rigidbody的基本功能

当你给一个GameObject添加Rigibody后,它具备以下能力:

功能描述
重力会受到 Unity 世界的重力影响。
力作用可通过 AddForce() 施加力。
碰撞可与带有 Collider 的物体发生物理碰撞。
移动可通过物理方式(而不是直接修改 transform)移动。

RigidbodyPanel

RigidbodyPanel

基础物理参数

参数名作用默认值建议用法
Mass(质量)控制惯性、碰撞反应1设为真实世界比例(如车 1000、人 70)
Drag(线性阻力)模拟空气/水的阻力(减速)0移动物体逐渐停止,可设为 1~5
Angular Drag(角阻力)减缓旋转速度0.05防止物体无限旋转,常设为 0.1~0.5

手动设置质心

rb.centerOfMass = new Vector3(0, -1f, 0); //手动设一个偏移量

设置后将覆盖自动计算值,适用于如车辆、飞船平衡优化、ragdoll调整等高级用途

可视化质心方法:

void OnDrawGizmo()
{
    if (rb != null)
    {
        Gizmos.color = Color.red;
        Gizmos.DrawSphere(rb.worldCenterOfMess, 0.1f);
    }
}

为什么质心重要

应用场景影响
飞船 / 载具若质心偏上,容易翻车或晃动
摆锤 / 吊挂物体旋转效果中心点取决于质心
多 Collider 组合物体自动质心可能不在视觉中心
被力击打(AddForce)力不作用在质心会引起旋转(力矩)

Automatic Tensor(自动惯性张量,默认为true)

什么是Tensor

默认自动计算惯性张量

手动设置惯性张量(自动覆盖)

rb.inertiaTensor = new Vector3(1, 1, 1); //自定义旋转惯性
rb.inertiaTensorRotation = Quaternion.identity; //张量方向

但这样做有前提条件:

rb.ResetInertiaTensor(); //可重置为自动计算值

设置之前你要禁用自动张量

什么情况需要自定义惯性张量

应用目的
物理模拟器 / 实验工具精确控制旋转行为
异形刚体(如飞船、复杂机器人)人为调整旋转惯性,防止旋转太快或不稳定
某些游戏设计让角色或物体转得更“重”或更“灵活”
制作旋转玩具 / 陀螺仪可控惯性带来物理可玩性

运动状态设置

参数作用默认使用场景
Use Gravity是否受重力影响true用于自由下落、角色跳跃等
Is Kinematic是否由代码控制,不参与物理false静态平台、动画控制角色等

Interpolate(插值)

选项说明使用场景
None不插值,可能抖动一般默认
Interpolate使用上一帧数据进行平滑摄像机跟随刚体时防抖动
Extrapolate使用下一帧数据预测位置一般不推荐,容易导致位置错误

插值仅影响视觉表现,不影响物理逻辑,适合处理低帧率时的视觉平滑

Collision Detection(碰撞检测模式)

模式描述使用场景
Discrete默认,普通对象慢速运动、低精度要求
Continuous防穿透快速移动物体(如子弹)
Continuous Dynamic防止快速刚体穿过静态物体用于导弹、飞行物
Continuous Speculative预测未来路径是否碰撞用于需要超高稳定性的对象

连续检测会增加计算量,不建议用于大量物体

Constraints(冻结轴向) 用于锁定物体的移动或旋转,防止不受控的漂移或翻滚

选项说明常用组合
Freeze Position X/Y/Z锁定对应轴上的移动冻住平台等静态物体
Freeze Rotation X/Y/Z锁定对应轴上的旋转防止角色倒地、车轮翻转
Freeze All锁定所有轴彻底不动,用于静态物体

Layer Overrides(图层覆盖)
允许刚体在物理世界中临时使用不同的Layer设置进行碰撞和检测计算,不会影响物体本身的Layer
影响范围:物理模拟(碰撞、Raycast、Force、Overlap等),不会影响渲染、标签识别、脚本逻辑

Exclude Layers优先于Include Layers

Rigidbody常见用法:

Rigidbody rb = GetComponent<Rigidbody>();

rb.AddForce(Vector3.forward * 10f); //施加一个向前的力
rb.AddTorque(Vector3.up * 5f); //添加一个旋转力
rb.MovePosition(newPos); //平滑低移动Rigidbody
rb.velocity = new Vector3(5, 0, 0); //设置线速度

isKinematic 和 非 Kinematic

用途:

Rigidbody vs Transform控制

不要在有Rigidbody的物体上直接用transform.position += ...来移动,这会跳过物理系统,导致碰撞问题

正确做法:

问题本质: 在Unity中,Rigidbody是由物理系统控制的,一旦你给GameObject添加了Rigidbody,它的位置和旋转应该只通过物理系统来控制。

使用transform.position += ...会出现的问题

问题说明
绕过物理引擎transform.position += ...立即改变 Transform 的位置,Unity 物理系统(PhysX)对此毫不知情
不会产生碰撞检测物体“穿越”其他碰撞体而不产生物理响应(穿模)
不会产生力或速度变化Rigidbody.velocity 不会更新,你也不能检测运动趋势
打乱内部物理状态会破坏 Rigidbody 的睡眠状态、插值、运动预测等机制,造成 jitter(抖动)或奇怪弹跳
失去重力/摩擦等作用物体移动但没有物理感,导致操作不自然

只有在以下三种情况中可以使用transform.position:
1.没有Rigidbody的对象(纯UI/特效/场景物体)

2.临时调整位置,如传送、重置

3.isKinematic = true

示例:角色控制器使用Rigidbody

public class PlayerMovement : MonoBehaviour
{
    public float speed = 5f;
    private Rigidbody rb;

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

    void FixedUpdate()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");

        Vector3 move = new Vector3(h, 0, v);
        rb.MovePosition(rb.position + move * speed * Time.fixedDeltaTime);
    }
}

物理力应用的类型

Unity提供了多种物理力应用方式,你可以根据物理效果需求选择合适的模式

rb.AddForce(Vector3.force, ForceMode.Force);
ForceMode作用适用场景
Force持续施加力(受质量影响)模拟发动机、风力等持续力
Impulse瞬时冲量(受质量影响)子弹击中、跳跃、爆炸推动
VelocityChange改变速度(忽略质量)快速位移、瞬间反弹
Acceleration施加加速度(不受质量影响)飞行器推进、不考虑质量时

爆炸力:AddExplosionForce

模拟爆炸冲击力,自动考虑距离衰减和力方向

rb.AddExplosionForce(force, explosionPosition, radius, upwardsModifier);

Rigidbody Constraints(锁定轴向)

锁定位置或旋转,常用于平台类游戏角色防止翻滚

rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;

Rigidbody Interpolation(插值)

用于缓解物体抖动或物理更新频率和渲染帧率不一致的问题
插值实在渲染帧之间平滑显示刚体位置或旋转,防止因物理更新滞后造成的抖动或卡顿

渲染帧和物理帧 在Unity游戏循环中,渲染帧(Update)和物理帧(Fixed Update)是分开的 渲染帧率和物理帧率可能不同,这样一来,在两次物理更新之间可能要渲染一次或多次画面,此时刚体的位置还没更新,就会导致物体“跳跃”,摄像机跟随刚体时抖动

rb.interpolation = RigidbodyInterpolation.Interpolate;
插值类型描述
None不插值,最性能优先
Interpolate插值上一次位置
Extrapolate预测下一帧位置

适用于:摄像机跟随物体 + Rigidbody,平滑动画等

插值不是同步手段
插值只影响视觉显示,不影响实际物理行为或碰撞检测

Rigidbody连接(Joint系统)

Unity提供了多个Joint来连接两个Rigidbody,来实现机械、吊挂、弹簧等效果

常用Joint类型

Joint 类型功能应用
FixedJoint完全绑定两个刚体构建刚性结构
HingeJoint像门铰链一样旋转车轮、门
SpringJoint模拟弹簧连接弹簧、绳索末端
ConfigurableJoint自定义约束自由度高级物理装置
CharacterJoint模拟人体骨骼人物 ragdoll

示例:固定一个物体

var joint = gameObject.AddComponent<FixedJoint>();
joint.connectedBody = otherRigidbody;

刚体时间管理

你可以临时控制刚体行为。例如冻结、暂停、缓动

rb.isKinematic = true; // 暂停物理影响
rb.detectCollisions = false; //禁用碰撞响应
rb.Sleep(); //进入“休眠”状态,除非外力唤醒
rb.WakeUp(); //强制唤醒

手动模拟物理(少见但强大)

Unity默认每帧自动调用Physics.Simulate(),你可以关闭自动模拟并手动调用它

Physics.autoSimulation = false;
Physics.Simulate(Time.fixedDeltaTime);

用于录制、回放、预测系统、AI训练等

实践建议

1.性能优化

2.碰撞过滤

3.组合Joint

4.多刚体组合

刚体不能直接禁用

1.刚体不是一个标准行为组件

2.Rigidbody是物理系统的一部分,关闭它的逻辑很复杂

Unity的Rigidbody是底层物理引擎(NVIDIA PhysX)注册的一个刚体对象,它包含大量复杂的状态(如质量、速度、力、碰撞状态等),不能简单“关掉”

如果允许直接enabled = false,Unity就得把它从物理世界中注销,可能会导致:

替代方法:

方法效果场景
rb.isKinematic = true不再受物理引擎驱动暂停物理交互,但可以通过 transform 控制
rb.detectCollisions = false不再检测碰撞让它“穿透”其他物体
rb.Sleep()让刚体进入休眠减少物理计算开销
Destroy(rb)彻底移除刚体完全不再参与物理

Rigidbody API

常用字段/属性

属性类型说明
massfloat质量(默认 1)
dragfloat线性阻力
angularDragfloat角阻力
useGravitybool是否启用重力
isKinematicbool是否受物理引擎影响
velocityVector3当前线速度
angularVelocityVector3当前角速度
positionVector3世界空间位置
rotationQuaternion世界旋转
centerOfMassVector3质心位置
inertiaTensorVector3惯性张量
constraintsRigidbodyConstraints锁定移动或旋转轴
interpolationRigidbodyInterpolation插值方式
collisionDetectionModeCollisionDetectionMode碰撞检测模式

常用方法(控制移动、施加力)

施加力的方法(力学模拟)

方法描述常用参数说明
AddForce(Vector3 force, ForceMode mode = ForceMode.Force)向刚体施加一个世界空间的力- ForceMode 可选:Force, Impulse, Acceleration, VelocityChange
AddRelativeForce(Vector3 force, ForceMode mode = ForceMode.Force)向刚体施加一个相对于自身方向的力用于局部方向推进,如飞船、角色局部移动
AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force)添加一个旋转力(转矩)控制刚体的旋转,比如陀螺仪效果
AddRelativeTorque(Vector3 torque, ForceMode mode = ForceMode.Force)添加一个相对坐标的转矩以自身坐标轴方向旋转
AddExplosionForce(float force, Vector3 position, float radius, float upwardsModifier = 0.0f, ForceMode mode = ForceMode.Force)模拟爆炸力常用于爆炸、炸飞物体等效果

移动与旋转(物理友好方式)

这些方法在FixedUpdate()中调用,以物理方式平滑移动对象

方法描述
MovePosition(Vector3 position)让刚体以物理方式移动到某位置(会产生碰撞)
MoveRotation(Quaternion rot)让刚体以物理方式旋转到目标旋转角度

不要使用transform.position = … 替代移动刚体,会破坏物理系统

状态控制

方法描述
Sleep()让刚体休眠(不再进行物理更新,除非唤醒)
WakeUp()唤醒休眠的刚体
IsSleeping()检查当前是否处于休眠状态

速度与点速度获取

方法描述
GetPointVelocity(Vector3 worldPoint)获取世界空间中某一点的实际速度
GetRelativePointVelocity(Vector3 relativePoint)获取某个相对位置的速度(少用)

状态检测与设置

方法 / 属性类型说明
IsSleeping()bool当前是否休眠
detectCollisionsbool是否响应碰撞
maxDepenetrationVelocityfloat最大穿透修正速度(用于防止卡住)
solverIterationsint物理求解器迭代次数(越高越精准)
sleepThresholdfloat控制何时休眠

高级设置

属性 / 方法说明
inertiaTensorRotation惯性张量旋转
maxAngularVelocity最大角速度
centerOfMass自定义质心位置
ResetCenterOfMass()重置为默认质心
ResetInertiaTensor()重置惯性张量

与Collider配合相关

Rigidbody本身不处理碰撞细节,但需配合Collider组件才能参与物理交互

方法说明
ClosestPointOnBounds(Vector3 position)获取边界上最接近某点的位置
SweepTest(Vector3 direction, out RaycastHit hit, float maxDistance)模拟刚体沿方向运动是否会撞到东西
SweepTestAll(...)返回所有碰撞信息
GetRelativePointVelocity(Vector3 relativePoint)获取某点相对速度
GetPointVelocity(Vector3 worldPoint)获取世界空间下某点速度

Unity官方文档(Rigidbody)