동적 환경 변화와 시뮬레이션
머티리얼 파라미터와 블루프린트를 연결해 날씨·시간 변화에 지형·수면·식생·조명이 함께 반응하도록 만듭니다.
시간과 날씨를 바꿨는데도 월드가 그대로라면 플레이어는 배경만 달라졌다고 느끼기 쉽습니다. 비가 오면 땅이 젖어 번들거리고, 눈이 오면 지붕에 눈이 쌓이고, 바람이 세지면 나무가 더 크게 흔들려야 세계가 날씨에 반응한다고 느낍니다.
이 글에서는 지면과 수면, 식물, 조명, 파티클이 날씨와 시간에 반응하게 만드는 방법을 살펴봅니다. 핵심은 재질 파라미터와 블루프린트를 연결해, 값 하나를 바꾸면 여러 재질이 함께 바뀌는 구조를 만드는 것입니다. 그리고 그렇게 바뀌는 것이 보이는 표면일 뿐인지, 충돌이나 마찰 같은 게임 플레이까지 바뀌는 것인지를 구분하는 기준도 함께 세웁니다.
환경이 변할 때 생기는 것
환경의 동적인 변화는 레벨의 상태를 시간과 입력, 게임 플레이 이벤트에 맞춰 바꾸는 설계 요소입니다. 시간과 날씨, 조명이 바뀔 때 월드도 함께 바뀌면, 레벨이 고정된 배경이 아니라 상태를 가진 공간처럼 보입니다.
이런 변화는 게임 플레이도 다양하게 만듭니다. 바뀌는 환경은 새로운 도전이나 전략적 기회, 숨겨진 길을 만들어 플레이를 덜 예측 가능하고 더 흥미롭게 합니다. 날씨와 시간의 변화를 이야기 속 사건과 연결하면 감정의 깊이를 더하거나 이야기의 진행에 영향을 줄 수도 있고, 같은 레벨이 매번 다른 경험을 주므로 다시 플레이할 가치도 높아집니다.
다만 동적인 변화를 만들 때는 어떤 이벤트에서 무슨 값이 바뀌고, 언제 원래 상태로 돌아오는지가 분명해야 합니다. 그렇지 않으면 비가 그쳤는데 땅이 계속 젖어 있거나, 날씨가 여러 번 바뀔수록 값이 이상하게 쌓이는 일이 생깁니다.
날씨에 반응하는 요소들
젖는 땅과 쌓이는 눈
여기서 다루는 젖음과 눈은 표면이 그렇게 보이게 하는 재질의 변화입니다. 랜드스케이프의 높이나 충돌을 실제로 바꾸거나, 물리적인 두께를 가진 눈을 만드는 것과는 다른 일이라는 점을 먼저 구분해 둡니다.
비가 올 때는 랜드스케이프 재질의 파라미터를 바꿔, 땅에 물이 고이거나 젖어서 번들거리는 모습을 만듭니다. 이를 위해 랜드스케이프 재질에 노멀 맵을 섞는 기능과 거칠기(Roughness)를 조절하는 기능을 넣습니다. 거칠기는 표면이 빛을 얼마나 흩뜨리는지를 나타내는 값으로, 0에 가까울수록 매끄러워 빛을 거울처럼 반사하므로 물에 젖은 것처럼 보입니다. 웅덩이는 노멀 맵으로 표면의 방향을 살짝 흔들고 거칠기를 0에 가깝게 만들어 표현합니다.
값을 넘기는 대상은 효과의 범위에 따라 고릅니다. 메시 하나에만 적용할 효과라면 그 메시에 동적 재질 인스턴스(Dynamic Material Instance)를 만들어 지정하고, 여러 랜드스케이프와 메시가 함께 쓰는 효과라면 재질 파라미터 컬렉션(MPC)을 씁니다. 그리고 날씨 상태에 따라 그 대상에 Set Scalar Parameter Value나 Set Vector Parameter Value로 값을 넘깁니다.
눈이 쌓이는 모습도 재질로 만듭니다. 스태틱 메시와 랜드스케이프의 재질에, 표면이 위를 향하는 정도나 월드 위치를 기준으로 눈 텍스처와 노멀을 섞는 계산을 넣습니다. 블루프린트에서는 눈이 오는 동안 SnowAmount 같은 파라미터를 조금씩 늘려 눈이 쌓이는 양을 흉내 냅니다. 눈 덮인 부분의 텍스처와 노멀, 빛이 표면 안으로 조금 스며들어 퍼지는 서브서피스 스캐터링(subsurface scattering) 값을 조절하면 눈의 질감이 살아납니다.
수면
레벨에 물이 있다면 날씨에 따라 물의 모습과 성질도 바꿀 수 있습니다. 비가 올 때는 수면에 잔물결을 더하고, 폭풍이 칠 때는 파도를 높입니다. 이 값은 쓰고 있는 물 웨이브 에셋과 재질, 전용 블루프린트가 노출한 값으로 조절합니다. 여기서 예로 드는 WaveHeight나 RippleAmount는 설명을 위한 이름이고, 모든 물 액터에 공통으로 있는 속성은 아닙니다.
특정 시간이나 홍수 같은 날씨에 맞춰 수위를 바꿀 수도 있습니다. 단순한 수면 메시라면 Z 위치를 보간해 높이를 바꿀 수 있습니다. 하지만 워터(Water) 플러그인의 워터 바디(Water Body)를 쓴다면, 그 유형이 실행 중의 갱신을 지원하는지와, 물 메시와 충돌, 부력 데이터도 함께 갱신되는지를 확인해야 합니다. 액터의 Z만 바꾸면 물과 관련된 모든 동작이 함께 맞춰진다고 가정하지 않습니다. 수위 변화는 물체가 뜨거나 플레이어가 헤엄치는 것처럼 복잡한 상호작용을 부를 수 있으므로, 초기 설계 단계에서 깊이 고려해야 합니다.
식물
나무와 풀 같은 식물도 날씨와 시간에 반응하게 만들 수 있습니다. 바람의 세기에 따라 식물이 흔들리는 정도를 바꾸는 것이 대표적입니다. Wind Directional Source 액터는 스피드트리(SpeedTree) 식물을 위한 기능입니다. 일반 식물 재질이 재질의 버텍스 위치를 움직이는 월드 포지션 오프셋(World Position Offset, WPO)으로 흔들린다면, 그 재질이 MPC의 바람 방향과 세기를 직접 읽도록 만듭니다. 천이나 물리 오브젝트를 바람에 움직이게 하려면, 재질과 별개로 힘을 주거나 시뮬레이션과 연결해야 합니다. 젖은 나뭇잎이나 눈 덮인 나뭇잎도 지면처럼 식물 재질에 비와 눈에 따른 변화를 적용해 만듭니다.
조명과 그림자
환경이 바뀔 때는 조명과 그림자도 함께 맞춰야 화면이 어울립니다. 구름 그림자가 땅 위를 흘러가게 하려면 구름 재질이 노출한 밀도와 이동 파라미터를 조절하고, 디렉셔널 라이트의 구름 그림자를 켭니다. 여기서도 Coverage나 Velocity 같은 이름이 모든 구름 액터에 공통으로 있는 속성은 아닙니다.
밤이 되면 가로등이 켜지거나 상점의 간판이 깜빡이게 할 수도 있습니다. 그 오브젝트에 붙은 포인트 라이트나 스포트 라이트의 Intensity를 시간 시스템 블루프린트에서 제어하면 됩니다.
파티클
날씨 시스템의 강수 파티클 말고도, 환경에 반응하는 파티클을 더할 수 있습니다. 비가 올 때 빗방울이 땅에 부딪혀 튀는 물방울이 대표적입니다. CPU에서 계산하는 나이아가라 이미터라면, 빗방울 이미터에 충돌(Collision)과 충돌 이벤트 생성을 넣고, 물방울 이미터에 이벤트 핸들러(Event Handler)를 연결해 충돌한 자리에 물방울을 만들 수 있습니다. 이벤트를 만들고 받는 설정은 간단한 이벤트 핸들러 설정에서 자세히 다룹니다. 충돌 모듈을 더하는 것만으로 다른 이미터가 저절로 생성되지는 않으며, 이 이벤트 경로는 GPU 시뮬레이션에는 그대로 적용되지 않습니다. 이 밖에 바람이 불 때 땅의 눈이 날리거나 안개가 한쪽으로 흘러가는 파티클을 더해 사실감을 높일 수도 있습니다.
재질 파라미터 컬렉션으로 한 번에 바꾸기
이런 동적인 변화는 대부분 날씨와 시간을 관리하는 블루프린트 안에서 함께 다룹니다. 그 중심에 있는 도구가 재질 파라미터 컬렉션(Material Parameter Collection, MPC)입니다. MPC는 여러 재질이 함께 읽는 값을 모아 둔 에셋으로, GlobalWetness, GlobalSnowAmount, WindStrength처럼 레벨 전체에 같이 적용할 값을 담기에 알맞습니다. 블루프린트에서 MPC의 값을 바꾸면, 그 값을 읽는 모든 재질이 한 번에 바뀝니다.
MPC를 쓰는 순서는 다음과 같습니다. 먼저 콘텐츠 브라우저를 오른쪽 클릭해 재질 관련 분류에서 Material Parameter Collection을 고릅니다. 메뉴의 분류 이름은 버전에 따라 다르므로, 보이지 않으면 검색으로 찾습니다. 그다음 MPC 에디터에서 Scalar Parameter나 Vector Parameter를 추가하고 이름을 붙입니다. 재질 에디터에서는 Collection Parameter 노드를 추가해 만든 MPC와 그 파라미터를 고르고, 출력을 실제 계산에 연결합니다. 마지막으로 블루프린트에서 MPC용 Set Scalar Parameter Value나 Set Vector Parameter Value 노드로 값을 바꿉니다.
값을 시간에 따라 부드럽게 바꾸려면 타임라인(Timeline)과 커브 에셋(Curve Asset)을 씁니다. 지형이 서서히 젖어 가거나 수위가 천천히 오르는 변화에 알맞습니다. 폭풍이 시작될 때 트리거 볼륨 안의 물체가 날아가거나 부서지게 하는 것처럼 물리적인 반응이 필요하다면, 충돌과 트리거 이벤트로 따로 연결합니다.
MPC가 영향을 주는 범위
SHARED MATERIAL INPUT · EXPLICIT CONNECTION
MPC 값을 읽도록 연결한 재질들이 함께 반응합니다
아래는 GlobalWetness를 지면·식물 재질에서 공유하는 연결 예시입니다. MPC에 값이 있다는 사실만으로 모든 재질이나 물리 상태가 자동으로 바뀌지는 않습니다.
MPC에 Scalar GlobalWetness를 정의한 뒤, 각 재질의 Collection Parameter로 그 값을 읽어 Roughness·노멀 블렌딩 등 실제 출력 계산에 연결합니다. 날씨 블루프린트에서는 해당 MPC의 값을 설정합니다. 같은 이름의 일반 Scalar Parameter만 두거나 MPC를 읽지 않는 재질은 이 공유 입력의 영향을 받지 않습니다.
분기선은 같은 입력을 읽는 관계이며 두 재질의 실행 순서를 뜻하지 않습니다. 개별 메시의 전용 효과는 생성·할당한 Dynamic Material Instance 등 별도 입력 경로로 구성합니다.
표면 표현과 게임플레이의 변화를 분리합니다
젖음·눈의 재질 변화는 지형 높이·충돌·캐릭터 마찰을 자동 변경하지 않습니다. Water Body의 물 메시·부력 갱신, 천·강체의 바람 힘, Niagara 충돌 이벤트도 각각 실제 지원 경로에 연결합니다.
위 그림은 GlobalWetness 하나를 지면 재질과 식물 재질이 함께 읽는 연결 예를 보여 줍니다. 왼쪽의 날씨 블루프린트가 MPC의 GlobalWetness 값을 정하고, MPC를 Collection Parameter로 읽어 실제 출력 계산에 연결한 지면 재질과 식물 재질에 같은 값이 전달됩니다. 그림의 설명처럼 갈라지는 화살표는 같은 값을 읽는 관계일 뿐, 두 재질이 실행되는 순서나 물리적인 마찰의 변경을 뜻하지 않습니다.
그림 가운데의 설명은 이 연결이 저절로 생기지 않는다는 점을 짚습니다. MPC에 Scalar GlobalWetness를 정의한 뒤, 각 재질에서 Collection Parameter로 그 값을 읽어 Roughness나 노멀 섞기 같은 실제 출력 계산에 이어야 합니다. 같은 이름의 일반 Scalar Parameter만 만들어 두었거나 MPC를 읽지 않는 재질은 이 값의 영향을 받지 않습니다. 메시 하나에만 줄 효과라면 동적 재질 인스턴스처럼 별도의 입력 경로를 씁니다.
그림의 오른쪽 아래 카드는 표면의 표현과 게임 플레이의 변화를 나누라고 말합니다. 젖음이나 눈의 재질 변화는 지형의 높이와 충돌, 캐릭터의 마찰을 저절로 바꾸지 않습니다. 워터 바디의 물 메시와 부력 갱신, 천이나 강체에 주는 바람의 힘, 나이아가라의 충돌 이벤트도 각각 실제로 지원하는 경로에 따로 연결해야 합니다.
정리하면, 각 표현이 저절로 바꾸지 않는 것은 다음과 같습니다.
| 표현 | 저절로 바뀌지 않는 것 |
|---|---|
| 젖음과 눈의 재질 | 지형의 높이, 충돌 형상, 캐릭터의 마찰 |
| 수면 메시의 이동 | 워터 바디의 부력, 충돌, 물 메시의 갱신 |
| 식물의 WPO | 나무의 충돌, 천과 강체에 주는 물리적인 힘 |
그러니 게임 플레이에 꼭 필요한 변화만 골라 별도의 규칙과 시뮬레이션에 연결합니다.
더 깊이: MPC의 한계와 구조를 바꿀 때의 비용
MPC에는 정해진 한계가 있습니다. 재질 파라미터 컬렉션 문서에 따르면 재질 하나가 참조할 수 있는 MPC는 최대 두 개이고, 컬렉션 하나에는 Scalar Parameter와 Vector Parameter를 각각 1024개까지 둘 수 있습니다. 문서는 두 개 가운데 하나는 게임 전체의 값에, 다른 하나는 레벨마다 다른 값에 쓰는 방식을 예로 듭니다. 그래서 날씨, 시간, 레벨의 특수 효과마다 MPC를 따로 만들면 한 재질이 이것들을 모두 읽지 못할 수 있으므로, 컬렉션을 어떻게 나눌지 처음부터 정해 둡니다.
컬렉션의 구조를 바꿀 때 드는 비용도 알아 둡니다. 컬렉션의 파라미터 개수를 바꾸면 그 컬렉션을 참조하는 모든 재질이 다시 컴파일되므로, 파라미터를 많이 더할 예정이라면 빈 맵에서 미리 한꺼번에 추가하는 편이 빠를 수 있습니다. 파라미터의 이름을 바꾸면 재질은 그대로 동작하지만, 그 파라미터를 쓰던 블루프린트 노드는 연결이 끊어지므로 노드의 Parameter Name을 다시 골라야 합니다. 반면 실행 중에 MPC의 값을 바꾸는 일은 여러 재질 인스턴스에 각각 파라미터를 설정하는 것보다 훨씬 효율적이라고 문서는 설명합니다.
첫 MPC 연습: 거칠기만 바꿔 보기
처음에는 표면의 Roughness 하나만 바꿔 봅니다. MPC에 GlobalWetness를 만들고 기본값을 0으로 둡니다. 재질에서 Collection Parameter로 이 값을 읽어 Lerp 노드의 Alpha에 연결하고, A에는 마른 상태의 거칠기 0.8을, B에는 젖은 상태의 거칠기 0.2를 예시 값으로 넣은 뒤, Lerp의 출력을 Roughness에 연결합니다. Lerp는 Alpha가 0이면 A를, 1이면 B를 내보내고, 그 사이에서는 A × (1 - Alpha) + B × Alpha로 둘을 섞습니다. 그래서 Alpha가 0 이상 1 이하일 때 Wetness가 0.5라면 0.8 × 0.5 + 0.2 × 0.5 = 0.5가 됩니다. 이 재질을 큐브에 지정하고, MPC의 값을 0과 1로 바꿔 가며 두 결과를 비교합니다.
블루프린트에서 이 값을 자동으로 바꿀 때는 노드를 정확히 골라야 합니다. Collection을 입력으로 받는 MPC용 Set Scalar Parameter Value를 고르고, 같은 컬렉션과 정확한 파라미터 이름을 지정합니다. 동적 재질 인스턴스를 Target으로 받는 같은 이름의 노드는 입력 대상이 다릅니다. 또 재질에 이름만 같은 일반 Scalar Parameter를 만들어 두면, 이 컬렉션의 값을 읽는 연결은 생기지 않습니다.
Wetness를 1로 바꿨는데 다른 메시 하나만 바뀌지 않는다면, 먼저 그 메시에 지정된 재질과, 그 재질에서 Collection Parameter의 출력이 실제로 연결되었는지를 확인합니다. 모든 메시를 하나씩 돌며 새 재질을 만들기 전에, 어떤 재질이 이 공유 값을 읽고 있는지부터 구분하는 것이 빠릅니다.
최적화와 현실적인 기준
동적인 환경 변화는 보기 좋은 만큼 비용도 큽니다. 그래서 Stat FPS, Stat Unit, ProfileGPU 같은 콘솔 명령으로 병목을 꾸준히 확인하고 개선합니다. 먼 곳의 오브젝트는 간단한 재질을 쓰거나 동적 효과를 끄는 것처럼 LOD와 컬링 설정을 적극적으로 활용합니다.
모든 환경 요소를 완벽하게 동적으로 만들 필요는 없습니다. 화면에서 가장 큰 영향을 주는 요소에 자원을 집중하고, 지나치게 복잡한 시뮬레이션보다는 게임의 아트 스타일에 맞는 수준의 변화를 만드는 것이 중요합니다.
정리
- 젖음과 눈은 재질의 거칠기와 노멀, 텍스처 섞기로 만드는 표면의 변화이며, 지형의 높이나 충돌, 마찰을 바꾸지 않습니다.
- 메시 하나의 효과는 동적 재질 인스턴스로, 여러 재질이 함께 쓰는 효과는 MPC로 값을 넘깁니다.
- 수위를 바꿀 때 워터 바디는 물 메시와 충돌, 부력의 갱신 지원을 따로 확인하고,
Wind Directional Source는 스피드트리용이며 일반 식물은 MPC의 바람 값을 읽게 만듭니다. - 나이아가라의 충돌 이벤트로 물방울을 만드는 경로는 CPU 이미터에서 이벤트 핸들러를 연결해야 하며, GPU 시뮬레이션에는 그대로 적용되지 않습니다.
- MPC는 Collection Parameter로 읽어 실제 출력에 연결한 재질에만 영향을 주고, 같은 이름의 일반 파라미터는 연결되지 않습니다.
- Lerp(A, B, Alpha)는
A × (1 - Alpha) + B × Alpha이며, 블루프린트에서는 MPC용Set Scalar Parameter Value를 골라야 합니다. - 게임 플레이에 꼭 필요한 변화만 별도의 규칙에 연결하고, 화면에 가장 큰 영향을 주는 요소에 비용을 집중합니다.
연습 문제
1. Wetness가 0.25일 때
앞의 재질에서 A = 0.8, B = 0.2이고, GlobalWetness가 0.25라면 Roughness는 얼마일까요? 이 값은 마른 상태와 젖은 상태 가운데 어느 쪽에 더 가깝게 보일까요?
해설 보기
Lerp는 A × (1 - Alpha) + B × Alpha이므로 0.8 × 0.75 + 0.2 × 0.25 = 0.6 + 0.05 = 0.65입니다.
0.65는 마른 상태의 0.8에 더 가까우므로, 표면이 아직 대체로 마른 듯 보이고 반사가 약간 강해진 정도입니다. 거칠기가 낮아질수록 빛이 거울처럼 반사되어 젖은 것처럼 보입니다.
2. 바뀌지 않는 메시 하나
MPC의 GlobalWetness를 1로 바꾸자 레벨의 땅과 바위가 모두 젖어 보이는데, 나무 상자 하나만 그대로 말라 보입니다. 상자의 재질에는 GlobalWetness라는 이름의 Scalar Parameter가 있습니다. 무엇이 문제일까요?
해설 보기
상자의 재질에 있는 것은 MPC를 읽는 Collection Parameter가 아니라, 이름만 같은 일반 Scalar Parameter일 가능성이 큽니다. 일반 파라미터는 MPC의 값과 연결되지 않으므로 MPC를 바꿔도 영향을 받지 않습니다.
상자 재질에서 일반 파라미터 대신 Collection Parameter 노드로 같은 MPC의 GlobalWetness를 읽고, 그 출력을 Roughness 계산에 실제로 연결합니다. 그래도 바뀌지 않는다면 상자에 지정된 재질이 정말 그 재질인지 확인합니다.
3. 눈은 쌓였는데 발이 빠지지 않는다
눈이 오는 동안 GlobalSnowAmount를 늘려 땅이 하얗게 덮이게 만들었습니다. 그런데 캐릭터는 눈 위를 걸어도 발이 빠지지 않고, 이동 속도도 그대로입니다. 왜 그럴까요?
해설 보기
눈이 쌓인 모습은 재질에서 텍스처와 노멀을 섞어 만든 표면의 변화일 뿐, 지형의 높이나 충돌, 캐릭터의 마찰을 바꾸지 않습니다. 그래서 캐릭터는 여전히 원래 지형의 충돌 위를 원래 속도로 걷습니다.
발이 빠지거나 느려지게 하려면, 눈이 오는 상태에서 캐릭터의 이동 속도를 낮추는 규칙을 따로 연결하거나, 발자국 같은 변형을 지원하는 별도의 방법을 써야 합니다. 이런 게임 플레이 변화가 꼭 필요한지 먼저 정하고, 필요한 것만 연결합니다.
재질 파라미터 컬렉션의 사용법은 Epic의 재질 파라미터 컬렉션 안내에서 확인할 수 있습니다.
다음 글 날씨 효과의 성능 최적화에서는 강수 파티클과 구름, 안개, 재질 파라미터 갱신처럼 날씨 효과가 만드는 비용을 측정하고 줄이는 방법을 다룹니다.