핵심 정리
| 항목 | 내용 |
|---|---|
| 역할 | 충돌, 중력, 힘, 속도, 물리 시뮬레이션을 받는 3D 물리 본체 |
| 언제 쓰는가 | 밀기, 떨어지기, 점프, 반동, 물리 기반 캐릭터나 투사체를 다룰 때 |
| 기준 버전 | Unity 6.5 (6000.5) |
| 핵심 Inspector | Mass, Drag, Angular Drag, Use Gravity, Is Kinematic, Interpolate, Collision Detection, Constraints |
| 자주 연결되는 API | velocity, linearVelocity, angularVelocity, AddForce, MovePosition, MoveRotation, Sleep, WakeUp |
Inspector 설정
| 설정값 | 언제 바꾸는가 | 잘못 맞추면 생기는 문제 |
|---|---|---|
| Mass | 밀치기, 충돌 반응, 점프 힘 체감을 맞출 때 | 같은 힘인데 너무 안 움직이거나 지나치게 튐 |
| Drag / Angular Drag | 미끄러짐, 회전 감쇠를 조절할 때 | 감쇠가 부족해 계속 미끄러지거나, 너무 커서 둔해짐 |
| Use Gravity | 공중 플랫폼, 드론, 수영체처럼 중력이 필요 없을 때 | 꺼 둔 줄 모르고 떨어지지 않거나, 켜 둬서 계속 추락 |
| Is Kinematic | 애니메이션/스크립트가 위치를 주도할 때 | AddForce가 안 먹는데 버그로 오해하기 쉬움 |
| Interpolate | 카메라에 잘 보이는 오브젝트 떨림을 줄일 때 | 끄면 시각적으로 끊겨 보이고, 켜도 물리 논리 문제는 해결 안 됨 |
| Collision Detection | 빠른 투사체, 대시, 튕김 공이 벽을 뚫을 때 | Discrete로 두면 통과, Continuous를 남발하면 비용 증가 |
| Constraints | 넘어지면 안 되는 캐릭터, 특정 축만 움직이는 플랫폼일 때 | 축 잠금을 안 해 충돌 시 비틀리거나 뒤집힘 |
Mass, Drag, Angular Drag
Mass는 힘에 대한 반응 크기입니다. 같은 AddForce라도 Mass가 크면 덜 움직입니다. Drag는 선형 속도 감쇠, Angular Drag는 회전 감쇠입니다. "미끄러지는 박스"를 멈추고 싶을 때 Drag를 올리고, 회전이 과하게 돈다면 Angular Drag를 조정합니다.
Mass를 극단적으로 키우거나 작은 값으로 두면 힘 균형이 어색해질 수 있습니다. 물리 퍼즐, 캐릭터 밀치기, 차량처럼 상호작용이 많은 장면에서는 서로 비교되는 Mass 스케일이 더 중요합니다.
Use Gravity, Is Kinematic
Use Gravity는 중력 적용 여부입니다. 공중 드론, 수중 오브젝트, 스크립트 제어 플랫폼은 끄는 경우가 많습니다. Is Kinematic은 물리 힘으로 움직이지 않고 스크립트나 애니메이션이 위치를 주도하게 만듭니다.
Is Kinematic을 켜면 AddForce로는 움직이지 않습니다. 대신 이동 플랫폼, 잡기 상태, 애니메이션이 직접 위치를 정하는 오브젝트에 적합합니다.
Interpolate, Collision Detection
Interpolate는 렌더 프레임 사이를 부드럽게 보간해 움직임 떨림을 줄입니다. 플레이어, 카메라가 자주 보는 중요한 오브젝트에 자주 씁니다.
Collision Detection은 빠른 오브젝트가 Collider를 뚫고 지나가는 문제를 줄이는 옵션입니다. 총알, 빠른 투사체, 빠르게 튕기는 공은 Continuous 계열을 먼저 의심합니다. 대신 비용이 늘어날 수 있습니다.
| 값 | 언제 고르는가 | 주의할 점 |
|---|---|---|
Interpolate = None | 물리 정확도만 중요하고 시각 떨림이 크게 거슬리지 않을 때 | 카메라가 가까이 보면 떨려 보일 수 있음 |
Interpolate = Interpolate | 플레이어, 카메라 추적 대상처럼 부드럽게 보이는 편이 중요할 때 | 렌더링 보간일 뿐 충돌 문제를 해결하지는 않음 |
Interpolate = Extrapolate | 속도 방향이 비교적 일정해서 한 프레임 앞 예측이 자연스러울 때 | 급정지나 충돌 직후에는 오히려 더 어색할 수 있음 |
Collision Detection = Discrete | 일반 박스, 느린 물체, 대부분의 기본 오브젝트 | 빠른 이동체는 벽을 통과할 수 있음 |
Collision Detection = Continuous | 빠르게 움직이지만 주로 정적인 콜라이더와 부딪히는 물체 | 모든 충돌을 해결해 주는 만능값은 아님 |
Collision Detection = Continuous Dynamic | 빠른 리지드바디끼리도 충돌 정확도가 중요할 때 | 비용이 가장 커서 핵심 오브젝트에만 제한적으로 쓰는 편이 안전 |
Collision Detection = Continuous Speculative | 캐릭터 컨트롤러 비슷한 안정감이 필요하거나 회전 포함 충돌을 좀 더 보수적으로 보고 싶을 때 | 과하게 보수적으로 반응해 미세한 걸림이 느껴질 수 있음 |
Constraints
Freeze Position/Rotation은 물리 축을 잠급니다. 2.5D 게임에서 Z 회전 고정, 캐릭터가 넘어지지 않게 X/Z 회전 고정, 엘리베이터에 Y만 허용 같은 경우에 자주 씁니다.
축을 잠그지 않고 스크립트로만 억지 보정하면 충돌 순간 흔들리거나 떨림이 생길 수 있습니다.
스크립트 연결
| 필드/프로퍼티 | 언제 읽거나 쓰는가 | 주의할 점 |
|---|---|---|
position | 물리 기준 현재 위치를 읽을 때 | transform.position과 섞어 읽지 않는 편이 안전 |
linearVelocity / velocity | 현재 이동 속도 확인, 즉시 속도 보정 | 최근 버전 명칭 차이를 프로젝트 API 기준으로 확인 |
angularVelocity | 회전 속도 기반 판정이 필요할 때 | 축 단위 값이 아니라 각속도 벡터 |
isKinematic | 잡기 상태, 컷신, 플랫폼 모드 전환 | 전환 직후 힘 적용 흐름이 바뀜 |
constraints | 축 잠금 상태를 코드에서 바꿔야 할 때 | 기존 비트마스크를 덮어쓰는 실수 주의 |
| 메서드 | 언제 쓰는가 | 연결 지점 |
|---|---|---|
AddForce() | 점프, 반동, 폭발 밀치기 | FixedUpdate, 입력 처리 후 물리 적용 |
MovePosition() | 제어형 이동을 물리와 같이 처리할 때 | FixedUpdate |
MoveRotation() | 물리 본체 회전을 부드럽게 보정할 때 | FixedUpdate |
Sleep() / WakeUp() | 필요할 때만 물리 활성화 | 최적화, 상태 전환 함수 |
AddTorque() | 회전 반동, 구르기, 회전체 제어 | FixedUpdate, 충돌 반응 |
제어형 이동은 MovePosition, 힘 기반 반응은 AddForce, 순간 속도 변경은 velocity 계열을 나눠 쓰는 편이 읽기 쉽습니다.
AddForce의 ForceMode
| 값 | 언제 쓰는가 | 결과 해석 |
|---|---|---|
ForceMode.Force | 지속적으로 미는 힘, 엔진 추력, 바람, 일반 이동 보조 | 질량의 영향을 받고 여러 FixedUpdate에 걸쳐 누적됨 |
ForceMode.Acceleration | 질량과 무관하게 같은 가속도를 주고 싶을 때 | 질량 차이를 무시하므로 무거운 물체도 같은 가속도로 움직임 |
ForceMode.Impulse | 점프, 폭발, 총 반동처럼 한 번에 툭 치는 힘 | 질량의 영향을 받는 순간 힘이라 점프/넉백에 가장 많이 씀 |
ForceMode.VelocityChange | 질량과 무관하게 즉시 속도를 바꾸고 싶을 때 | 반응은 즉각적이지만 물리감이 줄고 과하면 제어가 거칠어짐 |
점프는 보통 Impulse, 제트팩처럼 계속 미는 힘은 Force, 무게가 다른 적을 같은 속도로 밀어야 하는 특수 규칙은 Acceleration이나 VelocityChange를 검토합니다.
using UnityEngine;
public class PhysicsMover : MonoBehaviour
{
[SerializeField] private Rigidbody body;
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private float jumpForce = 7f;
private Vector3 moveInput;
private void Update()
{
moveInput = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")).normalized;
if (Input.GetKeyDown(KeyCode.Space))
{
body.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
}
}
private void FixedUpdate()
{
body.MovePosition(body.position + moveInput * moveSpeed * Time.fixedDeltaTime);
}
}입력은 Update, 물리 적용은 FixedUpdate, 충돌 결과를 읽는 것은 OnCollisionEnter/Stay/Exit가 기본 연결 지점입니다.
자주 틀리는 부분
- Rigidbody가 붙었는데
transform.position으로 이동하면 충돌과 보간이 어긋납니다. Is Kinematic상태에서AddForce가 안 먹는 것을 버그로 오해하기 쉽습니다.- 빠른 투사체가 통과하면
Collision Detection과Fixed Timestep부터 봐야 합니다. - 축 고정 없이 회전 보정을 직접 덮어쓰면 충돌 때 떨림이 생깁니다.
관련 컴포넌트
Transform, Collider, CharacterController vs Rigidbody, Unity Rigidbody 이동 기본, Physics LayerMask와 Collision Matrix
참고 링크
3 sources