물리 시뮬레이션은 실제 세계의 연속적인 물리 현상을 컴퓨터가 일정한 시간 간격으로 근사하여 계산하는 과정이다.
현실에서는 물리량이 시간에 따라 연속적으로 변하지만, 컴퓨터는 무한히 작은 시간 간격을 계산할 수 없다.
따라서
연속적인 물리 법칙 -> 시간 구간으로 분할 -> 매 Time Step마다 상태 계산 -> 다음 상태로 갱신
하는 방식으로 시뮬레이션한다.
핵심은 결국 미분방정식을 어떻게 시간에 따라 수치적으로 풀 것인가에 있다.
연속 시간과 이산 시간
현실의 물리 현상은 기본적으로 연속 시간(Continuous Time)에서 발생한다.
예를 들어 위치 x와 속도 v는 시간에 따라 연속적으로 변한다.
x(t)
v(t)
그리고
v = dx/dt
a = dv/dt
이다.
하지만 컴퓨터 시뮬레이션에서는 모든 순간을 계산할 수 없다.
따라서 특정 시간 간격마다 상태를 계산한다.
t_0 -> t_1 -> t_2 -> t_3 -> ...
이것이 이산 시간(Discrete Time)이다.
결국
현실 -> 연속 시간
컴퓨터 시뮬레이션 -> 이산 시간
이라고 볼 수 있다.
Time Step
Time Step Δt는 한 번의 물리 계산에서 시간이 얼마나 진행되는지를 나타낸다.
예를 들어
Δt = 0.02 s
라면 한 번 계산할 때마다 물리 시간이 0.02초 진행된다.
기본적인 시뮬레이션 구조는
현재 상태 -> 물리 계산 -> Δt만큼 진행 -> 다음 상태
이다.
Time Step이 작으면 일반적으로 더 정확한 계산이 가능하지만 계산량이 증가한다.
Δt 감소 -> 정확도 증가 / 계산량 증가
반대로
Δt 증가 -> 계산량 감소 / 수치 오차 증가 / 불안정 가능성 증가
한다.
Fixed Time Step
Fixed Time Step은 물리 계산의 시간 간격을 항상 일정하게 유지하는 방식이다.
예를 들어
Δt = 0.02 s
를 사용한다면 모든 물리 업데이트를 동일한 시간 간격으로 계산한다.
0.00 -> 0.02 -> 0.04 -> 0.06 -> ...
이 방식은 물리 시뮬레이션에서 중요하다.
프레임 렌더링 시간은 컴퓨터 성능에 따라 계속 변할 수 있기 때문이다.
예를 들어 렌더링 프레임이
16 ms -> 18 ms -> 12 ms -> 25 ms
처럼 변하더라도 물리 계산은
20 ms -> 20 ms -> 20 ms -> 20 ms
로 유지할 수 있다.
따라서
Render Frame Rate != Physics Time Step
으로 분리하는 것이 일반적이다.
게임에서는
렌더링 -> 가변 프레임
물리 -> 고정 시간 간격
구조를 사용하는 경우가 많다.
수치 적분
물리 시뮬레이션에서 가장 중요한 개념 중 하나다.
물리 법칙은 대부분 미분방정식 형태로 표현된다.
예를 들어
F = ma
에서
a = dv/dt
이므로
dv/dt = F/m
이다.
하지만 컴퓨터는 일반적인 상황에서 이 미분방정식의 정확한 해를 직접 구하기 어렵다.
따라서 현재 상태에서 다음 상태를 근사 계산한다.
이 과정을 수치 적분(Numerical Integration)이라고 한다.
기본 흐름은
힘 -> 가속도 -> 속도 변화 -> 위치 변화
이다.
Euler Integration
가장 단순한 수치 적분 방법이다.
현재 시점의 속도와 가속도를 사용하여 다음 상태를 예측한다.
속도는
v_next = v + aΔt
위치는
x_next = x + vΔt
로 계산한다.
구조는
현재 상태 -> 현재 가속도 계산 -> 속도 갱신 -> 위치 갱신
이다.
장점
구현이 매우 간단하다.
O(1) 계산
으로 상태를 갱신할 수 있으며 이해하기도 쉽다.
단점
수치 오차가 누적된다.
특히 스프링이나 충돌처럼 민감한 시스템에서는 Time Step이 크면 불안정해질 수 있다.
Δt 증가 -> 오차 증가 -> 불안정 가능성 증가
Semi-Implicit Euler
Semi-Implicit Euler는 게임 물리에서 매우 중요한 적분 방식이다.
먼저 속도를 갱신하고, 갱신된 속도를 이용하여 위치를 갱신한다.
v_next = v + aΔt
x_next = x + v_nextΔt
일반적인 Euler와 위치 계산 순서가 다르다.
Euler는
위치 -> 현재 속도 사용
Semi-Implicit Euler는
속도 갱신 -> 갱신된 속도로 위치 계산
이다.
이 작은 차이가 물리 시뮬레이션의 안정성에 큰 영향을 준다.
특히
스프링
중력
충돌
강체
등의 시뮬레이션에서 단순 Euler보다 안정적인 경우가 많다.
게임 엔진의 실시간 물리 계산에서 매우 흔하게 사용되는 방식이다.
Euler와 Semi-Implicit Euler 비교
두 방법의 차이는 위치 갱신에 어떤 속도를 사용하느냐이다.
Euler
v_next = v + aΔt
x_next = x + vΔt
Semi-Implicit Euler
v_next = v + aΔt
x_next = x + v_nextΔt
둘 다 속도 업데이트는 동일하지만 위치 업데이트가 다르다.
결과적으로 Semi-Implicit Euler가 에너지 보존 특성과 안정성 측면에서 더 좋은 경우가 많다.
특히 진동 시스템에서는 차이가 크게 나타날 수 있다.
Verlet Integration
Verlet Integration은 위치 기반으로 물리 상태를 적분하는 방법이다.
기본적인 Verlet 형태는
x_next = 2x - x_prev + aΔt²
이다.
현재 위치와 이전 위치를 이용하여 다음 위치를 계산한다.
이전 위치 + 현재 위치 + 가속도 -> 다음 위치
가 되는 구조다.
속도를 직접 저장하지 않는 기본 Verlet도 존재하며, 속도는 위치 차이로 근사할 수 있다.
v ≈ (x_next - x_prev)/(2Δt)
Verlet은 위치 제약을 다루는 시스템에서 특히 유용하다.
예를 들어
천 시뮬레이션
로프
입자 시스템
제약 기반 물리
등에서 활용된다.
Runge-Kutta
Runge-Kutta(RK)는 한 Time Step 안에서 여러 지점의 미분값을 평가하여 더 정확한 다음 상태를 계산하는 방법이다.
대표적인 것이 RK4다.
Euler가
현재 시점의 기울기 -> 다음 상태 예측
을 사용하는 반면,
RK4는 한 Time Step 안에서 여러 번 기울기를 평가한다.
개념적으로
현재 상태 -> k1
중간 상태 -> k2
중간 상태 -> k3
다음 상태 -> k4
를 계산한 후 이를 가중 평균한다.
RK4의 핵심은
한 번의 단순한 기울기 평가 -> 여러 기울기 평가 -> 더 정확한 적분
이다.
정확도는 높지만 계산량도 증가한다.
따라서 실시간 게임 물리 전체에 무조건 RK4를 사용하는 것이 좋은 것은 아니다.
적분 방법 비교
| 방법 | 특징 | 장점 | 단점 |
|---|---|---|---|
| Euler | 현재 상태의 미분값 사용 | 단순하고 빠름 | 오차와 불안정성 |
| Semi-Implicit Euler | 속도 먼저 갱신 | 게임 물리에 적합 | 고정밀 적분에는 한계 |
| Verlet | 이전/현재 위치 사용 | 위치 제약에 유리 | 일반적인 속도 기반 시스템에는 추가 처리 필요 |
| RK4 | 여러 지점 평가 | 높은 정확도 | 계산량 증가 |
핵심적인 선택은
단순성 -> Euler
실시간 게임 물리 -> Semi-Implicit Euler
위치/제약 중심 -> Verlet
높은 적분 정확도 -> RK4
정도로 이해하면 된다.
수치 오차
컴퓨터에서 수치 적분은 실제 해를 근사하기 때문에 오차가 발생한다.
대표적으로 절단 오차(Truncation Error)와 반올림 오차(Round-off Error)가 있다.
절단 오차
수학적으로 존재하는 항들을 일부 생략하면서 발생하는 오차다.
Euler는 낮은 차수의 근사이기 때문에 Time Step이 커질수록 오차가 커진다.
Δt 증가 -> 근사 오차 증가
반올림 오차
컴퓨터가 실수를 무한한 정밀도로 저장할 수 없기 때문에 발생한다.
예를 들어 부동소수점 연산에서는 아주 작은 오차가 계속 발생할 수 있다.
반복적인 물리 계산에서는 이러한 오차가 누적될 수 있다.
오차의 누적
물리 시뮬레이션에서는 한 번의 계산 오차보다 시간이 지나면서 오차가 어떻게 누적되는가가 중요하다.
예를 들어 이상적인 시스템에서 에너지가 일정해야 하는데
E_0 -> E_1 -> E_2 -> E_3 -> ...
하면서 계속 증가한다면 시스템이 실제 물리와 다르게 폭주할 수 있다.
반대로 에너지가 지나치게 감소하면 물체의 움직임이 빠르게 죽어버릴 수 있다.
따라서 수치 적분에서는
정확도
뿐만 아니라
에너지 거동
안정성
오차 누적
을 함께 봐야 한다.
안정성
수치 안정성(Numerical Stability)은 작은 계산 오차가 시간이 지나면서 폭발적으로 증가하지 않는 성질이다.
물리 시뮬레이션에서는 매우 중요하다.
특히
스프링
충돌
고속 물체
큰 질량 차이
강한 힘
등에서 안정성이 문제가 되기 쉽다.
예를 들어 Time Step이 지나치게 크면
큰 Δt -> 큰 상태 변화 -> 적분 오차 증가 -> 에너지 폭주 -> 시뮬레이션 불안정
이 발생할 수 있다.
대표적인 증상은
물체가 갑자기 튐
스프링이 폭발함
충돌 후 속도가 비정상적으로 증가함
물체가 지면을 뚫음
시뮬레이션이 NaN으로 오염됨
등이다.
Time Step과 안정성
Time Step은 단순히 “업데이트 빈도”가 아니다.
물리 시스템의 특성에 따라 안정적으로 사용할 수 있는 시간 간격의 범위가 존재한다.
예를 들어 매우 강한 스프링은
k 증가 -> 시스템 변화 속도 증가 -> 더 작은 Δt 필요
가 될 수 있다.
반대로 변화가 느린 시스템은 상대적으로 큰 Time Step을 사용할 수 있다.
따라서
물리 시스템의 시간 스케일 -> 적절한 Δt 결정
이라는 관점이 중요하다.
Fixed Time Step과 프레임
게임에서 렌더링과 물리 계산의 시간 간격을 분리하면 구조가 깔끔해진다.
예를 들어 렌더링 프레임은
Frame -> Frame -> Frame -> Frame
으로 실행되지만 물리 계산은
Physics -> Physics -> Physics -> Physics
고정된 Δt로 실행한다.
프레임이 너무 오래 걸리면 한 프레임에서 여러 번 물리 Step을 수행할 수도 있다.
실제 경과 시간 -> Physics Step 누적 -> Δt만큼 반복 계산
이 방식은 프레임 속도가 변해도 물리 시간의 진행을 일정하게 유지하는 데 유리하다.
다만 프레임이 지나치게 느려지면 물리 계산량이 폭증하는 문제가 생길 수 있다.
이를 흔히 Spiral of Death라고 한다.
성능 저하 -> Physics Step 증가 -> 계산량 증가 -> 더 큰 성능 저하
라는 악순환이다.
실제 엔진에서는 물리 Step 수에 제한을 두는 등의 방법으로 방어한다.
물리 시뮬레이션의 기본 루프
가장 기본적인 구조는 다음과 같다.
현재 상태 -> 힘 계산 -> 가속도 계산 -> 수치 적분 -> 다음 상태
뉴턴의 운동 법칙을 적용하면
F -> a = F/m
이후 적분을 통해
a -> v
v -> x
를 계산한다.
전체적으로
Force -> Acceleration -> Integration -> Velocity -> Position
이다.
게임 물리의 실제 구조
실제 게임 물리 엔진에서는 단순히 적분만 하는 것이 아니다.
대략적으로
입력/외력 -> 힘 계산 -> 충돌 검출 -> 접촉 제약 -> 충돌 해결 -> 속도 적분 -> 위치 적분 -> 상태 갱신
과 같은 여러 단계가 연결된다.
특히 충돌과 접촉이 들어오면 단순한 미분방정식만으로 해결되지 않는다.
연속적인 운동 + 이산적인 충돌 이벤트 + 접촉 제약
을 함께 처리해야 한다.
핵심 정리
연속 시간 -> 현실의 물리 현상
이산 시간 -> 컴퓨터가 계산하는 물리 시간
Time Step -> Δt
Fixed Time Step -> 일정한 Δt로 물리 계산
수치 적분 -> 미분방정식을 이산 시간에서 근사적으로 계산
Euler -> 현재 미분값으로 다음 상태 계산
Euler -> v_next = v + aΔt
Euler -> x_next = x + vΔt
Semi-Implicit Euler -> 속도를 먼저 갱신한 후 위치 갱신
Semi-Implicit Euler -> v_next = v + aΔt
Semi-Implicit Euler -> x_next = x + v_nextΔt
Verlet -> 이전 위치와 현재 위치를 이용하여 다음 위치 계산
Verlet -> x_next = 2x - x_prev + aΔt²
RK4 -> 한 Time Step에서 여러 기울기를 평가하여 적분
수치 오차 -> 근사와 부동소수점 연산에서 발생
Δt 증가 -> 일반적으로 수치 오차 증가
안정성 -> 오차가 시간에 따라 폭발하지 않는 성질
강한 힘/빠른 변화 -> 작은 Δt 필요
렌더링 시간 != 물리 Time Step
전체 구조는 다음과 같이 정리할 수 있다.
물리 법칙 -> 미분방정식 -> 수치 적분 -> 이산 시간 상태 -> 다음 상태
게임에서는
Render Frame -> Fixed Physics Step -> Physics Simulation -> State Update
가 기본적인 구조다.
그리고 적분기의 선택은
Euler -> 단순하지만 불안정할 수 있음
Semi-Implicit Euler -> 게임 물리에 적합한 기본 선택
Verlet -> 위치/제약 기반 시스템에 유리
RK4 -> 높은 정확도 대신 높은 계산량
으로 정리할 수 있다.
결국 물리 시뮬레이션의 본질은 연속적인 물리 법칙을 컴퓨터가 처리할 수 있는 이산적인 시간 단계로 변환하고, 수치 적분을 통해 매 순간의 상태를 근사적으로 갱신하는 것이다. 정확한 물리 법칙을 구현하는 것만으로 충분하지 않다. Time Step, 적분 방법, 오차 누적, 안정성까지 함께 설계해야 실제로 사용할 수 있는 시뮬레이션이 된다.