Chaos Physics 아키텍처
UE5의 기본 물리 엔진 Chaos의 내부 구조와 모듈 시스템을 이해합니다
PhysX에서 Chaos로의 전환
왜 Epic Games는 자체 물리 엔진을 만들었는가
UE4까지 사용되던 NVIDIA PhysX는 오랜 기간 검증된 물리 엔진이었지만, 차세대 게임의 요구 사항을 충족하기에는 한계가 있었습니다. Epic Games는 대규모 파괴(Destruction), 네트워크 물리(Networked Physics), Large World Coordinates 지원을 위해 완전히 새로운 물리 엔진을 개발하기로 결정했습니다.
UE5.0부터 Chaos가 기본(default) 물리 엔진으로 설정되었으며, UE5.5+에서는 PhysX 관련 코드가 완전히 제거되었습니다. 기존 PhysX 기반 프로젝트를 마이그레이션할 때 이 점을 반드시 고려해야 합니다.
| 항목 | PhysX (UE4) | Chaos (UE5) |
|---|---|---|
| 개발사 | NVIDIA | Epic Games (자체 개발) |
| 파괴 시스템 | APEX Destruction (제한적) | Chaos Destruction (시네마틱 수준) |
| Cloth | APEX Cloth / NvCloth | Chaos Cloth |
| Vehicle | PhysX Vehicle | Chaos Vehicle |
| 네트워크 동기화 | 수동 구현 필요 | 내장 Network Physics Prediction |
| LWC 지원 | 미지원 | Large World Coordinates 네이티브 지원 |
| 비동기 시뮬레이션 | 제한적 | Async Physics Tick 네이티브 지원 |
Chaos 엔진 아키텍처 개요
모듈 기반 설계와 핵심 서브시스템
Chaos Physics는 모듈형 아키텍처로 설계되어, 각 물리 서브시스템이 독립적으로 동작하면서도 통합된 시뮬레이션을 제공합니다. 핵심 구성 요소는 다음과 같습니다:
- Chaos Core — 파티클 기반 시뮬레이션 프레임워크. 모든 물리 객체는 내부적으로 Particle로 표현됩니다.
- Chaos Solver — 물리 방정식을 풀어 시뮬레이션을 진행하는 핵심 솔버(PBD: Position Based Dynamics 기반).
- FPhysScene_Chaos — UE5의 물리 씬을 관리하는 최상위 클래스. World와 Physics Thread를 연결합니다.
- Collision Detection — Broadphase(AABBTree)와 Narrowphase(GJK/EPA) 2단계 충돌 감지.
- Constraint Solver — 조인트, 접촉점, 거리 제약 등 다양한 구속 조건을 처리합니다.
Chaos에서 모든 물리 객체(Rigid Body, Cloth Vertex, Destruction Fragment 등)는 내부적으로 Chaos::FGeometryParticle을 상속받은 파티클로 표현됩니다. 이 통합 설계 덕분에 서로 다른 물리 서브시스템 간의 상호작용이 자연스럽습니다.
// Chaos 물리 파티클 계층 구조 (Engine/Source/Runtime/Experimental/Chaos/)
namespace Chaos
{
// 최상위 파티클 - 위치/회전만 가짐
class FGeometryParticle;
// 운동학적 속성 추가 (속도, 각속도)
class FKinematicGeometryParticle : public FGeometryParticle;
// 동역학 속성 추가 (질량, 관성 텐서, 힘)
class FRigidBodyParticle : public FKinematicGeometryParticle;
// 파티클 핸들 - 외부에서 파티클에 접근하는 인터페이스
template<typename T>
class TGeometryParticleHandle;
}
Physics Module과 초기화 흐름
엔진 시작부터 물리 씬 생성까지의 과정
UE5에서 물리 시스템은 IPhysicsModule 인터페이스를 통해 모듈로 로드됩니다. Chaos 모듈은 엔진 초기화 시 자동으로 등록되며, FPhysScene_Chaos가 각 UWorld에 대해 생성됩니다.
// FPhysScene_Chaos 가 World 에 바인딩되는 과정
// UWorld::InitializePhysicsSceneForWorld() 에서 호출
void UWorld::InitWorld(const InitializationValues IVS)
{
// ... 월드 초기화 로직 ...
// 물리 씬 생성
CreatePhysicsScene();
}
void UWorld::CreatePhysicsScene()
{
// FPhysScene_Chaos 인스턴스 생성
PhysicsScene = new FPhysScene_Chaos();
// Chaos Solver 초기화
// - Broadphase 설정 (AABBTree)
// - Solver Iteration 횟수 설정
// - Gravity 설정
PhysicsScene->Init(GravityZ, SolverType);
}
| 초기화 단계 | 클래스 | 역할 |
|---|---|---|
| 1. 모듈 로드 | FChaosEngineModule |
Chaos 물리 모듈 등록 및 초기화 |
| 2. 씬 생성 | FPhysScene_Chaos |
물리 월드와 솔버 인스턴스 생성 |
| 3. 솔버 설정 | FPBDRigidsSolver |
PBD 기반 리지드 바디 솔버 구성 |
| 4. Broadphase | FAABBTree |
공간 분할 구조로 충돌 후보 탐색 |
| 5. 파티클 등록 | FGeometryParticle |
액터의 물리 바디를 파티클로 등록 |
Project Settings > Engine > Physics에서 Chaos 관련 전역 설정을 확인할 수 있습니다. Solver Iteration Count, Gravity, Broadphase 알고리즘 등 핵심 파라미터가 여기에 있습니다.
물리 시뮬레이션 루프
매 프레임 물리가 업데이트되는 과정
Chaos Physics의 시뮬레이션은 매 프레임(또는 비동기 틱) 다음 순서로 진행됩니다:
- 1단계: Pre-Solve — 외부 힘(Gravity, AddForce 등)을 파티클에 적용하고, 속도를 통합(Integration)합니다.
- 2단계: Broadphase — AABB 트리를 사용해 충돌 가능성이 있는 파티클 쌍을 빠르게 필터링합니다.
- 3단계: Narrowphase — GJK/EPA 알고리즘으로 정밀한 충돌 감지를 수행하고, Contact Point를 생성합니다.
- 4단계: Constraint Solve — PBD(Position Based Dynamics) 방식으로 접촉, 조인트, 거리 제약을 반복 풀이합니다.
- 5단계: Post-Solve — 최종 위치/회전을 게임 스레드로 전달하고, 이벤트(OnHit, OnOverlap 등)를 발생시킵니다.
// FPhysScene_Chaos의 시뮬레이션 틱 (간략화)
void FPhysScene_Chaos::Tick(float DeltaTime)
{
// 1. 외부 힘 적용 및 속도 적분
Solver->ApplyExternalForces(DeltaTime);
Solver->IntegrateVelocity(DeltaTime);
// 2. Broadphase - 충돌 후보 검색
Broadphase->FindPotentialCollisions(PotentialPairs);
// 3. Narrowphase - 정밀 충돌 감지
CollisionDetection->DetectCollisions(PotentialPairs, Contacts);
// 4. Constraint Solve (PBD 반복)
for (int i = 0; i < SolverIterationCount; ++i)
{
ConstraintSolver->SolveContacts(Contacts);
ConstraintSolver->SolveJoints(Joints);
}
// 5. 위치 업데이트 및 이벤트 디스패치
Solver->IntegratePosition(DeltaTime);
DispatchPhysicsEvents();
}
Chaos는 전통적인 Impulse 기반 솔버 대신 PBD(Position Based Dynamics)를 사용합니다. PBD는 위치 수준에서 직접 제약을 풀기 때문에 안정적이며, 반복 횟수(Solver Iteration)를 늘릴수록 정밀도가 높아집니다. 기본값은 보통 8~12회입니다.
Game Thread와 Physics Thread
멀티스레딩 아키텍처와 데이터 마샬링
Chaos Physics는 게임 스레드(Game Thread)와 물리 스레드(Physics Thread)가 분리된 아키텍처를 사용합니다. 이 설계는 CPU 활용률을 극대화하고, 물리 연산이 게임 로직에 프레임 지연을 주지 않도록 합니다.
| 스레드 | 역할 | 주요 클래스 |
|---|---|---|
| Game Thread | 게임 로직, Actor Tick, 입력 처리 | UPrimitiveComponent, FBodyInstance |
| Physics Thread | 물리 시뮬레이션, 충돌 감지, 솔버 | FPBDRigidsSolver, FGeometryParticle |
| Marshalling | 두 스레드 간 데이터 동기화 | FPhysicsProxy, FPhysicsCommand |
// Physics Proxy: Game Thread 객체와 Physics Thread 객체를 연결
// 각 UPrimitiveComponent는 대응하는 PhysicsProxy를 가짐
class FSingleParticlePhysicsProxy : public IPhysicsProxyBase
{
// Game Thread 측 데이터
FBodyInstance* BodyInstance;
// Physics Thread 측 파티클
Chaos::FRigidBodyHandle* PhysicsParticle;
// Game Thread -> Physics Thread 데이터 전송
virtual void PushToPhysicsState() override;
// Physics Thread -> Game Thread 결과 수신
virtual void PullFromPhysicsState() override;
};
프로젝트 설정에서 Tick Physics Async를 활성화하면 물리가 별도 스레드에서 고정 타임스텝으로 실행됩니다. 이는 프레임레이트 독립적인 물리 시뮬레이션을 보장하며, 네트워크 물리에서 특히 유용합니다. 자세한 내용은 Part 07에서 다룹니다.
핵심 요약
- Chaos Physics는 Epic Games가 UE5를 위해 자체 개발한 물리 엔진으로, PhysX를 완전히 대체합니다.
- 모든 물리 객체는 내부적으로 Particle로 표현되며,
FGeometryParticle계층 구조를 따릅니다. - FPhysScene_Chaos가 각 UWorld의 물리 씬을 관리하며, PBD 기반 솔버로 시뮬레이션을 수행합니다.
- 시뮬레이션 루프는 Pre-Solve → Broadphase → Narrowphase → Constraint Solve → Post-Solve 순서로 진행됩니다.
- Game Thread와 Physics Thread가 분리되어 있으며, Physics Proxy 패턴으로 데이터를 동기화합니다.
- Destruction, Vehicle, Cloth 등 모든 서브시스템이 동일한 Chaos 프레임워크 위에서 동작합니다.
도전 과제
배운 내용을 직접 실습해보세요
UE5 프로젝트를 생성하고 Project Settings > Engine > Physics에서 Chaos 관련 설정(Solver Iteration Count, Gravity Z, Broadphase Algorithm)을 확인한 뒤, 각 파라미터를 변경하며 물리 시뮬레이션 차이를 관찰하세요.
콘솔 명령어 stat physics를 실행하여 Physics Thread의 Tick 시간, Broadphase 시간, Solver 시간을 모니터링하세요. 물리 객체 수를 10개, 50개, 100개로 변경하며 성능 변화를 기록하세요.
C++ 프로젝트에서 FPhysScene_Chaos의 초기화 흐름을 로그로 추적하고, Solver Iteration Count를 4, 8, 16으로 변경한 뒤 스택된 박스 타워의 안정성 차이를 비교하는 테스트 레벨을 제작하세요.