I'm FanJae.

[20260522] Unity 정리 ( Unity 물리 엔진 기초 - Rigidbody ) 본문

Unity/Unity 초격차캠프

[20260522] Unity 정리 ( Unity 물리 엔진 기초 - Rigidbody )

FanJae 2026. 5. 22. 22:56

1. Rigidbody

- Rigidbody는 Unity 물리 엔진을 이용해 오브젝트에 물리적인 특성을 부여하는 Component다.

- Rigidbody를 사용하면 오브젝트가 여러 물리 요소의 영항을 받을 수 있다.

- 중력, 충돌, 힘, 속도, 마찰, 감쇠 등등..

- Unity의 기본 3D 물리 엔진은 Nvidia PhysX를 사용하고 있다.


2. Rigidbody의 주요 속성

- Collision Detect은 더 정밀한 옵션을 사용할수록 연산 비용이 증가하기 때문에 상황에 맞게 적당히 선택해서 써야한다.


3. Rigidbody 이동 방식

3-1. Transform.Translate (권장하지 않음)

transform.Translate(Vecotr3.forward * moveSpeed * Time.deltaTime);

- Transform.Translate() 는 Transform의 위치를 직접 변경한다.

 

① 특징
- 물리 엔진을 거치지 않음
- 충돌 처리가 부자연스러울 수 있다.
- Rigidbody가 있는 오브젝트에서는 사용을 지양해야 한다.

② 이유
- transform.Translate()는 오브젝트의 위치를 즉시 변경하는 방식이다. 프레임 단위 순간이동의 느낌으로 이해해야 한다. 따라서 이동 경로상의 충돌을 연속으로 검사하며 막는 방식이 아니다.


3-2. AddForce

rb.AddForce(moveDir * force);

AddForce() 는 Rigidbody에 힘을 가하는 방식이다.

 

① 특징
- 질량, 마찰, 중력 등의 영향을 받는다.
- 점진적인 가속과 감속이 발생한다.
- 점프, 넉백, 폭발, 밀림 등에 적합하다.
- 정확한 캐릭터 이동에는 부자연스러울 수 있다.

 

② 적당한 사용처
- 물리적으로 밀려야 하는 오브젝트, 가속/감속이 자연스럽게 느껴져야 하는 이동한다.

 

③ 부적합한 사용처
- 정확한 위치 제어가 필요한 캐릭터 이동, 즉시 멈추거나 즉시 방향 전환해야 하는 이동
- 격자 이동, 일정한 속도로 딱 맞게 움직여야 하는 오브젝트
※ AddForce()는 호출 즉시 위치가 바뀌지 않고, 물리 엔진의 계산 단계에서 힘이 반영된다. 하지만, 이는 ForceMode에 따라 질량의 영향을 받을 수도 있고, 순간적인 힘처럼 적용할 수도 있다.


3-3. linearVelocity

float currentYVelocity = rb.linearVelocity.y;

Vector3 velocity = new Vector3(moveDir.x * moveSpeed, currentYVelocity, moveDir.z * moveSpeed

rb.linearVelocity = velocity;

- linearVelocity는 Rigidbody의 속도를 직접 지정하는 방식이다.


① 특징
- 속도를 직접 제어할 수 있음
- 이동 속도가 명확함
- Y축 속도를 덮어쓰면 중력이나 점프가 깨질 수 있음
- 일반적으로 X, Z축만 수정하고 Y축은 기존 값을 유지함


② 적당한 사용처
- 일정한 속도로 움직이는 캐릭터
- 수평 이동 속도의 제어가 필요한 경우
- 점프 중에도 이동 속도만 바꾸고 싶을 때(X축, Z축에 대한)
- 투사체처럼 속도를 명확히 지정해야 하는 경우

 

③ 부적합한 사용처
- 관성, 가속, 감속을 자연스럽게 살리고 싶은 이동
- 외부 힘의 영향을 자연스럽게 누적해야 하는 상황
- Y축 속도를 직접 덮어써야 하는 구조

 

※ linearVelocity는 Rigidbody가 현재 어느 방향으로 얼마나 빠르게 움직이고 있는지를 나태낸다. 

※ 값을 대입하면 기존 속도가 덮어써지기 때문에, 점프나 중력에 영향을 받는 Y축 속도는 기존 값을 유지하는 것이 안전하다.


3-4. MovePosition

Vector3 nextPos = rb.position + moveDir * moveSpeed *Time.fixedDeltaTime;
rb.MovePosition(nextPos);


- MovePosition()은 Rigidbody의 다음 위치를 지정하는 방식이다.


① 특징
- 물리 엔진 흐름 안에서 위치를 이동한다.
- Transform 직접 이동보다 안정적이다.
- Rigidbody 기반 이동에 적합하다.

 

② 적당한 사용처
- Rigidbody 기반 캐릭터 이동
- 키 입력에 따라 일정한 속도로 이동하는 오브젝트
- Transform 직접 이동보다 안정적인 물리 이동이 필요할 때
- Kinematic Rigidbody를 스크립트로 움직일 때

 

③ 부적합한 사용처
- 힘, 질량, 관성 중심의 자연스러운 물리 이동
- 밀림, 튕김, 폭발 같은 반응을 중심으로 하는 오브젝트
- 매우 빠르게 움직이는 투사체
※ MovePosition()은 Rigidbody를 지정한 위치로 이동시키는 메서드다.


4. Update와 FixedUpdate

4-1. Update

void Update()
{
	float horizontal = Input.GetAxisRaw("Horizontal");
	float vertical = Input.GetAxisRaw("Vertical");

	moveDir = new Vector3(horizontal,0.0f,vertical);
}

- Update()는 매 프레임 호출된다.

 

① 주요 사용처

- 키보드 입력

- 마우스 입력

- 화면 갱신 관련 로직

- 입력은 프레임 단위로 확인하는 것이 자연스럽기 때문에 Update() 에서 처리한다.

4-2. FixedUpdate

- FixedUpdate()는 일정한 물리 주기로 호출된다.

 

① 주요 사용처

- Rigidbody 이동

- AddForce

- MovePosition

- 물리 계산 관련 로직

- Rigidbody처럼 물리 엔진과 관련된 처리는 FixedUpdate()에서 처리하는 것이 일반적이다.


5. GetComponent를 이용한 Rigidbody 가져오기

- GetComponent()는 현재 게임 오브젝트에 붙어있는 컴포넌트를 가져오는 함수다.

- Rigidbody를 매번 찾지 않도록 Start()나 Awake()에서 한 번만 가져와 변수에 저장한다.

① Update()에서 사용 주의

void Update()
{
    rb = GetComponent<Rigidbody>();
}

- Update()와 같은 곳에 GetComponent<> 같은 것은 붙이면 안된다.

- 보통 한 번만 가져와서 재사용하는게 나으며, 불필요한 검색이 반복될 뿐만 아니라, 프레임 단위로 컴포넌트 검색에 대한 비용이 발생할 수 있다.


6. 터널링 현상

- 오브젝트가 빠르게 이동하면 이전 위치에서 다음 위치로 순간 이동한 것처럼 처리될 수 있다.

- 이때 물리 엔진이 중간에 있는 Collider를 감지하지 못하고 통과하는 현상이 발생할 수 있다.

- 이것을 터널링(Tunneling)이라고 한다.

 

① 예시

- 빠른 총알이 벽을 뚫고 지나감

- 빠른 캐릭터가 얇은 벽을 통과함

② 해당 내용 관련

- Collision Detection

- Continuous 충돌 감지

- 이동 속도 조절 (이동속도가 너무 빠르면 뚫고 지나간다)


 

7. 사용 예시

using UnityEngine;

public class RigidBasic : MonoBehaviour
{
    private Rigidbody rb;
    private Vector3 moveDir;

    [SerializeField]
    private float moveSpeed = 20.0f;

    private void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    private void Update()
    {
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");

				// 각 이동 처리 확인 뒤, 대각선 이동 보간
        moveDir = new Vector3(horizontal, 0.0f, vertical).normalized;
    }

    private void FixedUpdate()
    {
    
        Vector3 nextPos = rb.position + moveDir * moveSpeed * Time.fixedDeltaTime;
        rb.MovePosition(nextPos);
    }
    // 현재 위치에 (방향 *속도*물리 프레임에 걸리는 시간). 즉, 물리 프레임 동안 이동할 거리
    // 만큼 Rigidbody 이동.
}

8. 정리

※ Rigidbody는 오브젝트를 Unity 물리 엔진의 계산 흐름 안에서 동작하게 만드는 Component다.

※ 따라서 Rigidbody가 붙은 오브젝트는 Transform을 통해 직접 조작하기보다 상황에 맞게, AddForce, linearVelocity, MovePosition과 같은 Rigidbody 기반 방식을 사용하는 것이 좋다.

※ 이러한 Rigidbody 관련 물리 이동은 FixedUpdate()에서 처리하는 식으로 분리한다. 즉, Rigidbody를 사용할 때는 직접 위치를 바꾼다가 아닌 물리 엔진을 통해 움직이는 것이다.


 

Comments