Unity Term Book
Physics

Rigidbody

Rigidbody trao GameObject cho physics engine — trọng lực, lực tác dụng, vận tốc và va chạm đều do Unity Physics tính toán, không phải vòng Update của bạn.

Hãy tưởng tượng...

Rigidbody giống như linh hồn vật lý của đồ vật. Trước khi có Rigidbody, một cái hộp chỉ là hình ảnh đứng yên trong không trung. Sau khi thêm Rigidbody, nó trở thành vật thể có khối lượng thực — bị hút xuống bởi trọng lực, bật lại khi va chạm, trượt khi có lực. Bạn tương tác với nó qua `AddForce()` như tay đẩy, không phải chỉnh `transform.position` trực tiếp.

Khái niệm chi tiết

Rigidbody đăng ký GameObject với Unity Physics Engine. Các thuộc tính chính: mass (kg), drag (cản không khí), angularDrag (cản xoay), useGravity, isKinematic.

ForceMode: Force (liên tục, tính mass), Acceleration (liên tục, bỏ qua mass), Impulse (tức thời, tính mass — dùng cho jump), VelocityChange (tức thời, bỏ qua mass).

Kinematic Rigidbody: isKinematic = true — vẫn tham gia collision detection nhưng không bị lực/trọng lực tác động. Di chuyển qua MovePosition(). Dùng cho moving platforms, animated objects.

Lưu ý quan trọng: Không gọi transform.position trực tiếp trên Rigidbody non-kinematic — sẽ teleport và phá vỡ physics simulation. Luôn dùng AddForce() hoặc velocity.

Sơ đồ: Forces & ForceMode

ForceMode Types

Force

Liên tục, tính mass. Dùng cho rocket engine, wind...

rb.AddForce(dir * 10f)

Impulse

Tức thời, tính mass. Dùng cho jump, explosion knockback

rb.AddForce(Vector3.up * 5f, ForceMode.Impulse)

VelocityChange

Tức thời, bỏ qua mass. Đặt velocity trực tiếp

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

Hướng dẫn thực hành

1

Thêm Rigidbody Component

Inspector → Add Component → Physics → Rigidbody. Cũng cần thêm Collider để có va chạm.

2

Cache Rigidbody trong Awake

_rb = GetComponent<Rigidbody>() — dùng trong FixedUpdate.

3

Di chuyển qua forces trong FixedUpdate

Không dùng transform.position. Dùng AddForce() hoặc set velocity.

4

Freeze Rotation cho 2D top-down

Inspector → Constraints → Freeze Rotation X, Y, Z để tránh object xoay khi va chạm.

5

Dùng isKinematic cho Moving Platforms

Platform di chuyển theo animation → isKinematic = true + MovePosition().

Trình mô phỏng tương tác

Click canvas để spawn object. Điều chỉnh Gravity, Mass, Drag và xem vật lý thay đổi. Nhấn Force Up để thêm lực.

Objects: 0|Gravity: 9.8 m/s²|Click canvas để spawn Rigidbody

Ví dụ Code

Cơ bản

Di chuyển và jump với 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()
  {
      // Giới hạn tốc độ theo mặt phẳng ngang
      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;
}

Ví dụ Code

Nâng cao

Explosion force với AddExplosionForce — ném vật thể theo hướng tâm vụ nổ.

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()
  {
      // Tìm tất cả Collider trong bán kính
      Collider[] cols = Physics.OverlapSphere(transform.position, radius);

      foreach (var col in cols)
      {
          var rb = col.GetComponent<Rigidbody>();
          if (rb == null) continue;

          // Unity tự tính lực theo khoảng cách
          rb.AddExplosionForce(force, transform.position, radius, upModifier);
      }

      // Visual effect + destroy
      GetComponent<ParticleSystem>()?.Play();
      Destroy(gameObject, 2f);
  }
}

📌 Ghi nhớ nhanh

  • Forces → FixedUpdate; Input → Update
  • Jump: AddForce(up, ForceMode.Impulse)
  • Không gọi transform.position trên non-kinematic RB
  • Moving platform → isKinematic + MovePosition

⚠️ Lỗi thường gặp

  • ❌ transform.position trực tiếp trên Rigidbody

    Teleport — phá vỡ physics, xuyên tường, glitch collision

    ✅ rb.MovePosition() hoặc velocity

  • ❌ Physics code trong Update thay vì FixedUpdate

    Không đồng bộ với physics timestep → jitter, tunneling

    ✅ Mọi AddForce/velocity → FixedUpdate