Unity Term Book
물리

Rigidbody

Rigidbody는 GameObject를 Unity Physics에 맡깁니다. 중력·힘·속도·충돌을 Update가 아니라 물리 엔진이 계산합니다. AddForce나 velocity로 움직이고 Kinematic과 보간을 이해하면 캐릭터와 이동 플랫폼의 손맛이 안정됩니다.

상상해 보세요...

Rigidbody는 물체의 물리 영혼과 같습니다. 추가하기 전 상자는 공중에 걸린 정지 이미지일 뿐입니다. Rigidbody를 붙이면 실제 질량을 가진 몸이 되어 중력에 떨어지고, 충돌에 튕기고, 힘에 미끄러집니다. `transform.position`을 직접 쓰지 말고 `AddForce()`로 손으로 밀듯 움직입니다.

개념 자세히

Rigidbody는 GameObject를 Unity Physics에 등록합니다. 주요 속성: mass(kg), drag(공기 저항), angularDrag(회전 저항), useGravity, isKinematic.

ForceMode: Force(연속, 질량 반영), Acceleration(연속, 질량 무시), Impulse(순간, 질량 반영 — 점프에 흔함), VelocityChange(순간, 질량 무시).

Kinematic Rigidbody: isKinematic = true — 충돌 감지에는 참여하지만 힘·중력에는 끌려가지 않습니다. MovePosition()으로 움직입니다. 이동 플랫폼·애니메이션 오브젝트에 씁니다.

핵심 규칙: non-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 탑다운이면 Freeze Rotation

Inspector → Constraints → Freeze Rotation X, Y, Z로 충돌 시 넘어지지 않게 합니다.

5

이동 플랫폼은 isKinematic

애니메이션으로 움직이는 플랫폼 → isKinematic = true + MovePosition().

인터랙티브 시뮬레이터

캔버스를 클릭해 오브젝트를 생성하세요. Gravity·Mass·Drag를 조절한 뒤 Force Up으로 Impulse를 가해 보세요.

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; Input → Update
  • ▸점프: AddForce(up, ForceMode.Impulse)
  • ▸non-kinematic RB에 transform.position 금지
  • ▸이동 플랫폼 → isKinematic + MovePosition

⚠️ 흔한 실수

  • ❌ Rigidbody에 transform.position 직접 대입

    순간이동 — 물리 깨짐, 벽 관통, 충돌 글리치

    ✅ rb.MovePosition() 또는 velocity

  • ❌ 물리 코드를 Update에 두고 FixedUpdate를 안 씀

    물리 timestep과 어긋남 → 떨림, 터널링

    ✅ 모든 AddForce/velocity 호출 → FixedUpdate