Unity·Unreal 물리 엔진 충돌 지연(Jittering) 원인과 해결 방법

게임에서 충돌 순간 오브젝트가 떨리거나 튀는 물리 엔진 Jittering의 원인을 고정 시간 간격, 보간, 콜라이더, 질량비 관점에서 분석하고 Unity·Unreal 실전 해결 절차를 정리합니다.

✓ 복사 완료!
챕터일반 가이드
난이도중급
상태● 검토 완료
대상 엔진
UnityUnreal Engine
최종 업데이트
Unity·Unreal 물리 엔진 충돌 지연(Jittering) 원인과 해결 방법

물리 충돌 지연(Jittering)은 렌더링 프레임과 물리 시뮬레이션의 시간 간격이 다르거나 접촉점 보정이 반복해서 충돌할 때 주로 발생합니다. 먼저 물리 객체는 고정 시간 단계로 이동시키고 화면에는 보간된 위치를 표시하며 콜라이더 중첩·과도한 질량비·이동 방식 충돌을 제거해야 합니다.

물리 엔진 충돌 지연은 왜 발생하는가?

물리 엔진은 일반적으로 일정한 시간 간격마다 속도, 힘, 충돌을 계산합니다. 반면 렌더링은 기기 성능과 화면 주사율에 따라 매 프레임 실행됩니다. 두 주기가 맞지 않으면 물체의 실제 물리 위치와 화면에 보이는 위치가 번갈아 어긋나면서 떨림처럼 보입니다.

물리 시뮬레이션의 시간 단계는 다음과 같이 표현할 수 있습니다.

xt+Δt=xt+vtΔtx_{t + \Delta t} = x_t + v_t \Delta t

여기서 Δt가 물리 단계마다 일정하지 않거나 렌더링이 물리 결과 사이를 부드럽게 연결하지 않으면 위치 변화가 계단처럼 나타납니다. 충돌이 있는 경우 엔진은 접촉 침투를 밀어내는 보정까지 수행하므로 시각적 떨림이 더 커질 수 있습니다.

물리 고정 업데이트와 렌더링 프레임 간격 차이로 위치가 계단처럼 변하는 모습

대표적인 원인 비교

원인나타나는 증상우선 해결책
렌더링과 물리 업데이트 주기 불일치이동 중인 Rigidbody가 미세하게 끊겨 보임Rigidbody 보간 사용
Update에서 물리 객체 위치 변경충돌 시 밀림, 관통, 불안정한 반발FixedUpdate와 물리 API 사용
콜라이더 초기 중첩 또는 너무 얇은 콜라이더충돌 순간 튀거나 계속 진동배치 간격, 콜라이더 형태 점검
큰 질량비가벼운 물체가 심하게 튐질량비 완화, Solver 반복 횟수 조정
프레임 드롭물리 단계가 한 번에 여러 번 실행되어 갑작스러운 이동물리 비용 최적화, 최대 시간 단계 점검
카메라가 다른 업데이트 주기를 따름캐릭터는 정상인데 화면만 흔들림카메라 추적 시점 통일

Unity Rigidbody Jittering은 어떻게 해결할까?

Unity에서 동적 물체는 Transform.position으로 직접 움직이지 않는 것이 기본입니다. Transform을 직접 수정하면 PhysX가 예상한 이전 상태와 실제 위치가 달라져 충돌 해석이 불안정해질 수 있습니다.

1. 물리 이동을 FixedUpdate로 옮긴다

힘, 속도, Rigidbody.MovePosition 같은 물리 처리는 FixedUpdate에서 실행합니다. 입력값은 Update에서 받아 두고 물리 단계에서 사용하면 입력 누락도 줄일 수 있습니다.

using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class PhysicsMover : MonoBehaviour
{
    [SerializeField] private float speed = 5f;

    private Rigidbody body;
    private Vector2 moveInput;

    private void Awake()
    {
        body = GetComponent<Rigidbody>();
        body.interpolation = RigidbodyInterpolation.Interpolate;
    }

    private void Update()
    {
        moveInput = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")).normalized;
    }

    private void FixedUpdate()
    {
        Vector3 velocity = new Vector3(moveInput.x, 0f, moveInput.y) * speed;
        body.velocity = new Vector3(velocity.x, body.velocity.y, velocity.z);
    }
}

RigidbodyInterpolation.Interpolate는 이전 물리 상태와 현재 물리 상태 사이를 보간해 렌더링 위치를 부드럽게 만듭니다. 플레이어처럼 카메라가 가까이에서 추적하는 Rigidbody에 특히 효과적입니다.

2. Rigidbody 종류와 이동 API를 맞춘다

객체 유형권장 방식피해야 할 방식
동적 Rigidbody힘, 속도, MovePosition매 프레임 Transform.position 변경
키네마틱 RigidbodyMovePosition, 애니메이션 기반 이동동적 물체처럼 힘 적용 기대
정적 배경 콜라이더움직이지 않는 Collider런타임에 Transform을 계속 변경
이동 발판키네마틱 Rigidbody + MovePositionCollider만 Transform으로 이동

동적 Rigidbody를 순간이동해야 한다면 속도도 함께 의도적으로 초기화해야 이전 충돌 반응이 남는 문제를 줄일 수 있습니다.

body.position = spawnPoint.position;
body.velocity = Vector3.zero;
body.angularVelocity = Vector3.zero;

3. 접촉 조건과 Solver 설정을 점검한다

물체가 시작부터 겹쳐 있으면 엔진은 매 물리 단계마다 침투를 해소하려고 합니다. 벽과 바닥, 발판의 콜라이더가 서로 불필요하게 겹치지 않는지 먼저 확인하세요.

다음 조건에서는 Unity의 Project Settings > Physics에서 Solver Iterations와 Solver Velocity Iterations을 소폭 높이는 방법이 유효할 수 있습니다.

  • 무거운 상자 위에 매우 가벼운 물체가 쌓인다.
  • 빠르게 움직이는 물체가 얇은 콜라이더와 충돌한다.
  • 관절(Joint)로 연결된 구조물이 흔들린다.

다만 반복 횟수 증가는 CPU 비용을 높입니다. 전역 값을 크게 올리기보다 문제가 있는 Rigidbody의 Solver Iterations를 먼저 조정하는 편이 안전합니다.

Unreal Engine에서 충돌 떨림을 줄이는 방법은?

Unreal Engine에서도 핵심은 같습니다. 물리 시뮬레이션으로 움직이는 컴포넌트와 프레임 기반 위치 변경을 섞지 말고 빠르거나 무거운 물체에만 필요한 물리 정확도를 적용합니다.

1. Simulate Physics 객체에는 물리 함수 사용

Simulate Physics가 활성화된 Static Mesh Component를 매 Tick마다 SetActorLocation으로 움직이면 충돌 해석과 위치 강제가 경쟁할 수 있습니다. 지속 이동에는 힘·임펄스·속도 제어를 사용하고 순간 이동이 목적일 때만 Teleport 옵션을 명확히 사용하세요.

블루프린트에서는 다음 구분이 실용적입니다.

  • 밀고 당기는 물체: Add Force, Add Impulse
  • 지속 속도 제어: Set Physics Linear Velocity
  • 순간 배치 변경: Set World Location의 Teleport 사용 여부를 의도에 맞게 선택
  • 캐릭터: CharacterMovementComponent의 이동 처리 유지

2. 빠른 충돌에는 CCD와 Substepping을 제한적으로 적용

작고 빠른 물체는 한 물리 단계 사이에 얇은 벽을 통과할 수 있습니다. 이때 Continuous Collision Detection(CCD) 또는 Physics Substepping이 도움이 됩니다.

하지만 모든 물체에 적용하면 물리 비용이 빠르게 늘어납니다. 총알, 빠른 투사체, 충돌 정확도가 중요한 소수의 액터에만 적용하는 것이 좋습니다.

빠른 투사체가 이산 물리 단계에서 얇은 벽을 통과하는 경우와 연속 충돌 검사를 적용한 경우

3. 카메라 추적과 물리 시점을 분리해 확인한다

캐릭터 본체는 안정적인데 카메라만 흔들린다면 충돌 해결 문제가 아니라 카메라 업데이트 순서 문제일 수 있습니다. 스프링 암, 카메라 컴포넌트, 추적 대상이 서로 다른 Tick Group에서 갱신되는지 확인하고 카메라가 보간된 최종 위치를 따라가도록 구성하세요.

충돌 Jittering을 해결하는 점검 순서

1. 증상을 재현하고 물리 객체를 분류한다

문제가 동적 Rigidbody인지 키네마틱 이동체인지 캐릭터 컨트롤러인지 구분합니다. 카메라만 흔들리는지 실제 충돌체가 진동하는지도 별도로 확인합니다.

2. 위치 변경 경로를 하나로 통일한다

물리 객체의 Transform 직접 변경, Update 이동, 애니메이션 루트 모션, 네트워크 동기화가 동시에 위치를 덮어쓰지 않는지 찾습니다. 한 객체는 한 가지 권한 있는 이동 경로만 갖게 만드세요.

3. 시간 단계와 보간을 조정한다

Unity라면 FixedUpdate와 Rigidbody 보간부터 적용합니다. Unreal이라면 물리 시뮬레이션 객체의 Tick 기반 위치 강제를 제거하고 필요한 객체에만 Substepping 또는 CCD를 적용합니다.

4. 콜라이더와 질량비를 단순화한다

복잡한 Mesh Collider 대신 가능한 경우 Box, Capsule, Sphere Collider를 사용합니다. 접촉하는 두 객체의 질량 차이가 지나치게 크지 않은지, 초기 배치가 겹치지 않는지 점검합니다.

5. 프로파일러로 프레임 드롭을 확인한다

물리 설정만 높여 해결하려 하지 마세요. CPU 병목으로 프레임 시간이 길어지면 물리 단계가 누적되어 또 다른 끊김이 생깁니다. Unity Profiler 또는 Unreal Insights로 Physics 비용과 프레임 시간을 함께 확인합니다.

flowchart TD
    A[충돌 또는 화면 떨림 재현] --> B{실제 충돌체가 흔들리는가?}
    B -->|아니오| C[카메라 추적 및 업데이트 순서 점검]
    B -->|예| D{물리 객체를 Transform으로 이동하는가?}
    D -->|예| E[물리 API와 고정 물리 단계로 변경]
    D -->|아니오| F{빠른 물체 또는 큰 질량비인가?}
    F -->|예| G[CCD·Substepping·Solver를 대상별 조정]
    F -->|아니오| H[콜라이더 중첩과 프레임 드롭 점검]

자주 묻는 질문 (FAQ)

Rigidbody Interpolate만 켜면 충돌 떨림이 해결되나요?

아닙니다. Interpolate는 렌더링 시각의 움직임을 부드럽게 할 뿐입니다. Transform 직접 변경, 콜라이더 중첩, 불안정한 질량비로 생기는 실제 물리 진동은 별도로 해결해야 합니다.

Fixed Timestep을 더 작게 만들면 항상 좋아지나요?

물리 정확도는 높아질 수 있지만 초당 계산 횟수와 CPU 비용도 증가합니다. 먼저 이동 API와 보간을 바로잡고 빠른 충돌처럼 정확도가 필요한 상황에서만 시간 단계 조정을 검토하세요.

빠른 투사체에는 Rigidbody와 CCD가 항상 필요한가요?

필수는 아닙니다. 명중 판정만 필요하다면 이전 위치에서 현재 위치까지 Raycast 또는 SphereCast를 수행하는 방식이 더 단순하고 예측 가능할 수 있습니다. 실제 반동과 물리 상호작용이 필요할 때 Rigidbody와 CCD를 사용하세요.

정리

충돌 Jittering의 우선 해결 순서는 명확합니다. 물리 객체의 위치 변경을 물리 시스템으로 통일하고 렌더링 보간을 적용한 뒤 콜라이더·질량비·고속 충돌 조건을 점검하세요. Solver 반복 횟수와 Substepping은 근본 원인을 정리한 뒤 필요한 객체에만 제한적으로 적용하는 것이 성능과 안정성을 함께 지키는 방법입니다.