핵심 정리
private void FixedUpdate()
{
body.MovePosition(body.position + moveDirection * moveSpeed * Time.fixedDeltaTime);
}구조 이해
Transform 대신 Rigidbody를 써야 하는 이유
Rigidbody가 붙은 오브젝트를 물리적으로 움직일 때는 Transform보다 Rigidbody API를 우선 고려합니다. transform.position을 직접 바꾸면 충돌 시스템을 우회하여 물리 결과가 부자연스러워질 수 있습니다. MovePosition은 물리 시뮬레이션 안에서 이동을 처리하므로 충돌과 반응이 더 자연스럽게 연결됩니다.
Update와 FixedUpdate 역할 분리
입력은 보통 Update에서 읽고, 실제 물리 이동은 FixedUpdate에서 적용하는 흐름이 안정적입니다. FixedUpdate는 프레임 속도와 무관하게 일정한 물리 타임스텝으로 호출되므로, 프레임 속도가 달라져도 이동 결과가 일관성을 유지합니다. 입력 방향은 Update에서 필드에 저장해 두고, FixedUpdate에서 그 값을 읽어 이동을 적용하는 패턴을 씁니다.
[SerializeField] private float moveSpeed = 5f;
private Rigidbody body;
private Vector3 moveDirection;
private void Awake() => body = GetComponent<Rigidbody>();
private void Update()
{
moveDirection = new Vector3(Input.GetAxisRaw("Horizontal"), 0f, Input.GetAxisRaw("Vertical")).normalized;
}
private void FixedUpdate()
{
body.MovePosition(body.position + moveDirection * moveSpeed * Time.fixedDeltaTime);
}MovePosition과 AddForce 선택 기준
MovePosition은 충돌 시스템과 더 잘 어울리고, 순간이동은 position 직접 설정과 성격이 다릅니다. 점프나 반동처럼 힘 기반 표현이 필요하면 AddForce를 함께 이해해야 합니다. 캐릭터를 "제어하며 움직이는" 느낌이면 MovePosition, "물리 힘을 받아 자연스럽게 반응하는" 느낌이면 AddForce가 더 적합한 경우가 많습니다.
체크포인트
| 상황 | 적합한 선택 |
|---|---|
| 물리 충돌을 유지하며 제어 이동 | MovePosition (FixedUpdate 안에서) |
| 점프·반동 등 힘 기반 표현 | AddForce |
| 물리와 무관한 단순 배치·순간이동 | transform.position 직접 설정 |
| 입력 읽기 | Update (프레임 단위) |
| 물리 적용 | FixedUpdate (고정 타임스텝) |
| 비교 | 더 잘 맞는 쪽 | 이유 |
|---|---|---|
| 제어형 이동 vs 힘 기반 이동 | MovePosition / AddForce | 조작감 우선인지 물리 반응 우선인지 다름 |
| 연속 이동 vs 순간 위치 스냅 | MovePosition / position 직접 설정 | 텔레포트 성격이면 직접 위치 변경이 낫다 |
| 이동 처리 vs 회전 처리 | 둘 다 Rigidbody API 우선 | transform와 섞으면 물리 상태가 어긋나기 쉬움 |
주의할 점
Rigidbody가 붙은 오브젝트를 transform.position으로 직접 옮기면 물리 시뮬레이션이 어긋납니다.
// ❌ Rigidbody 있는 오브젝트를 transform으로 이동
// 충돌 통과, 물리 튕김 등 부자연스러운 결과
private void Update()
{
transform.position += moveDir * speed * Time.deltaTime;
}
// ✅ MovePosition으로 물리 친화적 이동
private Rigidbody body;
private Vector3 moveDir;
private void Update()
{
moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0f,
Input.GetAxisRaw("Vertical")).normalized;
}
private void FixedUpdate()
{
body.MovePosition(body.position + moveDir * speed * Time.fixedDeltaTime);
}
// ❌ 같은 프레임에 transform과 Rigidbody를 섞음
private void Update()
{
transform.position += moveDir * speed * Time.deltaTime;
}
private void FixedUpdate()
{
body.AddForce(Vector3.forward);
}
// → 충돌, 보간, 속도 계산이 흔들림참고 링크
2 sources