낮과밤 시스템
게임에서 시간의 흐름(해가 뜨고 지고)를 표현하면 플레이어게 더욱더 생동감있는 몰입감을 제공해줄 수 있다.
환경 조명 설정(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);
}
'유니티 공부 > Unity' 카테고리의 다른 글
Unity - Unity에서 수학 개념을 이해해보자 1편 - 벡터,내적,외적 (0) | 2025.05.23 |
---|---|
Unity - velocity vs addForce +) Velocity 덮어쓰기 , AddForce 무시 문제 (0) | 2025.05.22 |
Unity - InputAction을 사용해서 플레이어 동작 기능 구현하기 (0) | 2025.05.16 |
Unity - 제네릭이 꼭 좋은 건 아니였다. (0) | 2025.05.12 |
Unity - FSM(Finite State Machine)을 사용해서 몬스터 AI를 만들어보자 (0) | 2025.05.09 |
댓글