개요

 언리얼엔진의 물리연산은 Determinism(결정론적 동작)을 보장하고 있지 않지만 Physics Divergence(물리 연산의 오차 발산)을 막기 위해 어느정도 고려하고 있습니다. 특히 네트워크 동기화에서는 매 Frame마다 물리 연산이 조금이라도 달라지면 짧게는 수 Frame, 길게는 수 초 후의 결과가 완전히 달라지기 때문에 여러 구조적 개선을 지속적으로 진행해왔습니다. 이 글은 그러한 언리얼 엔진의 Physics를 Determinism 관점으로 오차 최소화를 어떻게 달성하였는지에 대해 정리한 글입니다.

 

언리얼엔진의 물리, 각 스텝 정리

[1] PrePhysics

Actor Tick (PrePhysics Group)

  • 입력 처리 / 이동 요청 확정
  • 물리에 들어가기 전 게임 상태 정리(게임 로직 기반 상태 업데이트)
  • Determinism 관점
    • Lockstep에서 "동일한 입력"이 보장되어야 하므로 이 단계가 핵심입니다.
    • 모두 같은 프레임에서 같은 입력을 받고 동일한 초기 상태를 맞춰야 Physics Divergence를 방지할 수 있습니다.

▼  (Barrier: 모두 완료 시 다음 단계)

 

[2] StartPhysics

  • Chaos Physics 엔진에 Step 시작 명령
  • Substep 준비
  • Collision BroadPhase 준비
  • Determinism 관점
    • Substep 개수, Step 간격, BroadPhase(충돌 탐색 알고리즘 순서)가 플랫폼과 스레드에 영향을 받지 않게 유지될수록 Determinism이 향상된다.
    • UE5에서 이곳의 안정성을 강화하고 있습니다.

 

[3] DuringPhysics

  • Substep 단위로 Physics Integration
  • 강체를 이동시킨 후, 충돌 감지, 반응 계산을 병렬로 수행
  • Solver 수행
  • Chaos Simulation 실행
  • Determinism 관점
    • 가장 Non-deterministic한 단계로 이 단계에서는 Divergence가 아래의 세가지 이유로 발생합니다.
      • Floating point차이
      • 멀티스레드 스케줄링 차이
      • Solver 순서 차이
    • 그렇기에 Lockstep 구현 시에는 Fixed Step, Fixed Seed, 동일 Substep을 강제로 통일합니다.

▼  (Barrier: 모든 물리 연산 완료 시 다음 단계)

 

[4] EndPhysics (PostPhysics)

  • Physics 결과를 게임 월드로 반영
  • Transform Sync
  • CharacterMovement / VehicleMovement 이동 보정(RootMotion/Prediction 보정)
  • PostPhysics Tick 실행
  • Determinism 관점
    • Physics가 만든 결과가 실제 게임 로직으로 흘러 들어가는 구간으로 Lockstep에서의 값들이 모든 클라이언트에 동일해야 이후 Prediction/Interpolation이 안정적으로 작동합니다.

 

[5] PostUpdate

  • During Physics의 모든 병렬 스레드를 대기하여 정리
  • Rendering 준비
  • Determinism 관점
    • 물리 결과가 렌더링 이전에 완전히 확정되는 곳입니다. 즉 Lockstep에서는 Frame Boundary가 되는 지점입니다.

Solver란?

 물리 연산 과정에서 발생한 힘, 속도, 충돌 등을 정리하여 게임에 맞게 보정하는 단계입니다. Chaos에서는 충돌 후의 위치, 속도, 반응을 반복 계산(Iterative Solve)하여 안정적인 결과로 수렴시키며, 최종적으로는 게임 월드에 반영하기 적합한 형태로 물리 상태를 정제하는 역할을 합니다.

 

Substep이란?

 하나의 물리 Frame을 여러개의 더 작은 시간 단위로 나누어 여러 번 시뮬레이션을 수행하는 구조입니다. 그로 인해 PhysicsThread는 고정된 시간 간격(Fixed Step)으로 더 촘촘하게 물리를 계산할 수 있습니다. 기본적으로 GameThread의 Tick 속도와 관계없이 진행됩니다. 하지만 PrePhysics와 PostPhysics가 GameThread에 종속되어 있기 때문에 시작과 끝으로 동기화 된다고 보시면 됩니다.

 Substep은 다음 목적에서 사용됩니다.

  • 빠르게 움직이는 객체의 충돌 누락 방지
  • 폭발, 충돌 등 입출력이 빠르게 변하는 상황에서 안정적인 결과 유지
  • Lockstep에서 모든 클라이언트가 동일한 수의 Substep을 수행하도록 강제하여 Determinism을 향상시킴

결론

 이처럼 물리 파이프라인의 각 단계를 통일된 방식으로 처리하여 Lockstep 구조에서 발생하는 Physics Divergence를 크게 줄일 수 있습니다. 또한 UE5가 지속적으로 강화하고 있는 Substep·Solver·Tick 구조는 Determinism을 향상시키는 방향으로 설계되어 있어 언리얼엔진에 있어 네트워크 게임에서의 물리 불일치 문제를 완화하는 핵심 축이 되었습니다.

 

 

GPU의 역사 - 1 : FFP에서 SIMD까지

그래픽카드의 한계 2000년대 초반의 GPU는 FFP(Fixed Function Pipeline)중심이었고, 지금처럼 복잡한 셰이더 기반 렌더링이 불가능했습니다. VRAM 용량도 32~64MB 수준이라 SSAA나 고급 조명 기법을 적용하기

chessire.tistory.com

이전 글과 이어지는 게시글입니다.

 

UE2의 등장

 UE2는 2001년에 빌드 633 형태로 처음 공개되었습니다. 2001년 이전의 GPU는 대부분 FFP(Fixed Function Pipeline) 기반이었지만, DirectX 8 세대에 들어서면서 픽셀 셰이더와 버텍스 셰이더를 활용할 수 있게 되었습니다. UE2는 이러한 변화에 맞추어 GPU 가속 렌더링과 멀티플랫폼을 고려한 구조로 설계되었고, 이때부터 고정 함수 결과에 셰이더 출력을 조합(Combine) 하는 형태의 Material 처리 방식이 자리 잡기 시작했습니다. 이 과정에서 지금의 Material System으로 이어지는 초기 형태의 조합 기반 효과(= Add, Mul, Lerp 등을 활용한 간단한 Overlay 스타일 처리)가 사용되었고, 이후 언리얼 엔진 3에서 노드 기반 Material Editor로 확장되며 우리가 알고 있는 Overlay 계열 블렌딩이 정식 기능으로 자리 잡게 됩니다.

Rendering Pipeline

Fixed-Function Pipeline

 앞서 설명드린 것 처럼 DirectX8 이전 버전은 FFP 기반이었고, DirectX9 초기까지도 FFP를 기반한 Rendering Pipline형태였습니다. (위 이미지 참고) Diffuse Lighting, Lightmap 같은 연산은 여전히 하드웨어 단계에서 단계적으로 수행하였죠. 여기까지는 Programmable Shader가 개입할 수 없었습니다.

Execute Shader

 완전한 형태의 Programmable은 아니었지만 Pixel Shader Stage가 생기면서 UE2에도 부분적으로 Shader가 들어오기 시작했습니다. 조명 보정을 위한 NormalMap, Overlay에 쓰일 추가 색 계산까지, 드디어 Pixel Shader Stage가 하드웨어에 고정된  형식이 아닌 프로그래머가 작성한 코드를 통해 하드웨어에서 실행할 수 있게 된 것입니다.

Combine Process

 그렇게 Pixel Shader Stage에서 실행된 코드가 Combine Process를 타고 FFP의 결과물에 Overlay되게 됩니다. UE2 시절의 Overlay는 Add/Multiply 기반의 단순 조합이었음에도 언리얼엔진의 초기 머터리얼 시스템의 개념적 기반이 될 수 있었습니다. 즉, 텍스처 샘플링 결과와 셰이더에서 계산된 값을 다양한 방식으로 섞어 최종 색을 만드는 개념이 이때 자리를 잡기 시작한 것입니다. 이 개념은 UE3에서 노드 기반 머터리얼 시스템으로 확장되며 지금과 같은 형태까지 발전하게 됩니다.

Pixel Output

 그렇게 최종적으로 픽셀이 화면에 출력되게 됩니다. Pixel Output은 GPU 파이프라인의 End Point이지만, 그 이전 단계에서 FFP 연산, 쉐이더 계산, 조합 과정 등 다양한 처리가 누적되며 최종적인 화면이 구성됩니다. 즉, 우리가 보는 한 장의 화면은 여러 단계의 계산이 겹쳐 만들어진 결과물인 셈입니다.

Epic Games, Post Process 설명에서 발췌

Post Process Effect

 UE2 후반에 와서 카툰 렌더링(셀 셰이딩 + 외곽선 추출)을 비롯한 다양한 Post Process Effect가 가능해졌습니다. UE2당시의 Post Process는 단순히 화면 렌더링을 한번 더 샘플링 하는 단순 스크린 패스 수준이었지만 UE3에서 실질적인 체계가 확립되고 UE4에서 영화 렌더러 수준까지 진화할 정도의 무서운 약진이라 할 수 있습니다.

 

맺는 말

기술을 배울 때 그 변화의 흐름을 함께 이해하면 구조가 더 명확하게 잡히고, 어떤 설계 철학으로 발전해 왔는지도 선명하게 드러납니다. 언리얼 엔진은 이제 게임뿐 아니라 영화, 건설, 시뮬레이션 등 다양한 분야에 활용되는 범용 실시간 엔진이 되었고, 그중 UE2는 렌더링 시스템의 기반이 형성되던 중요한 시기였습니다.

 오늘은 UE2의 Overlay와 Post Process Effect를 간단히 정리해보았습니다. 다음 글에서는 UE3에서 본격적으로 확립된 머티리얼 시스템과 렌더링 변화에 대해 이어 설명하겠습니다.

'Game Programming > Unreal Engine' 카테고리의 다른 글

Unreal Engine Physics Determinism: Lockstep  (0) 2025.12.10

+ Recent posts