
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;
}
}