오늘은 Unity에서 UI 패널을 서서히 투명하게 만들고, 완전히 사라지면 HUD 패널을 켜주는 코루틴을 작성했다.
Unity에서는 특정 작업을 시간에 따라 나눠서 실행하고 싶을 때 코루틴(Coroutine)을 사용한다. 일반적으로 코드는 한 번 실행되면 끝나지만, 코루틴은 yield return을 사용해 중간에 멈췄다가 다음 프레임에서 다시 시작하는 방식이다. 덕분에 애니메이션이나 UI 페이드 효과 같은 것들을 부드럽게 구현할 수 있다.
IEnumerator FadeOutPanel(GameObject panel, float duration, System.Action onComplete = null)
panel: 투명하게 만들 패널 오브젝트
duration: 페이드아웃이 완료되기까지 걸리는 시간(초)
onComplete: 패널이 완전히 사라진 후 실행할 콜백(선택 사항)
코루틴은 IEnumerator를 반환해야 한다. 이 메서드는 UI 패널을 서서히 투명하게 만든 뒤 비활성화하고, HUD 패널을 활성화하는 역할을 한다.
CanvasGroup canvasGroup = panel.GetComponent<CanvasGroup>();
if (canvasGroup == null)
{
canvasGroup = panel.AddComponent<CanvasGroup>();
}
CanvasGroup은 Unity에서 UI의 투명도(Alpha)를 조절하는 데 사용하는 컴포넌트다.
panel에 CanvasGroup이 붙어있는지 확인하고, 없으면 AddComponent를 사용해 동적으로 추가한다.
CanvasGroup.alpha 값만 조절하면 투명해지지만, interactable과 blocksRaycasts를 함께 사용하면 패널이 클릭되지 않도록 설정할 수도 있다.
왜 필요할까?
Unity에서는 Image나 TextMeshPro 자체에는 alpha 값을 조절하는 기능이 없다.
CanvasGroup을 사용해야만 부모 오브젝트 전체의 투명도를 조절할 수 있다.
float startAlpha = canvasGroup.alpha;
float elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
canvasGroup.alpha = Mathf.Lerp(startAlpha, 0f, elapsedTime / duration);
yield return null;
}
startAlpha: 시작 시의 투명도 값 (현재 패널의 alpha 값)
elapsedTime: 시간이 얼마나 흘렀는지를 계산하는 변수
Mathf.Lerp(a, b, t): a에서 b로 t만큼 선형 보간(lerp)하는 함수
elapsedTime / duration: 시간이 지나면서 0에서 1로 증가함
결과적으로 alpha 값이 startAlpha에서 0까지 서서히 변함
yield return null 덕분에 다음 프레임까지 기다리면서 alpha 값을 조절한다. 이게 바로 서서히 사라지는 효과의 핵심이다.
canvasGroup.alpha = 0f;
panel.SetActive(false);
hudPanel.SetActive(true);
반복문이 끝나면 alpha 값을 0으로 설정해 패널을 완전히 투명하게 만든다.
SetActive(false)로 패널 자체를 비활성화한다.
이후 HUD 패널을 활성화해 게임 UI를 표시한다.
onComplete?.Invoke();
?.는 onComplete가 null이 아닐 때만 호출하는 연산자다.
이 부분이 중요한 이유는 특정 패널이 사라진 후 추가 동작(예: 사운드 재생, 텍스트 변경 등)을 쉽게 붙일 수 있기 때문이다.
예시:
StartCoroutine(FadeOutPanel(enemyPanel, 2f, () => Debug.Log("패널이 사라졌습니다.")));
IEnumerator FadeOutPanel(GameObject panel, float duration, System.Action onComplete = null)
{
CanvasGroup canvasGroup = panel.GetComponent<CanvasGroup>();
if (canvasGroup == null)
{
canvasGroup = panel.AddComponent<CanvasGroup>();
}
float startAlpha = canvasGroup.alpha;
float elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
canvasGroup.alpha = Mathf.Lerp(startAlpha, 0f, elapsedTime / duration);
yield return null;
}
canvasGroup.alpha = 0f;
panel.SetActive(false);
// HUD 패널 활성화
hudPanel.SetActive(true);
// 완료 콜백 실행
onComplete?.Invoke();
}
CanvasGroup을 확인하고 없으면 추가한다.
시간이 지나면서 패널의 alpha 값을 서서히 0으로 줄인다.
완전히 투명해지면 패널을 비활성화하고 HUD 패널을 활성화한다.
추가 작업이 필요한 경우 onComplete 콜백을 실행한다.
페이드 인/아웃 모두 구현
IEnumerator FadePanel(GameObject panel, float duration, bool fadeIn)
{
CanvasGroup canvasGroup = panel.GetComponent<CanvasGroup>() ?? panel.AddComponent<CanvasGroup>();
float startAlpha = fadeIn ? 0f : canvasGroup.alpha;
float targetAlpha = fadeIn ? 1f : 0f;
float elapsedTime = 0f;
while (elapsedTime < duration)
{
elapsedTime += Time.deltaTime;
canvasGroup.alpha = Mathf.Lerp(startAlpha, targetAlpha, elapsedTime / duration);
yield return null;
}
canvasGroup.alpha = targetAlpha;
panel.SetActive(fadeIn);
}
fadeIn 값을 true로 설정하면 패널이 서서히 나타나고, false면 서서히 사라진다.
UI 클릭 방지 기능 추가
canvasGroup.interactable = false;
canvasGroup.blocksRaycasts = false;
패널이 사라질 때 클릭을 막고 싶다면 위 코드를 추가한다.
Unity에서 UI를 서서히 사라지게 만들고 HUD 패널을 활성화하는 코루틴을 작성했다. 단순한 기능 같지만, 이를 직접 구현해보면서 CanvasGroup의 역할과 Lerp의 사용법, 코루틴의 흐름을 더 깊이 이해할 수 있었다. 앞으로 다른 UI 전환 효과에도 응용할 수 있을 것 같다.
