본문 바로가기
유니티 공부/Unity

Unity - Lighting을 활용한 낮과 밤 시스템 구현 방법

by 코딩하는 돼징 2025. 5. 19.
반응형

낮과밤 시스템

게임에서 시간의 흐름(해가 뜨고 지고)를 표현하면 플레이어게 더욱더 생동감있는 몰입감을 제공해줄 수 있다.

 

환경 조명 설정(Environment Lighting)

Unity에서 씬 전체의 조명 효과는 Lighting Settigs에서 크게 좌우된다.

1. Skybox Material : 하늘 텍스처 설정

2. Sun Source: 태양 담당을 하는 Direction Light 오브젝트를 지정

3. Realtime Shadow Color: 실시간 그림자 색상을 바꿀 수 있어 해 질 무렵이나 밤에는 살짝 푸르게 변경 가능

4. Intensity Multiplier: 전체 조명 강도 조절 이 값이 낮아질 수록 어둡게 표현

5. Environment Reflections: 모든 오브젝트에 기본적으로 적용되는 빛이다. 반사광을 낮추게되면 밤처럼 어두운 연출을 할 수 있다.


코드 전체 개요

하루를 0.0f ~ 1.0f 범위의 time으로 설정하고 시간에 따라 해와 달의 위치,색상,밝기를 계산하여 게임 씬에 반영한다. 또한 RenderSettings.ambientIntensity 와 reflectionIntensity를 시간에 따라 변경하여 전체적인 조명 분위기를 조절한다.

 

 

01 변수 설정

1. 시간 관련

[Range(0.0f, 1.0f)]
public float time; // 현재 게임 시간 하루 중 어느 시점인지 나타냄
public float fullDayLength; // 게임 내에서 언제를 해당할지 설정
public float startTime = 0.4f; // 게임 시작 시점(기본 0.4는 오전 9~10시 정도)
private float timeRate; // 하루가 얼마나 빠르게 흐르는지 계산
public Vector3 noon; // 태양과 달이 하루 동안 회전할 방향 벡터, (90 0 0)= 위에서 아래로 도는 방향

 

2. 태양 관련

[Header("Sun")]
public Light sun; // Directional Light 오브젝트
public Gradient sunColor; // 시간에 따른 태양의 색상
public AnimationCurve sunIntenstiy; // 시간에 따른 태양밝기 제어

3. 달 관련

[Header("Moon")]
public Light moon; // Directional Light 오브젝트
public Gradient moonColor;  // 시간에 따른 달의 색상
public AnimationCurve moonIntenstiy; // 시간에 따라 달의 밝기를 제어

4. 환경 조명 조절

[Header("Other Lighting")]
public AnimationCurve lightingIntensityMulitplier;
public AnimationCurve reflectionIntensityMultitplier;

 


02 초기 설정

하루 전체를 fullDayLength초에 걸쳐서 다 채우러면 1초마다 time이 얼마나 증가해야 하는지 계산 이를 바탕으로 및에서 반복적인 시간 흐름 구현

private void Start()
{
    timeRate = 1.0f / fullDayLength; 
    time = startTime;
}

예시

fullDayLength 예시
60초(하루가 1분)	
1 / 60 = 0.016666...
120초(하루가 2분이면)	
1 / 120 = 0.008333...
300초(하루가 5분이면)	
1 / 300 = 0.003333...

 

정리

fullDayLength ↑ → timeRate ↓ → 하루가 길어진다 → 느리게 흐름

fullDayLength ↓ → timeRate ↑ → 하루가 짧아진다 → 빨리 흐름

 


03 UpdateLighting 함수

조명(sun 또는 moon)의 상태를 갱신한다.

 

01 밝기값

현재 시간을 기준으로 커브에서 밝기값을 가져온다.

 float intensity = intenstiryCurve.Evaluate(time);

2. 회전 계산

현재 시간을 기준으로 태양 또는 달의 위치를 회전시켜 실제로 하늘을 이동하는 것처럼 보이게 만듬 

기준시간을 빼소 회전 각도를 기준 중심에서 상대적으로 이동시킨다.

lightSource.transform.eulerAngles = (time - (lightSource == sun ? 0.5f : 0.75f)) * noon;

태양과 달의 기준점 설정

태양은 0.5일때 의미 정오, 달은 0.75일때 달의 정점에 있는시간

offset = (lightSource == sun) ? 0.5f : 0.75f;

이 값을 왜 빼줄까?

태양 0.5일때 정점에 위치해야하므로 중심을 0.5로 맞추기 위해 time-0.5f로 조정해주는 것이다.

예시

// 태양인 경우
time = 0.5f; // 정오
(lightSource == sun) → true
offset = 0.5f
→ (0.5 - 0.5) * (90, 0, 0) = (0, 0, 0)
→ 태양은 머리 위 (정점)

time = 0.25f; // 아침 6시쯤
→ (0.25 - 0.5) * (90, 0, 0) = (-22.5, 0, 0)
→ 태양이 지평선 근처에서 떠오르는 중

time = 0.75f; // 오후 6시쯤
→ (0.75 - 0.5) * (90, 0, 0) = (22.5, 0, 0)
→ 태양이 지는 방향으로 기울어짐

// 달인 경우
time = 0.75f → offset = 0.75f
(0.75 - 0.75) * (90, 0, 0) = (0, 0, 0)
→ 달이 머리 위에 위치 (밤의 중심)

time = 0.5f
→ (0.5 - 0.75) * 90 = (-22.5, 0, 0)
→ 달이 동쪽 지평선에서 막 뜨는 중

time = 1.0f
→ (1.0 - 0.75) * 90 = (22.5, 0, 0)
→ 달이 서쪽으로 지고 있음

03 색상, 밝기 적용

현재 시간에 맞는 색과 밝기 전용

lightSource.color = gradient.Evaluate(time);
lightSource.intensity = intensity;

04 켜고 끄기 처리

밝기가 0이면 꺼지고 0보다 크면 다시 킨다. 

GameObject go = lightSource.gameObject;

if (lightSource.intensity == 0 && go.activeInHierarchy)
{
    go.SetActive(false);
}
else if (lightSource.intensity > 0 && !go.activeInHierarchy)
{
    go.SetActive(true);
}

03 시간흐름을 기반으로 빛환경 자동 조절

private void Update()
{
    // 하루를 반복시켜주기 위해 정규화
    time = (time + timeRate * Time.deltaTime) % 1.0f;
	
    // 태양과 달의 상태를 현재 시간기준으로 업데이트
    UpdateLighting(sun, sunColor, sunIntenstiy);
    UpdateLighting(moon, moonColor, moonIntenstiy);
	
    // 반사광을 시간에 따라 조정하여 반사 효과 조절
    RenderSettings.ambientIntensity = lightingIntensityMulitplier.Evaluate(time);
    RenderSettings.reflectionIntensity = reflectionIntensityMultitplier.Evaluate(time);
}

 

 

 

 

 

 

 

반응형

댓글