날씨 및 시간 시스템의 기초
Directional Light와 Sky Light·대기 효과를 시간에 따라 제어하고 비가 전환되는 날씨 시스템을 구성합니다.
지금까지는 오브젝트의 물리 상호작용과 환경 쿼리를 다뤘습니다.
이번에는 게임 세계의 생동감을 높이는 날씨 및 시간 시스템으로 확장합니다.
역동적인 낮/밤 주기와 기상 변화는 시각적 품질뿐 아니라 게임플레이에도 직접 영향을 줄 수 있습니다.
이번 절에서는 낮/밤 주기 시스템과 간단한 날씨 변화를 구현하는 기초 방법을 정리합니다.
날씨 및 시간 시스템이란 무엇인가?
날씨 및 시간 시스템(Weather & Time System)은 게임 월드의 환경 조명, 대기 효과, 기상 현상 등을 동적으로 변화시키는 메커니즘을 의미합니다.
- 낮/밤 주기(Day/Night Cycle): 태양과 달의 위치를 시간에 따라 변화시켜 월드의 조명을 동적으로 변경하고, 일출/일몰과 같은 시각적 전환을 제공합니다.
- 날씨 변화(Weather System): 비, 눈, 안개, 천둥 번개 등 다양한 기상 현상을 구현하여 환경에 변화를 주고, 게임플레이에 영향을 미치기도 합니다.
- 몰입감 증대: 현실 세계와 유사한 환경 변화는 플레이어의 몰입도를 크게 높입니다.
- 시각적 다양성: 동일한 레벨이라도 시간과 날씨에 따라 다르게 보이므로 시각적 지루함을 줄입니다.
-
게임플레이 변화
- 낮/밤: 밤에는 시야가 제한되어 은신 플레이를 유도하거나, 특정 적들이 밤에만 출현하도록 만들 수 있습니다.
- 날씨: 비가 오면 시야가 흐려지거나, 바닥이 미끄러워져 이동에 영향을 주거나, 특정 스킬의 효율이 변하는 등의 게임플레이 요소를 추가할 수 있습니다.
- 내러티브 강화: 특정 시간이나 날씨가 스토리에 중요한 배경이 될 수 있습니다.
낮/밤 주기 시스템 구현의 기초
낮/밤 주기는 주로 Directional Light (태양/달), Sky Light, Sky Atmosphere, Volumetric Cloud 액터들의 속성을 시간에 따라 변경하여 구현합니다.
필수 환경 액터 배치
템플릿과 레벨에 따라 배치 여부가 다르므로 다음 환경 액터를 확인하고 없는 것은 추가합니다.
이 액터들이 낮/밤 주기의 핵심 요소입니다.
Directional Light: 태양(또는 달)을 나타내는 광원입니다.Mobility:Movable로 설정되어 있어야 블루프린트에서 회전을 제어할 수 있습니다.Atmosphere Sun Light를 켜 Sky Atmosphere의 태양으로 사용합니다.Source Angle: 태양의 각 크기와 그림자 부드러움에 영향을 줍니다.
Sky Light: 하늘에서 오는 주변광을 캡처하여 월드를 비춥니다.Source Type:SLS Captured Scene으로 설정되어 있어야Sky Atmosphere와Volumetric Cloud의 색상 변화를 반영합니다.- Stationary 또는 Movable에서
Real Time Capture를 켜 동적으로 갱신합니다. 이 예제에서는 이 경로를 사용합니다.
Sky Atmosphere: 지구의 대기권을 시뮬레이션하여 하늘의 색상, 안개, 광원 산란 등을 구현합니다.Volumetric Cloud: 실시간으로 동적인 구름을 시뮬레이션합니다. (성능에 영향을 줄 수 있음)Exponential Height Fog: 안개를 시뮬레이션합니다. (선택 사항,Sky Atmosphere와 통합될 수 있음)
시간 시스템 블루프린트 생성
이 액터들을 제어할 블루프린트 액터를 생성합니다.
새 블루프린트 클래스 생성: Actor를 부모 클래스로 하는 새로운 블루프린트 BP_DayNightCycle을 생성합니다.
DirectionalLight(Directional Light Object Reference): 레벨에 있는 태양/달 광원 액터의 참조를 저장합니다.Instance Editable로 설정하여 레벨에 배치 후 직접 연결할 수 있도록 합니다.SkyLight(Sky Light Object Reference)SkyAtmosphere(Sky Atmosphere Object Reference)VolumetricCloud(Volumetric Cloud Object Reference)TimeOfDay(Float, 기본값 0.0, 범위 0.0~24.0): 현재 시간을 24시간 기준으로 나타냅니다.DayCycleSpeed(Float, 기본값 1.0): 낮/밤 주기의 속도 조절 (1.0 = 실제 시간과 동일, 높을수록 빠르게 변함).
Event Tick 활용)Event Tick에서TimeOfDay = FMod(TimeOfDay + DeltaSeconds * DayCycleSpeed / 3600.0, 24.0)으로 갱신합니다. TimeOfDay는 시간 단위이므로 초를 3600으로 나눕니다. 여기서는 음수가 아닌 속도를 사용합니다.FMod는 24시간을 넘은 나머지를 보존하므로 무조건 0으로 대입하는 것과 다릅니다.Update Sun Position함수 (커스텀 함수):DirectionalLight의 회전을 업데이트합니다.DirectionalLight의Set Actor Rotation노드를 호출합니다.TimeOfDay를 기반으로 태양의 Pitch(고도)와 Yaw(방위)를 계산합니다.- 단순 회전 예시:
Pitch = 90.0 - TimeOfDay * 15.0(6시 0도, 12시 -90도, 18시 -180도). 광선의 진행 방향을 기준으로 정오에 아래를 향하게 합니다. 위도·계절을 계산하는 실제 태양 위치 모델은 아닙니다. Yaw는TimeOfDay에 따라 변화시키거나 고정합니다.
- 단순 회전 예시:
Update SkyLight함수 (커스텀 함수):SkyLight의 설정을 업데이트합니다.- 앞에서 Real Time Capture를 켰으므로 Tick에서
Recapture Sky를 반복 호출하지 않습니다. 수동 캡처 방식을 선택한 경우에만 필요 시 Sky Light Component의 Recapture를 호출합니다. - Sky Light Component의
Set Intensity를 통해 시간별 주변광을 조절합니다.
- 앞에서 Real Time Capture를 켰으므로 Tick에서
Update SkyAtmosphere/Update VolumetricCloud: 필요에 따라 이 액터들의 특정 파라미터(예: 밀도, 색상, 고도)를TimeOfDay에 따라 조절하여 더욱 사실적인 낮/밤 변화를 구현합니다.
시간 갱신을 함수 호출까지 연결하기
Tick의 실행 선은 TimeOfDay 저장 → 유효한 DirectionalLight 확인 → Update Sun Position → 선택한 주변광 갱신으로 이어 줍니다. 순수 계산 핀을 배치한 것만으로 저장이나 회전 적용이 실행되지는 않습니다. 아직 연결하지 않은 환경 액터의 참조는 먼저 확인하고 해당 선택 갱신을 건너뜁니다.
예시 시간 단위를 맞춰 하루 경계 넘기기
TimeOfDay=23.5, DeltaSeconds=60, DayCycleSpeed=60인 한 갱신에서는 60 × 60 ÷ 3600 = 1시간을 더합니다. 24.5를 24로 순환하면 0.5시간이며, 단순 태양식의 Pitch는 90 - 0.5 × 15 = 82.5도입니다. 실제로 60초가 한 프레임에 걸렸다는 주장이 아니라, 입력과 단위가 주어진 계산 사례입니다. 속도 60은 게임 시간이 실제 시간의 60배로 흐르는 조건입니다.
레벨에 배치 및 연결
BP_DayNightCycle 액터를 레벨에 배치합니다.디테일(Details) 패널: BP_DayNightCycle을 선택하고, 미리 생성한 변수 슬롯에 레벨의 Directional Light, Sky Light, Sky Atmosphere, Volumetric Cloud 액터들을 드래그 앤 드롭하여 연결합니다.
간단한 날씨 변화 구현의 기초 (비 예시)
날씨 시스템은 파티클 시스템(Niagara/Cascade)과 오디오, 그리고 환경 액터의 변화를 통해 구현됩니다.
날씨 시스템 블루프린트 생성
이 액터는 날씨의 종류와 강도를 제어합니다.
새 블루프린트 클래스 생성: Actor를 부모 클래스로 하는 BP_WeatherManager를 생성합니다.
CurrentWeather(Enum, 예:EWeatherType::Clear,EWeatherType::Rain,EWeatherType::Snow): 현재 날씨 상태.RainParticleSystem(Niagara System Object Reference): 이 예제의 비 효과 에셋입니다. Cascade Particle System과는 다른 타입입니다.RainSound(Sound Base Object Reference): 비 소리 오디오 큐.RainIntensity(Float, 0.0~1.0): 비의 강도.
BP_WeatherManager에Niagara Component와Audio Component를 추가하고Auto Activate를 해제합니다.BP_DayNightCycle참조도 받아 시간 조명에 곱할 날씨 계수를 전달합니다. 같은 광원 값을 두 액터의 Tick에서 서로 덮어쓰지 않도록 최종 조명 적용은 DayNightCycle 한 곳이 맡습니다.
날씨 변화 로직 구현
SetWeather 함수 (커스텀 함수)
Input:NewWeatherType(EWeatherType Enum),Intensity(Float)-
로직
CurrentWeather = NewWeatherType,RainIntensity = Clamp(Intensity, 0, 1)을 먼저 저장하고Switch on EWeatherType로 분기합니다. 여기서는 Rain/Clear를 구현하며 Snow는 별도 효과가 준비되기 전에는 선택하지 않습니다.-
Rain일 때- Niagara Component의
Set Asset에RainParticleSystem을 연결하고Activate를 호출합니다. Cascade를 별도로 사용한다면 Particle System Component의Set Template경로로 구성해야 합니다. Audio Component의Set Sound노드를 사용하여RainSound를 설정하고Play노드를 호출합니다.- Niagara 에셋에
User.RainIntensity를 만들고 스폰율에 연결한 뒤,Set Niagara Variable (Float)로RainIntensity를 전달합니다. 이름만 설정해도 기존 에셋의 비의 양이 자동으로 변하는 것은 아닙니다. - DayNightCycle에 날씨 계수를 전달해 Directional Light Component의 강도를 조절합니다. Sky Atmosphere에 일반적인
Intensity속성이 있다고 가정하지 않습니다. PostProcess Volume의Exposure또는Color Grading을 조절하여 날씨에 맞는 분위기를 연출합니다.
- Niagara Component의
-
Clear일 때Niagara Component와Audio Component를Deactivate또는Stop합니다.- 조명을 원래대로 복원합니다.
- 부드러운 전환이 필요하면 이벤트 그래프의 커스텀 이벤트에서 Timeline을 시작하고, 그 Update가 현재 계수를 적용하는 함수를 호출하게 합니다. 일반 함수 내부에 Timeline을 넣지 않습니다.
- 날씨 전환 타이머:
Set Timer by Event에는 입력 없는 콜백을 연결합니다. 콜백이 날씨·강도를 선택한 뒤 인자가 있는SetWeather를 호출하도록 구성합니다.
날씨 계수를 전달하는 최소 연결
BP_DayNightCycle에 Float WeatherLightFactor를 만들고 기본값을 1로 둡니다. 시간별 BaseSunIntensity는 선택한 광원의 같은 강도 단위로 구한 기본값입니다. 입력 Float를 받아 계수를 저장하는 커스텀 함수 SetWeatherLightFactor를 만들고, BP_WeatherManager의 Instance Editable 참조에 레벨의 DayNightCycle 인스턴스를 연결합니다.
Rain 분기는 Lerp(1.0, 0.4, RainIntensity)를 그 함수에 전달하고 Clear는 1을 전달하도록 정했다고 가정합니다. 이는 이 실습의 조명 디자인 선택이며 실제 날씨의 보편적 물리식은 아닙니다. DayNightCycle의 최종 갱신에서 BaseSunIntensity × WeatherLightFactor를 계산한 뒤 Directional Light Component의 Set Intensity로 적용합니다. 시간 기본값이 10이고 RainIntensity가 1이면 계수 0.4로 최종 4, Clear로 바꾸면 계수 1로 최종 10입니다. 이전 비 상태의 최종값 4를 다시 기본값으로 곱하지 않습니다.
스스로 확인하기
TimeOfDay=23.75, DeltaSeconds=30, DayCycleSpeed=120인 한 갱신의 새 시간과 단순 Pitch를 계산하세요. 그 시점의 기본 강도가 8이고 RainIntensity가 0.5라면 위 계수와 최종 강도는 얼마인가요? Clear로 바뀐 뒤 무엇을 복원해야 할까요?
시간·날씨 입력과 적용 지점을 나누어 풀이
추가 시간은 30 × 120 ÷ 3600 = 1이므로 새 시간은 0.75, Pitch는 90 - 0.75 × 15 = 78.75도입니다. 날씨 계수는 1 + (0.4 - 1) × 0.5 = 0.7, 최종 강도는 8 × 0.7 = 5.6입니다. Clear는 계수를 1로 복원하므로 같은 기본 강도 조건에서 8을 적용합니다. 시간은 계속 바뀔 수 있으므로 오래전에 저장한 최종 강도를 복원하는 대신, 현재 시간의 기본값과 현재 계수를 한 적용 지점에서 결합합니다.
레벨에 배치 및 초기 설정
BP_WeatherManager 액터를 레벨에 배치합니다.디테일 패널: RainParticleSystem과 RainSound 변수에 적절한 에셋을 연결합니다. 템플릿에 적합한 에셋이 없다면 직접 준비하고, 사용자 파라미터와 반복 재생 설정을 확인합니다.
TIME · WEATHER · ONE APPLICATION POINT
시간과 날씨의 입력을 합쳐 조명은 한 곳에서 적용합니다
두 관리 액터가 각각 같은 광원 값을 설정하면 서로의 결과를 덮어쓸 수 있습니다. 본문처럼 날씨는 계수를 전달하고, DayNightCycle이 시간과 결합해 최종 조명을 적용합니다.
입력 A · DayNightCycle의 시간
DeltaSeconds × DayCycleSpeed를 3600으로 나눠 시간 단위로 더합니다. FMod(..., 24)는 넘친 나머지를 유지합니다.
- 단순 수치 예
- 23.9시간 + 0.2시간 = 24.1시간
- 24시간으로 순환한 결과
- 0.1시간 · 무조건 0으로 초기화하지 않습니다.
TimeOfDay로 태양 회전과 시간별 기본 조명 강도를 구합니다.
입력 B · WeatherManager의 상태
Rain/Clear와 Clamp한 RainIntensity를 저장합니다. 날씨 계수를 DayNightCycle에 전달합니다.
- Rain
- 준비한 Niagara·오디오를 활성화하고 User.RainIntensity를 실제 스폰율에 연결합니다.
- Clear
- 비 효과·소리를 멈추고 날씨 계수를 복원합니다.
두 액터의 Tick이 같은 Light 강도를 각각 덮어쓰지 않게 합니다.
최종 적용 · DayNightCycle 한 곳
결합 예시: 시간별 기본 강도 × 날씨 계수 → Directional Light Component의 최종 강도
태양 회전과 주변광도 이 제어 경로에서 갱신합니다. 이 예제는 Sky Light의 Real Time Capture를 켜며, Tick마다 Recapture Sky를 반복 호출하지 않습니다.
기준 상태와 각 클라이언트의 표현을 나눕니다
멀티플레이에서는 서버가 기준 시간·날씨·강도를 결정해 복제합니다. 각 클라이언트는 그 상태에서 조명과 Niagara 표현을 갱신합니다. 액터 Replicates만 켜서 모든 환경 속성이 자동 동기화되지는 않습니다.
90 − TimeOfDay × 15 회전은 본문의 단순 모델입니다. 실제 위도·계절의 태양 위치 계산을 뜻하지 않습니다.
고급 고려사항
- 성능: 파티클 시스템, 볼류메트릭 클라우드, 스카이 애트모스피어 등은 성능에 큰 영향을 미칠 수 있습니다. 저사양 시스템을 고려하여 최적화에 신경 써야 합니다.
- 블렌딩: 날씨 변화를 부드럽게 만들기 위해 FInterp To, Lerp, 타임라인 등을 사용하여 시간에 따라 파라미터 값을 서서히 변경하는 것이 중요합니다.
- 네트워크 동기화: 서버가 기준 시간·날씨·강도를 결정하고 GameState 또는 복제 관리 액터의 상태로 전달합니다. 각 클라이언트가 그 값에서 로컬 조명·Niagara 표현을 갱신합니다. 액터의 Replicates만 켠다고 파티클과 모든 환경 속성이 자동 동기화되지는 않습니다.
-
게임플레이 연동
- 이동 속도 감소: 비가 오면 캐릭터의 이동 속도나 차량의 마찰력을 줄입니다.
- 시야 감소: 안개나 밤에는 플레이어의 시야 범위나 AI의 감지 거리를 줄입니다.
- 환경 효과: 비가 오면 물웅덩이가 생기거나, 젖은 표면의 셰이더가 활성화되도록 합니다.
- 데이터 테이블: 복잡한 날씨 시스템의 경우, 날씨 상태별 파라미터(조명 강도, 파티클 스폰율, 사운드 볼륨 등)를 데이터 테이블로 관리하면 유연하게 조절할 수 있습니다.
날씨 및 시간 시스템은 조명, 안개, 구름, 파티클, 게임플레이 상태를 함께 바꾸는 환경 제어 구조입니다.
시각 변화와 게임플레이 반응을 같은 기준 변수로 묶으면 관리가 쉬워집니다.
이번 절에서는 언리얼 엔진에서 낮/밤 주기 시스템과 간단한 날씨 변화를 구현하는 기초적인 방법, 그리고 관련 환경 액터들의 역할에 대해 알아보았습니다.
동적인 환경 변화는 게임의 몰입도를 크게 향상시킵니다.