Unity Term Book
物理

Rigidbody

Rigidbody 把 GameObject 交给 Unity Physics 引擎——重力、力、速度和碰撞由物理系统计算,而不是在 Update 里手写。配合 Collider 驱动刚体玩法;移动时应走物理 API。理解 Kinematic 模式与插值设置,能帮程序做出稳定手感的角色与可互动物品。

想象一下...

Rigidbody 就像物体的物理灵魂。加上它之前,一个箱子只是悬在空中的静图。挂上 Rigidbody 后,它才变成有真实质量的刚体——受重力下坠、碰撞后弹开、受力后滑动。你用 `AddForce()` 像用手推它,而不是直接写 `transform.position`。

概念详解

Rigidbody 会把 GameObject 注册进 Unity Physics。 主要属性:mass(千克)、drag(空气阻力)、 angularDrag(旋转阻力)、useGravityisKinematic

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

mass1.0 kg
drag0.0
angularDrag0.05
useGravitytrue
isKinematicfalse

Constraints (Freeze)

☑ Freeze Pos X☑ Freeze Rot Z□ Freeze Pos Y□ Freeze Rot X

动手步骤

1

添加 Rigidbody 组件

Inspector → Add Component → Physics → Rigidbody。若需要碰撞,再挂一个 Collider。

2

在 Awake 中缓存 Rigidbody

_rb = GetComponent<Rigidbody>() —— 然后在 FixedUpdate 里使用。

3

在 FixedUpdate 里用力移动

不要写 transform.position。使用 AddForce() 或设置 velocity

4

2D 俯视角冻结旋转

Inspector → Constraints → Freeze Rotation X, Y, Z,避免撞击后翻滚。

5

移动平台用 isKinematic

由动画驱动的平台 → isKinematic = true + MovePosition()

交互模拟器

点击画布生成物体。调整 Gravity、Mass、Drag,再按 Force Up 施加冲量。

Objects: 0|Gravity: 9.8 m/s²|点击画布生成 Rigidbody

代码示例

基础

用 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