물리 시뮬레이션 기본 제어
컴포넌트의 물리 시뮬레이션과 질량·재질을 설정하고 힘과 토크를 적용해 강체 움직임을 제어합니다.
상자를 쌓아 두고 공을 던지면 상자가 무너지고, 얼음 위의 썰매는 멀리 미끄러지고, 폭발 근처의 통은 날아갑니다. 이런 반응을 하나하나 애니메이션으로 만든다면 끝이 없습니다. 게다가 플레이어가 어디서 무엇을 던질지 미리 알 수 없으므로, 정해진 애니메이션만으로는 모든 경우를 다룰 수도 없습니다.
언리얼 엔진은 물리 엔진을 내장하고 있어서 충돌, 중력, 힘 같은 현상을 계산으로 처리합니다. 10장은 이렇게 게임 세계의 물리와 환경을 다루는 장이며, 이 글에서는 그 출발점으로 물리 시뮬레이션의 개념과, 컴포넌트 단위로 물리를 켜고 질량과 재질을 정하고 힘을 가하는 방법을 익힙니다.
물리 시뮬레이션이 하는 일
물리 시뮬레이션(physics simulation)은 게임 안의 오브젝트가 중력, 질량, 마찰, 충돌 같은 물리 법칙에 따라 서로 반응하게 만드는 과정입니다. 정해진 애니메이션을 재생하는 것과 달리, 매 순간의 상태에서 다음 상태를 계산하므로 미리 정하지 않은 상호작용도 만들어 냅니다.
물리 시뮬레이션을 쓰는 이유는 크게 네 가지입니다. 먼저 현실감입니다. 총에 맞은 적이 쓰러지는 방식이나 폭발로 흩어지는 파편이 물리적으로 반응하면 게임 세계가 더 설득력 있게 느껴집니다. 다음은 게임플레이의 변화로, 오브젝트를 밀어 길을 막거나 새 경로를 만드는 퍼즐처럼 매번 다른 상황이 생깁니다. 제작 효율도 있습니다. 모든 반응을 손으로 애니메이션하거나 스크립트로 짤 필요 없이 물리 엔진이 계산해 주므로 개발 시간이 줄어듭니다. 마지막으로 물리 기반의 상호작용은 가끔 예상하지 못한 재미있는 상황을 만들어 냅니다.
언리얼 엔진 5.8의 물리 엔진
언리얼 엔진의 물리 백엔드는 버전에 따라 다릅니다. UE4 계열은 주로 NVIDIA의 PhysX를 썼고, UE5 계열은 카오스 물리(Chaos Physics)가 기본입니다. 이 교재가 기준으로 삼는 언리얼 엔진 5.8도 Chaos를 씁니다. 강체(rigid body), 충돌, 제약(constraint), 파괴, 천 시뮬레이션 같은 물리 기능을 찾아볼 때는 자료가 어느 엔진 버전과 물리 백엔드를 기준으로 하는지부터 확인해야 합니다. 인터넷의 오래된 자료 가운데는 PhysX 전용 설정이나 명령을 설명하는 것이 많기 때문입니다.
컴포넌트에서 물리 켜기
언리얼 엔진에서 물리 시뮬레이션은 주로 프리미티브 컴포넌트(Primitive Component), 곧 스태틱 메시, 스켈레탈 메시, 캡슐 콜리전 같은 컴포넌트 단위로 제어합니다. 액터 자체가 물리를 계산하는 것이 아니라, 액터에 들어 있는 컴포넌트가 물리적 특성을 가집니다.
가장 기본적인 제어는 컴포넌트의 물리 시뮬레이션을 켜고 끄는 것입니다. 물리를 적용할 액터 블루프린트, 예를 들어 BP_PhysicsCube를 열고, 디테일 패널에서 물리를 적용할 Static Mesh Component 같은 프리미티브 컴포넌트를 선택합니다. 그리고 Physics 섹션의 Simulate Physics를 켭니다. 이때 컴포넌트가 Movable이어야 하고, 유효한 물리 바디와, 물리 충돌을 허용하는 Collision Enabled 설정이 준비되어 있어야 합니다. 스태틱 메시라면 알맞은 단순 충돌(simple collision)이 있는지, 스켈레탈 메시라면 피직스 에셋(Physics Asset)에 바디가 있는지 확인합니다.
Simulate Physics를 켜면 그 컴포넌트의 위치와 회전은 엔진의 물리 계산이 정합니다. 그래서 블루프린트에서 Set Relative Location 같은 노드로 위치를 강제로 바꾸면 물리 계산과 부딪혀 부자연스러운 결과가 나올 수 있습니다. 물리로 움직이는 물체는 힘이나 충격량으로 움직이는 것이 원칙입니다.
물리 충돌이 일어났을 때 On Hit 이벤트를 받고 싶다면, 보통 Simulation Generates Hit Events를 켜고 콜리전 응답을 Block으로 맞춰야 합니다. 서로 겹쳤을 때의 Overlap 이벤트는 이와 별개로 Generate Overlap Events와 Overlap 응답을 맞춰야 받을 수 있습니다. 이 차이는 다음 글에서 자세히 다룹니다.
두 가지 예를 보겠습니다. 떨어지는 상자를 만들려면 물리를 적용할 메시를 액터의 루트로 두고 Simulate Physics와 알맞은 콜리전 프리셋을 설정합니다. 루트가 아닌 자식 컴포넌트 하나에 시뮬레이션을 켜면 그 컴포넌트가 부모에서 떨어져 나가 따로 움직일 수 있고, 시뮬레이션을 다시 끈다고 저절로 다시 붙지는 않습니다. 부딪히면 열리는 문을 만들려면 문에 물리 시뮬레이션을 켜는 것과 함께 경첩 역할을 하는 Physics Constraint를 설정해야 합니다. 시뮬레이션만 켜면 문 전체가 바닥으로 떨어집니다.
질량과 감쇠 정하기
물체의 질량, 감쇠, 표면 재질은 물리 시뮬레이션의 결과를 크게 바꿉니다. 감쇠(damping)는 속도와 회전에 대한 저항이고, 표면의 마찰은 뒤에서 볼 물리적 재질의 Friction으로 다룹니다. Simulate Physics를 켠 컴포넌트를 선택하면 Physics 섹션에서 다음 값을 조정할 수 있습니다.
| 항목 | 하는 일 |
|---|---|
Mass (kg) | 물체의 질량을 킬로그램 단위로 보여 줍니다. 기본 힘과 충격량 계산에서는 질량이 클수록 같은 입력에 덜 반응합니다. 체크하면 질량을 직접 지정할 수 있고, 블루프린트에서는 Set Mass Override in Kg 노드로 바꿉니다. |
Mass Scale | 계산된 질량에 배율을 곱해 조정합니다. |
Linear Damping | 직선 속도를 줄이는 저항입니다. 값이 클수록 이동 속도가 빨리 줄어듭니다. |
Angular Damping | 회전 속도를 줄이는 저항입니다. 값이 클수록 회전이 빨리 멈춥니다. |
Enable Gravity | 이 컴포넌트에 중력을 적용할지 정합니다. 끄면 중력의 영향을 받지 않습니다. |
질량이 반응을 줄인다는 설명에는 예외가 있습니다. 뒤에서 볼 Vel Change나 Accel Change처럼 질량을 무시하는 옵션을 켜면 질량과 관계없이 같은 변화가 적용되므로, 이 표의 설명과 구분해야 합니다.
물리적 재질로 표면 정하기
물리적 재질(Physical Material)은 물체 표면의 마찰력(friction)과 반발력(restitution)을 정의해, 부딪히거나 미끄러질 때의 반응을 정하는 에셋입니다. 콘텐츠 브라우저에서 마우스 오른쪽 버튼을 눌러 Physics > Physical Material을 고르고, PM_Ice나 PM_Rubber처럼 이름을 짓습니다.
에셋을 열면 디테일 패널에서 세 값을 정할 수 있습니다. Friction은 표면의 마찰 계수로, 값이 클수록 마찰이 강해 잘 미끄러지지 않습니다. 다른 재질과 만났을 때 두 마찰 값을 어떻게 합칠지는 Friction Combine Mode로 조정할 수 있습니다. Restitution은 다른 물체와 부딪힐 때의 반발 계수로, 값이 클수록 더 많이 튕겨 나갑니다. Density는 물질의 밀도로, 질량을 계산하는 데 쓰일 수 있습니다. 얼음이라면 Friction을 낮게, 고무공이라면 Restitution을 높게 두는 식입니다.
만든 재질은 컴포넌트에 연결해야 적용됩니다. 물리를 적용할 Static Mesh Component를 선택하고 Phys Material Override에 만든 물리적 재질을 지정합니다. 스태틱 메시 에셋 쪽의 Simple Collision Physical Material로 단순 충돌의 재질을 정하는 방법도 있습니다. 재질이 기대대로 적용되지 않는다면, 실제로 쓰이는 충돌 형상이 무엇이고 재질이 어느 경로로 지정되었는지를 함께 확인합니다.
힘, 충격량, 토크 가하기
블루프린트에서는 물리 시뮬레이션 중인 물체에 직접 힘을 가해 움직임을 제어할 수 있습니다. 세 노드 모두 Target에 힘을 받을 프리미티브 컴포넌트를 연결합니다.
| 노드 | 하는 일 | 주요 입력 | 예 |
|---|---|---|---|
Add Force | 지정한 방향으로 계속 미는 힘을 가합니다. 힘이 유지되어야 하는 동안 반복해서 호출합니다. | Force(방향과 크기), Bone Name(스켈레탈 메시의 특정 본) | 바람, 제트 추진 |
Add Impulse | 한순간에 충격량을 한 번 가합니다. | Impulse(충격량 벡터), Vel Change | 폭발, 총격 |
Add Torque in Radians | 물체를 회전시키는 힘(토크)을 가합니다. | Torque(토크 벡터) | 회전하는 바퀴 |
공식 문서는 Add Impulse를 한 번의 순간적인 분출에 알맞은 노드로 설명하고, Vel Change를 켜면 입력을 충격량이 아니라 속도 변화로 다루어 질량이 영향을 주지 않는다고 설명합니다. 반대로 Add Force는 한 번 호출하면 그 물리 스텝에만 작용하므로, 지속적인 추진을 원한다면 필요한 기간 동안 반복해서 호출하는 흐름을 따로 만들어야 합니다.
두 가지 활용 예를 보겠습니다. 총알이 적에게 맞았을 때 밀려나는 효과는, 래그돌처럼 실제로 시뮬레이션 중인 스켈레탈 메시의 바디에 Add Impulse를 적용해 만듭니다. 캐릭터가 일반적인 CharacterMovementComponent 이동 상태라면 물리 바디가 시뮬레이션 중이 아니므로, 캐릭터를 밀어낼 때는 Launch Character 같은 이동 쪽 노드를 씁니다. 차량이 언덕을 오르는 구동력은 바퀴 컴포넌트에 Add Force를 계속 적용해 흉내 낼 수 있습니다.
같은 충격량을 두 질량에 주기
질량이 반응을 어떻게 바꾸는지 비교 실험으로 확인해 보겠습니다. 먼저 BP_PhysicsCube 두 개를 바닥이나 다른 물체에 닿지 않는 위치에 둡니다. 각 큐브는 메시를 루트로 하고, Movable, 유효한 단순 충돌, 물리 충돌을 준비한 뒤 시뮬레이션을 켭니다. 두 바디는 처음에 정지해 있고, 중력을 끄고, 감쇠도 0으로 맞춥니다. 질량은 각각 2 kg과 4 kg으로 확인합니다. 다른 힘, 접촉, 제약이 없는 직선 운동만 비교하려는 조건입니다.
입력 이벤트 한 번에서 두 메시를 각각 Target으로 해 같은 벡터의 Add Impulse를 적용하고, Vel Change는 끕니다. 물리 스텝이 진행된 뒤 두 바디의 선속도를 비교하면, 속도 변화는 충격량을 질량으로 나눈 값이므로 2 kg 바디의 속도 변화가 4 kg 바디의 두 배가 됩니다. 다만 이것은 중력, 감쇠, 충돌을 모두 뺀 조건의 계산이며, 실제 월드에서 이것들을 다시 켠 결과까지 같은 비율이라고 단정하지 않습니다. 또 이 실험은 한 번의 충격이므로, 계속 미는 추진을 보고 싶다면 Add Force를 필요한 기간에 반복 호출하는 별도의 흐름을 만듭니다. 이 결과는 공식 문서의 노드 설명과 운동량의 관계로 계산한 것이며, 실제 엔진에서 실행해 옮긴 값은 아니므로 프로젝트의 물리 설정을 맞춘 뒤 직접 확인해 보세요.
물리 시뮬레이션 디버깅
물리가 기대대로 움직이지 않을 때는 먼저 충돌 형상을 눈으로 확인합니다. 플레이 중에 콘솔에서 show collision을 입력하면 콜리전 형상이 표시되므로, 형상과 응답이 의도와 맞는지 볼 수 있습니다. UE5의 Chaos 프로젝트라면 카오스 비주얼 디버거(Chaos Visual Debugger)로 물리 바디, 제약, 충돌 이벤트를 기록하고 추적할 수 있습니다. 오래된 자료에 나오는 pxvis collision, pxvis joints, pxvis bodies 같은 명령은 UE4의 PhysX 프로젝트용이므로, UE5의 Chaos에서는 그대로 쓸 수 없을 수 있습니다. 물리 계산의 성능은 콘솔(~)에서 stat physics로 통계를 띄워 확인합니다.
물리를 쓸 때 따질 것
먼저 성능입니다. 너무 많은 물체에 복잡한 물리 시뮬레이션을 적용하면 성능이 떨어질 수 있으므로, 필요한 물체에만 시뮬레이션을 켜고, 단순화한 콜리전 메시를 쓰고, 움직임이 멈춘 바디가 계산을 쉬는 슬립(sleep) 기능을 활용합니다.
재현성과 동기화도 따져야 합니다. 플랫폼, 시간 간격, 설정이 다른 실행에서 물리 결과가 비트 단위까지 똑같이 나온다고 가정하지 않습니다. 멀티플레이어에서는 최종 게임 상태를 서버가 정하고, 물리 상태의 복제와 예측, 보정 방식을 따로 설계합니다.
물체끼리 어떻게 반응하는지는 콜리전 채널과 프리셋 설정에 크게 좌우됩니다. 이 설정은 다음 글에서 다룹니다. 마지막으로 캐릭터가 걷다가 총에 맞아 래그돌로 바뀌는 것처럼 애니메이션과 물리가 함께 쓰이는 경우에는, 둘 사이의 전환이 자연스럽게 이어지도록 신경 써야 합니다.
정리
- 물리 시뮬레이션은 오브젝트가 중력, 질량, 마찰, 충돌에 따라 반응하게 만드는 계산이며, 언리얼 엔진 5.8은 Chaos 물리를 씁니다.
- 물리는 프리미티브 컴포넌트 단위로 켜며,
Simulate Physics에는 Movable, 유효한 물리 바디, 물리 콜리전 설정이 필요합니다. 켠 뒤에는 위치를 직접 바꾸지 말고 힘으로 움직입니다. - 질량은
Mass (kg)과Mass Scale로, 감쇠는Linear Damping과Angular Damping으로, 표면은 물리적 재질의Friction과Restitution으로 정합니다. Add Force는 반복 호출하는 지속적인 힘,Add Impulse는 한 번의 충격,Add Torque in Radians는 회전력이며,Vel Change를 켜면 질량이 영향을 주지 않습니다.- 충돌 형상은
show collision과 Chaos Visual Debugger로 확인하고, PhysX용 명령은 UE5에서 그대로 쓰지 않습니다.
연습 문제
1. 같은 충격량의 속도 변화
본문의 조건(정지, 중력 없음, 감쇠 0, 다른 접촉 없음)에서 2 kg과 4 kg 바디에 Vel Change를 끈 채 X 방향 크기 400의 충격량을 한 번씩 주었습니다. 두 바디의 속도 변화는 각각 얼마이고, 몇 배 차이일까요?
해설 보기
속도 변화는 충격량을 질량으로 나눈 값이므로, 2 kg 바디는 400 / 2 = 200, 4 kg 바디는 400 / 4 = 100만큼 X 방향 속도가 바뀝니다. 언리얼 엔진의 길이 단위가 센티미터이므로 속도는 초당 센티미터로 읽습니다. 가벼운 바디의 변화가 정확히 두 배입니다.
이 계산은 중력과 감쇠, 접촉을 모두 뺀 조건에서만 성립합니다. 감쇠가 있으면 시간이 지나며 속도가 줄고, 바닥에 닿아 있으면 마찰이 더해지므로 이 비율이 그대로 유지되지 않습니다.
2. Vel Change를 켰을 때
같은 초기 조건에서 두 바디의 Add Impulse에 Vel Change를 켰습니다. 같은 벡터를 한 번 주었을 때도 가벼운 바디의 속도 변화가 두 배일까요? 시뮬레이션을 켜지 않은 메시에 이 비교를 그대로 적용해도 될까요?
해설 보기
두 배가 아닙니다. Vel Change를 켜면 입력을 충격량이 아니라 속도 변화로 다루므로 질량이 영향을 주지 않고, 두 바디에 같은 속도 변화가 적용됩니다.
다만 이 비교는 물리 바디가 실제로 시뮬레이션 중이라는 전제가 먼저 있어야 합니다. 시뮬레이션이 꺼진 메시에는 노드를 연결해 두어도 물리 계산으로 움직이지 않으므로 비교 자체가 성립하지 않습니다. 결과가 이상하다면 Target 메시, 시뮬레이션과 콜리전 설정, 처음 속도, 노드 옵션을 차례로 확인합니다.
3. 한 번만 호출한 Add Force
로켓 상자를 만들려고 BeginPlay에서 Add Force를 한 번 호출했는데, 상자가 거의 움직이지 않습니다. 같은 크기의 값을 Add Impulse에 넣으면 상자가 튀어 나갑니다. 왜 이런 차이가 생길까요? 로켓처럼 계속 밀고 싶다면 어떻게 해야 할까요?
해설 보기
Add Force는 힘이 유지되는 동안 반복해서 호출하는 노드라서, 한 번 호출하면 그 짧은 물리 스텝 동안만 작용합니다. 힘에 아주 짧은 시간을 곱한 만큼의 운동량만 더해지므로 거의 움직이지 않습니다. Add Impulse는 입력값 자체를 한 번의 충격량으로 주므로 같은 숫자라도 훨씬 큰 변화가 생깁니다.
로켓처럼 계속 밀려면 추진이 필요한 기간 동안 매 프레임 Add Force를 호출해야 합니다. 예를 들어 Tick에서 추진 중인지 확인하는 Boolean이 참일 때만 Add Force를 호출하고, 연료가 떨어지면 그 값을 거짓으로 바꾸는 식으로 만듭니다.
Add Impulse의 입력과 Vel Change의 의미는 언리얼 엔진 공식 문서의 Add Impulse 노드 설명에서 확인할 수 있습니다.
다음 글 콜리전 시스템 기본 개념에서는 물체끼리 막을지, 겹칠지, 무시할지를 정하는 콜리전 채널과 응답, 그리고 Hit와 Overlap 이벤트를 받는 조건을 살펴봅니다.