Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

1vdlrwnsv1 님의 블로그

유니티 개발 숙련주차 3. 조명기능 만져서 낮과 밤 구현 본문

Unity숙련주차

유니티 개발 숙련주차 3. 조명기능 만져서 낮과 밤 구현

1vdlrwnsv1 2025. 3. 5. 19:41

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DayNightCycle : MonoBehaviour
{
    [Range(0.0f, 1.0f)]
    public float time;
    public float fullDayLength;
    public float startTime = 0.4f;
    private float timeRate;
    public Vector3 noon; //vector(90 y 0)
    [Header("Sun")]
    public Light sun;
    public Gradient sunColor;
    public AnimationCurve sunIntensity;

    [Header("Moon")]
    public Light moon;
    public Gradient moonColor;
    public AnimationCurve moonIntensity;

    [Header("Other Lighting")]
    public AnimationCurve lighingIntensityMultiplier;
    public AnimationCurve ReflectionIntensityMultiplier;

    // Start is called before the first frame update
    void Start()
    {
        timeRate = 1.0f / fullDayLength;
        time = startTime;
    }

    // Update is called once per frame
    void Update()
    {
        time = (time + timeRate * Time.deltaTime) % 1.0f;
        UpdateLighting(sun, sunColor, sunIntensity);
        UpdateLighting(moon, moonColor, moonIntensity);

        RenderSettings.ambientIntensity = lighingIntensityMultiplier.Evaluate(time);
        RenderSettings.reflectionIntensity = ReflectionIntensityMultiplier.Evaluate(time);
    }

    void UpdateLighting(Light lightSource, Gradient gradient, AnimationCurve intensityCurve)
    {
        float intensity = intensityCurve.Evaluate(time);
        lightSource.transform.eulerAngles = (time - (lightSource == sun ? 0.25f : 0.75f)) * noon * 4f;
        lightSource.color = gradient.Evaluate(time);
        lightSource.intensity = intensity;

        GameObject go = lightSource.gameObject;
        if(lightSource.intensity == 0 && go.activeInHierarchy)
        {
            go.SetActive(false);

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

변수 설명

  • time: 현재 시간(0~1 범위로 순환, 0은 시작 시간, 1은 하루가 끝난 상태)
  • fullDayLength: 하루 길이
  • startTime: 시작 시간 (0.4f로 설정하면 하루의 40% 지점부터 시작)
  • timeRate: 시간 속도, 하루의 길이에 맞춰서 계산됨.
  • noon: 태양의 정오 위치 (Vector3(90, y, 0) 형태로 설정)

태양 관련 변수

  • sun: 태양을 담당하는 Light 객체.
  • sunColor: 태양 색상을 시간에 따라 변화시키는 Gradient 객체.
  • sunIntensity: 태양의 밝기를 시간에 맞춰 변화시키는 AnimationCurve 객체.

달 관련 변수

  • moon: 달을 담당하는 Light 객체.
  • moonColor: 달 색상을 시간에 맞춰 변화시키는 Gradient 객체.
  • moonIntensity: 달의 밝기를 시간에 맞춰 변화시키는 AnimationCurve 객체.

기타 조명 관련 변수

  • lighingIntensityMultiplier: 기타 조명의 밝기를 시간에 맞춰 변화시키는 AnimationCurve 객체.
  • ReflectionIntensityMultiplier: 반사광의 강도를 시간에 맞춰 변화시키는 AnimationCurve 객체.

 

주요 함수

Start()

  • timeRate = 1.0f / fullDayLength;
    하루를 1로 설정하고, fullDayLength에 맞춰 시간의 흐름 속도를 계산.
  • time = startTime;
    게임이 시작할 때 startTime에서 시작하도록 설정.

Update()

  • time = (time + timeRate * Time.deltaTime) % 1.0f;
    매 프레임마다 time을 업데이트. timeRate에 따라 하루를 진행시키며 1로 나눠서 0~1 범위로 순환하도록 함.
  • UpdateLighting(sun, sunColor, sunIntensity);
    태양에 대해 UpdateLighting 함수를 호출.
  • UpdateLighting(moon, moonColor, moonIntensity);
    달에 대해 UpdateLighting 함수를 호출.
  • RenderSettings.ambientIntensity = lighingIntensityMultiplier.Evaluate(time);
    시간에 맞춰 다른 조명의 밝기를 조정.
  • RenderSettings.reflectionIntensity = ReflectionIntensityMultiplier.Evaluate(time);
    시간에 맞춰 반사광의 강도를 조정.

UpdateLighting(Light lightSource, Gradient gradient, AnimationCurve intensityCurve)

  • lightSource.transform.eulerAngles = (time - (lightSource == sun ? 0.25f : 0.75f)) * noon * 4f;
    주어진 lightSource(태양 또는 달)의 위치를 계산하여 회전시킴. sun은 정오가 0.25f로, moon은 0.75f로 설정되어 서로 다른 시간대에 맞춰 위치가 변함.
  • lightSource.color = gradient.Evaluate(time);
    시간에 맞춰 lightSource의 색상을 gradient에 맞춰 업데이트.
  • lightSource.intensity = intensity;
    시간에 맞춰 lightSource의 밝기를 intensity로 설정.
  • if (lightSource.intensity == 0 && go.activeInHierarchy)
    밝기가 0이면 해당 조명을 비활성화하여 보이지 않게 함.
  • else if (lightSource.intensity > 0 && !go.activeInHierarchy)
    밝기가 0보다 크면 조명을 활성화하여 보이게 함.

밤에서 정오로 갈수록 태양의 intensity(밝기)가 커져야함 반대로 낮에서 자정으로 갈때는 태양의 intenty가 낮아지고 달 조명의 intensity가 커져야 하니 AnimationCurve를 태양과는 반대로 설정해주면됨