69.내일배움캠프 61일차 TIL <Unity Unity 2D 팀프로젝트- MartialGod:Reborn - 10일차> 07/04

정광훈(Unity_9기)·2025년 7월 4일

TIL (Today I Learned)

목록 보기
70/97
post-thumbnail

Instance

instance는 특정 오브젝트에 붙어있는 스크립트 컴포넌트가 가진 기능을 사용할 수 있도록 해주는 통로 역할.

instance = this; 코드가 실행되어 instance 변수가 바로 이 GlobalVolumeManager 인스턴스를 참조하게 됩니다.

"GlobalVolumeManager 인스턴스를 참조하게 됩니다."라는 말은 간단히 말해,
메모리 어딘가에 존재하는 GlobalVolumeManager라는 이름의 실제 오브젝트를 가리키게 된다는 뜻

유니티 게임에서 스크립트 컴포넌트는 C# 클래스로 만들어짐. 이 클래스는 설계도와 같음.
이 설계도를 가지고 실제 게임에 배치되어 작동하는 '실체'를 만들면, 그걸 인스턴스(Instance)라고 부름.

예를 들어, GlobalVolumeManager라는 스크립트(설계도)가 있다면:

설계도 (클래스):
public class GlobalVolumeManager : MonoBehaviour

실제 오브젝트 (인스턴스):
여러분이 씬에 GlobalVolumeManager 컴포넌트를 가진 GameObject를 만들면,
그게 바로 GlobalVolumeManager의 인스턴스.

instance라는 변수는 메모리 어딘가에 존재하는 그 유일한 GlobalVolumeManager 오브젝트를 '참조'(가리키고)하게 됨.

instance = null이라는 뜻은 GlobalVolumeManager 컴포넌트를 가진 GameObject가 현재 메모리 상에 생성되어 있지 않거나,
아직 instance 변수가 그 오브젝트를 '참조(가리키고)'하고 있지 않다는 의미

if (instance == null)이라는 조건은 "현재까지 GlobalVolumeManager의 유일한 인스턴스를 저장해둔 변수가 아무것도 가리키고 있지 않다"는 것을 확인.


<코드>

오늘 작업한 코드이고 Instance부분을 잘 구현 한 것은 아님.

using UnityEngine;
using UnityEngine.Rendering.Universal;
using DG.Tweening;
using NaughtyAttributes;
using UnityEngine.Rendering;

public class GlobalVolumeManager : MonoBehaviour
{
    private static GlobalVolumeManager instance;
    public static GlobalVolumeManager Instance
    {
        get
        {
            // 다른 스크립트가 GlobalVolumeManager.Instance에 처음으로 접근할 때
            // instance == null이면
            if (instance == null)
            {
                // 씬에서 GlobalVolumeManager 인스턴스를 찾아 'instance'가 가리킴
                instance = FindObjectOfType<GlobalVolumeManager>();
    
                // 그래도 없으면 생성하게 하는게 맞나?
            }
    
            return instance;
        }
    }

    [Header("Global Volume")]
    [SerializeField] private Volume globalVolume;
    
    private FilmGrain filmGrain;
    private ChromaticAberration chromaticAberration;
    private Vignette vignette;

    void Reset()
    {
        globalVolume = FindObjectOfType<Volume>();
    }

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            InitGlobalVolume();
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void InitGlobalVolume() // 글로벌 볼륨 초기화
    {
        if (globalVolume == null)
        {
            LogHelper.LogError("GlobalVolumeManager에 Global Volume이 할당되지 않았습니다.", this);
            return;
        }

        if (!globalVolume.profile.TryGet<FilmGrain>(out filmGrain))
        {
            LogHelper.LogError("Global Volume에 FilmGrain이 없습니다.", this);
        }

        if (!globalVolume.profile.TryGet<ChromaticAberration>(out chromaticAberration))
        {
            LogHelper.LogError("Global Volume에 ChromaticAberration이 없습니다.", this);
        }

        if (!globalVolume.profile.TryGet<Vignette>(out vignette))
        {
            LogHelper.LogError("Global Volume에 Vignette가 없습니다.", this);
        }
    }

    [Button]
    public void test1()
    {
        SetVignette(1);
    }
    
    [Button]
    public void test2()
    {
        SetVignette(0.5f,2f);
    }
    
    /// <summary>
    /// Global Volume의 FilmGrain - intensity를 변경
    /// </summary>
    /// <param name="intensity">변화시킬 intensity의 목표치</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetFilmGrain(float intensity, bool fade = true)
    {
        if (filmGrain == null)
        {
            LogHelper.LogError("Global Volume에 FilmGrain이 초기화되지 않았습니다.", this);
            return;
        }

        filmGrain.active = true;
        filmGrain.intensity.overrideState = true;

        if (fade)
        {
            DOTween.To(GetFilmGrainIntensity, SetFilmGrainIntensity, intensity, 1.0f);
        }
        else
        {
            filmGrain.intensity.value = intensity;
        }
    }
    
    /// <summary>
    /// Global Volume의 FilmGrain - intensity를 변경
    /// </summary>
    /// <param name="intensity">변화시킬 intensity의 목표치</param>
    /// <param name="duration">fade하는데 걸리는 시간</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetFilmGrain(float intensity, float duration, bool fade = true)
    {
        if (filmGrain == null)
        {
            LogHelper.LogError("Global Volume에 FilmGrain이 초기화되지 않았습니다.", this);
            return;
        }

        filmGrain.active = true;
        filmGrain.intensity.overrideState = true;

        if (fade)
        {
            DOTween.To(GetFilmGrainIntensity, SetFilmGrainIntensity, intensity, duration);
        }
        else
        {
            filmGrain.intensity.value = intensity;
        }
    }
    
    private float GetFilmGrainIntensity()
    {
        return filmGrain.intensity.value;
    }

    private void SetFilmGrainIntensity(float x)
    {
        filmGrain.intensity.value = x;
    }
    
    /// <summary>
    /// Global Volume의 ChromaticAberration - intensity를 변경
    /// </summary>
    /// <param name="intensity">변화시킬 intensity의 목표치</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetChromaticAberration(float intensity, bool fade = true)
    {
        if (chromaticAberration == null)
        {
            LogHelper.LogError("Global Volume에 ChromaticAberration이 초기화되지 않았습니다.", this);
            return;
        }

        chromaticAberration.active = true;
        chromaticAberration.intensity.overrideState = true;

        if (fade)
        {
            DOTween.To(GetChromaticAberrationIntensity, SetChromaticAberrationIntensity, intensity, 1f);
        }
        else
        {
            chromaticAberration.intensity.value = intensity;
        }
    }
    
    /// <summary>
    /// Global Volume의 ChromaticAberration - intensity를 변경
    /// </summary>
    /// <param name="intensity">변화시킬 intensity의 목표치</param>
    /// <param name="duration">fade하는데 걸리는 시간</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetChromaticAberration(float intensity, float duration, bool fade = true)
    {
        if (chromaticAberration == null)
        {
            LogHelper.LogError("Global Volume에 ChromaticAberration이 초기화되지 않았습니다.", this);
            return;
        }

        chromaticAberration.active = true;
        chromaticAberration.intensity.overrideState = true;

        if (fade)
        {
            DOTween.To(GetChromaticAberrationIntensity, SetChromaticAberrationIntensity, intensity, duration);
        }
        else
        {
            chromaticAberration.intensity.value = intensity;
        }
    }
    
    private float GetChromaticAberrationIntensity()
    {
        return chromaticAberration.intensity.value;
    }

    private void SetChromaticAberrationIntensity(float x)
    {
        chromaticAberration.intensity.value = x;
    }

    /// <summary>
    /// Global Volume의 Vignette - color를 변경
    /// </summary>
    /// <param name="color">변화시킬 color의 목표치</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetVignette(Color color, bool fade = true)
    {
        if (vignette == null)
        {
            LogHelper.LogError("Global Volume에 Vignette가 초기화되지 않았습니다.", this);
            return;
        }

        vignette.active = true;
        vignette.color.overrideState = true;

        if (fade)
        {
            vignette.color.DoColor(color, 1.0f);
        }
        else
        {
            vignette.color.value = color;
        }
    }
    
    /// <summary>
    /// Global Volume의 Vignette - intensity를 변경
    /// </summary>
    /// <param name="intensity">변화시킬 intensity의 목표치</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetVignette(float intensity, bool fade = true)
    {
        if (vignette == null)
        {
            LogHelper.LogError("Global Volume에 Vignette가 초기화되지 않았습니다.", this);
            return;
        }

        vignette.active = true;
        vignette.intensity.overrideState = true;

        if (fade)
        {
            DOTween.To(GetVignetteIntensity, SetVignetteIntensity, intensity, 1.0f);
        }
        else
        {
            vignette.intensity.value = intensity;
        }
    }
    
    /// <summary>
    /// Global Volume의 Vignette - intensity를 변경
    /// </summary>
    /// <param name="intensity">변화시킬 intensity의 목표치</param>
    /// <param name="duration">fade하는데 걸리는 시간</param>
    /// <param name="fade">false를 입력하지 않으면 기본적으로 fade처리</param>
    public void SetVignette(float intensity, float duration, bool fade = true)
    {
        if (vignette == null)
        {
            LogHelper.LogError("Global Volume에 Vignette가 초기화되지 않았습니다.", this);
            return;
        }

        vignette.active = true;
        vignette.intensity.overrideState = true;

        if (fade)
        {
            DOTween.To(GetVignetteIntensity, SetVignetteIntensity, intensity, duration);
        }
        else
        {
            vignette.intensity.value = intensity;
        }
    }
    
    private float GetVignetteIntensity()
    {
        return vignette.intensity.value;
    }

    private void SetVignetteIntensity(float x)
    {
        vignette.intensity.value = x;
    }
}

0개의 댓글