Rigidbody
Rigidbody 把 GameObject 交给 Unity Physics 引擎——重力、力、速度和碰撞由物理系统计算,而不是在 Update 里手写。配合 Collider 驱动刚体玩法;移动时应走物理 API。理解 Kinematic 模式与插值设置,能帮程序做出稳定手感的角色与可互动物品。
想象一下...
Rigidbody 就像物体的物理灵魂。加上它之前,一个箱子只是悬在空中的静图。挂上 Rigidbody 后,它才变成有真实质量的刚体——受重力下坠、碰撞后弹开、受力后滑动。你用 `AddForce()` 像用手推它,而不是直接写 `transform.position`。
概念详解
Rigidbody 会把 GameObject 注册进 Unity Physics。
主要属性:mass(千克)、drag(空气阻力)、
angularDrag(旋转阻力)、useGravity、
isKinematic。
ForceMode: Force(持续、考虑质量)、
Acceleration(持续、忽略质量)、Impulse(瞬时、考虑质量——
跳跃常用)、VelocityChange(瞬时、忽略质量)。
Kinematic Rigidbody:
isKinematic = true——仍参与碰撞检测,但不受力或重力驱动。用
MovePosition() 移动。适合移动平台和动画驱动的物体。
关键规则:永远不要在非 kinematic 的 Rigidbody 上直接设
transform.position——那等于瞬移,会破坏模拟。请始终使用
AddForce() 或 velocity。
示意图:力与 ForceMode
ForceMode Types
Force
持续作用,计入质量。用于火箭、风力…
rb.AddForce(dir * 10f)Impulse
瞬时作用,计入质量。用于跳跃、爆炸击退
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse)VelocityChange
瞬时作用,忽略质量。直接设置速度
rb.AddForce(dir, ForceMode.VelocityChange)Rigidbody Properties
Constraints (Freeze)
动手步骤
添加 Rigidbody 组件
Inspector → Add Component → Physics → Rigidbody。若需要碰撞,再挂一个 Collider。
在 Awake 中缓存 Rigidbody
_rb = GetComponent<Rigidbody>() —— 然后在 FixedUpdate 里使用。
在 FixedUpdate 里用力移动
不要写 transform.position。使用 AddForce() 或设置 velocity。
2D 俯视角冻结旋转
Inspector → Constraints → Freeze Rotation X, Y, Z,避免撞击后翻滚。
移动平台用 isKinematic
由动画驱动的平台 → isKinematic = true + MovePosition()。
交互模拟器
点击画布生成物体。调整 Gravity、Mass、Drag,再按 Force Up 施加冲量。
代码示例
基础用 Rigidbody 移动和跳跃。
using UnityEngine;
public class PhysicsPlayer : MonoBehaviour
{
[SerializeField] private float moveForce = 10f;
[SerializeField] private float jumpForce = 7f;
[SerializeField] private float maxSpeed = 8f;
private Rigidbody _rb;
private Vector3 _input;
private bool _grounded;
void Awake() => _rb = GetComponent<Rigidbody>();
void Update()
{
_input = new Vector3(Input.GetAxisRaw("Horizontal"), 0,
Input.GetAxisRaw("Vertical"));
if (Input.GetButtonDown("Jump") && _grounded)
_rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
void FixedUpdate()
{
// Cap speed on the horizontal plane
Vector3 flatVel = new Vector3(_rb.velocity.x, 0f, _rb.velocity.z);
if (flatVel.magnitude > maxSpeed)
_rb.velocity = flatVel.normalized * maxSpeed + Vector3.up * _rb.velocity.y;
_rb.AddForce(_input.normalized * moveForce, ForceMode.Force);
}
private void OnCollisionEnter(Collision col)
=> _grounded = col.gameObject.CompareTag("Ground");
private void OnCollisionExit(Collision col)
=> _grounded = false;
}代码示例
进阶用 AddExplosionForce 施加爆炸力——把刚体从爆炸中心推开。
using UnityEngine;
public class Explosion : MonoBehaviour
{
[SerializeField] private float force = 500f;
[SerializeField] private float radius = 5f;
[SerializeField] private float upModifier = 0.5f;
public void Explode()
{
// Find every Collider inside the radius
Collider[] cols = Physics.OverlapSphere(transform.position, radius);
foreach (var col in cols)
{
var rb = col.GetComponent<Rigidbody>();
if (rb == null) continue;
// Unity scales the force by distance
rb.AddExplosionForce(force, transform.position, radius, upModifier);
}
// Visual effect + destroy
GetComponent<ParticleSystem>()?.Play();
Destroy(gameObject, 2f);
}
}📌 快速记忆
- ▸力 → FixedUpdate;输入 → Update
- ▸跳跃:
AddForce(up, ForceMode.Impulse) - ▸不要在非 kinematic 的 RB 上设
transform.position - ▸移动平台 → isKinematic + MovePosition
⚠️ 常见错误
❌ 在 Rigidbody 上直接写 transform.position
瞬移——破坏物理、穿墙、碰撞异常
✅ 用 rb.MovePosition() 或 velocity
❌ 在 Update 而不是 FixedUpdate 里写物理
与物理步长不同步 → 抖动、穿模
✅ 每次 AddForce/velocity 都放到 FixedUpdate