내일배움캠프 76일차 TIL
Unity 2D 환경에서 시간의 흐름을 시뮬레이션하는 시스템, 바로 TimeManager를 만들었다! 단순히 시간만 가는 게 아니라, 시간에 따라 조명 색상이 자연스럽게 바뀌고, 슬라임 게이지, 날씨, 작물 성장 같은 다른 여러 시스템들과 유기적으로 연동될 수 있는 핵심 기반을 다졌다.
게임 내 시간 흐름 구현
현실 세계의 1초가 게임 내에서는 몇 분이 될지 timeScale 값으로 조절할 수 있게 했다.
(예를 들어 timeScale = 60이면 현실 1초가 게임 1분이 된다!)
하루를 86400초 (24시간 × 60분 × 60초) 기준으로 구성해서 정확하게 시간이 흘러가도록 했다.
시간대(TimeOfDay) 구분
하루 중 시점에 따라 총 다섯 가지 시간대로 나눴다.
- Dawn (05~09시): 새벽
- Morning (09~12시): 아침
- Noon (12~17시): 낮
- Evening (17~21시): 저녁
- Night (나머지 시간): 밤
이 시간대 구분은 나중에 조명 색상 변경이나 다른 시스템들이 조건에 따라 다르게 작동하도록 분기할 때 아주 유용하게 쓸 수 있다.
2D 조명(Global Light2D) 제어
Unity의 URP(Universal Render Pipeline)와 2D Renderer를 사용하고 있어서, Global Light2D의 색상을 부드럽게 바꿀 수 있었다.
AnimationCurve를 사용해서 시간에 따른 밝기 변화 곡선을 만들고, Color.Lerp 함수를 사용해서 낮 색상과 밤 색상 사이를 점진적으로 섞이도록 했다. 이 덕분에 낮에서 밤으로 넘어갈 때 조명 색상이 뚝뚝 끊기지 않고 마치 실제처럼 자연스럽게 변하는 것을 보니 정말 만족스러웠다.
주요 구조 및 구성 요소
| 항목 | 설명 |
| time | 현재 게임 내 시간 (초 단위) |
| timeScale | 시간 흐름의 배속 조절 값 (기본 60: 현실 1초 = 게임 1분) |
| days | 게임이 며칠째 진행 중인지 카운트 |
| Hours, Minutes | time 값을 시/분 단위로 변환해주는 속성 (읽기 전용) |
| TimeOfDay | enum으로 새벽, 아침, 낮, 저녁, 밤 시간대를 정의 |
| lightCurve | AnimationCurve 에셋: 시간에 따라 조명 밝기(0~1)를 조절하는 곡선 |
| dayLightColor, nightLightColor | 낮과 밤의 대표 조명 색상 |
| globalLight.color | 현재 적용 중인 2D 조명의 색상 (실제 변경되는 부분) |
▶ 시간 흐름 처리: 매 프레임 Time.deltaTime에 timeScale을 곱해서 time 변수에 계속 더해줬다.
time += Time.deltaTime * timeScale;
▶ 빛 색상 변화: lightCurve에서 현재 시간에 해당하는 밝기 값을 가져와서 Color.Lerp로 색을 보간했다.
float curve = lightCurve.Evaluate(Hours); // 현재 시간에 해당하는 곡선 값(밝기)
Color lightColor = Color.Lerp(dayLightColor, nightLightColor, curve); // 낮-밤 색상 사이를 보간
globalLight.color = lightColor; // 실제 2D 조명 색상에 적용
▶ 시간대 자동 갱신: 현재 시(hour) 값에 따라 currentTimeOfDay enum 값을 자동으로 업데이트하도록 했다.
if (hour >= 5f && hour < 9f) currentTimeOfDay = TimeOfDay.Dawn; // 새벽
// ... 나머지 시간대들도 비슷한 방식으로 분기 처리했다.
다른 시스템과 연동하기
이 TimeManager가 중심이 되어서 다른 시스템들이 시간 흐름에 맞춰 작동할 수 있는 예시들을 고민해봤다.
슬라임 게이지 연동 예시: 우리가 얘기했던 대로, 밤에만 슬라임 게이지가 자연 소모되도록 할 수 있다.
if (TimeManager.Instance.CurrentTimeOfDay == TimeOfDay.Night)
{
DrainSlimeGauge(); // 밤에만 슬라임 게이지가 서서히 줄어드는 로직
}
날씨 시스템 연동 예시: 하루가 지나면 날씨를 새롭게 정하는 방식으로 활용할 수 있다.
if (TimeManager.Instance.Days != previousDay)
{
SetRandomWeather(); // 새로운 날이 되면 랜덤 날씨를 적용
previousDay = TimeManager.Instance.Days;
}
작물 성장/몬스터 스폰 예시: 시간대별로 작물이 자라거나 특정 몬스터가 스폰되도록 만들 수 있다.
if (TimeManager.Instance.CurrentTimeOfDay == TimeOfDay.Morning)
{
GrowCrops(); // 아침이 되면 작물이 성장
}
if (TimeManager.Instance.CurrentTimeOfDay == TimeOfDay.Night)
{
SpawnNocturnalMonsters(); // 밤이 되면 야행성 몬스터 스폰
}
느낀 점
TimeManager는 단순한 시간 처리 이상으로, 게임 내 여러 시스템을 유기적으로 연결할 수 있는 중심 허브 역할을 한다는 것을 깨달았다. 단순히 밤/낮만 표현하는 것이 아니라, 슬라임 게이지 시스템의 자연 소모, 날씨 변화 트리거, 작물 성장 등 정말 다양한 기능을 제어하는 중요한 모듈이 되어서 매우 뿌듯했다. AnimationCurve를 사용해서 조명이 정말 부드럽게 변화하는 것을 보니 시각적인 몰입감이 확 올라가는 것을 느꼈다. 인스펙터에서 time, timeScale 등을 직접 수정할 수 있게 해서 테스트가 엄청나게 편리했다! 빠르게 시간대를 바꿔가며 다른 시스템과의 연동을 테스트할 수 있어서 좋았다.
꼭 기억할 포인트들
- 조명이 변하지 않을 때: SpriteRenderer에 2D/Sprite-Lit 머티리얼이 적용되어 있는지 꼭 확인해야 한다. 이게 아니면 2D 조명 효과를 못 받는다.
- 인스펙터에서 실시간 조절: time, timeScale, currentTimeOfDay 같은 핵심 변수들을 public으로 만들거나 [SerializeField]를 붙여 인스펙터에서 테스트 중 수동으로 조정할 수 있게 하는 것이 디버깅에 큰 도움이 된다.
- URP 필수: Unity의 Light2D 기능은 URP (Universal Render Pipeline)와 2D Renderer 설정이 되어 있어야 정상적으로 작동한다.
- 테스트 최적화: timeScale = 3600f로 설정하면 현실 1초가 게임 1시간으로 빠르게 흘러가서 하루를 순식간에 테스트할 수 있다.
- 시스템 연동의 핵심: TimeOfDay나 Days 같은 TimeManager의 값을 기준으로 다른 시스템들이 조건에 따라 기능을 실행하도록 분기하는 것이 가장 깔끔한 방법이다.
다음 계획
- 이제 이 TimeManager를 이용해 슬라임 시스템과 실제 연동 테스트를 진행할 예정. 특히 밤에만 슬라임 게이지가 자연 소모되는 로직을 확실히 구현해야 한다.
- 작물 성장 시스템을 구현한다면 하루가 지날 때마다 성장 단계가 갱신되도록 연동해야 한다.
- 날씨/온도 시스템과도 연동하여 날마다 환경 효과가 변경되도록 구현할 계획
- 더 나아가, OnTimeChanged 같은 이벤트를 만들어서 외부 시스템들이 TimeManager의 시간 변화를 구독할 수 있도록 리팩토링하는 것도 고려해볼 계획

'TIL' 카테고리의 다른 글
| 바이옴에 따른 자원 군집 형성 (3) | 2025.07.11 |
|---|---|
| A* 알고리즘 (1) | 2025.07.10 |
| Unity에서 Find() 함수 사용을 자제해야 하는 이유 (2) | 2025.07.09 |
| 박싱, 언박싱 그리고 제너릭 (1) | 2025.07.08 |
| 셀룰러 오토마타로 육각형 지형 만드는 시스템 구현 (0) | 2025.07.07 |