본문 바로가기
프로그래밍/유니티

[Unity C#] 코루틴을 사용해서 페이드 인, 페이드 아웃 + α

by 김시루시루르 2021. 10. 27.

레테에서 많이 쓴 기능. 페이드 인.. 페이드 아웃...

Coroutine을 사용해서 UI Pannel을 페이드인, 아웃 하는 방법이에요.

이거 말머리에 UGUI 붙일까말까 좀 고민했어 (결국 안붙임)

 

굳이 판넬이 아니어도 alpha 값을 갖고있다면 무리 없이 가능한 것 같은데...

그런데 이게 GameObject에서도 먹힐지는 잘 모르겠어요 저번에 스프라이트로 해봤는데 안됐던것같기도 하고

어쨌든 이 예시에서는 Image 컴포넌트를 가진 판넬로다가 예시를 들어서 작성합니다.

 

1. 페이드 아웃 / 페이드 인 스크립트

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
GameObject FadePannel;
 
//페이드 아웃
public IEnumerator FadeInStart()
{
    FadePannel.SetActive(true);
    for (float f = 1f; f > 0; f -= 0.02f)
    {
        Color c = FadePannel.GetComponent<Image>().color;
        c.a = f;
        FadePannel.GetComponent<Image>().color = c;
        yield return null;
    }
    yield return new WaitForSeconds(1);
    FadePannel.SetActive(false);
}
 
//페이드 인
public IEnumerator FadeOutStart()
{
    FadePannel.SetActive(true);
    for (float f = 0f; f < 1; f += 0.02f)
    {
        Color c = FadePannel.GetComponent<Image>().color;
        c.a = f;
        FadePannel.GetComponent<Image>().color = c;
        yield return null;
    }
}
cs

여기선 매번 이미지 컴포넌트를 참조해줬지만 참조는 한 번만 해도 됩니다.

 

요는 이미지 컴포넌트의 알파(불투명도) 값을 여러 프레임에 걸쳐 변경한다는 것!

알파가 0일수록 투명에 가깝습니다. 불투명도가 0이란 소리니까요.

그래서 이 판넬을 페이드아웃 시킬 때는 알파를 0으로 수렴하고,

페이드인 시킬 때는 알파를 1로 수렴하게 합니다.

 

페이드 아웃 코드에서 WaitForSeconds와 SetActive가 등장했는데

이것은 사실 코드를 그대로 긁어오다보니 발생한 어쩌구이지만

for문을 이런식으로 돌리면 알파값이 완전히 0 또는 1이 되지 않을 수도 있기 때문에,

페이드 아웃 시에는 나중에 완전히 비활성화 해주는 것도 깔끔한 페이드 아웃을 위한 방법이기도 합니다.

아니면 for문에 0과 1이 아니라 더 낮고 높은 수를 써도 되고요...


2. 여러 판넬을 동시에 페이드 인-아웃 하기

1
2
3
4
5
6
7
8
9
10
11
12
13
CutSceneBlack.SetActive(true);
CutScenePannel.SetActive(true);
for (float f = 0f; f < 1.2; f += 0.05f)
{
    //각각의 판넬 동시에 페이드인
    Color c = CutScenePannel.GetComponent<Image>().color;
    c.a = f;
    Color cb = CutSceneBlack.GetComponent<Image>().color;
    cb.a = f;
    CutScenePannel.GetComponent<Image>().color = c;
    CutSceneBlack.GetComponent<Image>().color = cb;
    yield return null;
}
cs

이건 동시에 두 판넬(CutSceneBlack, CutScenePannel)을 페이드 인 하는 것입니다.

아웃도 비슷하게 하면 됩니다.

여기서는 f의 최대값을 1.2로 잡아둬서 불투명도가 100%가 나오게 조정했네요.

 

아웃까지 이 함수에 넣어서 하려면, 해당 판넬의 알파 값을 1-f같은 느낌으로 하면 되겠죠.

이건 아래의 3번에서 25번줄에 등장합니다. 거기선 동시에 하진 않지만...


3. 교차로 페이드 인-아웃 하기

두 개 이상의 서로 다른 이미지를 보여주며, 순서대로 페이드인이 되어야 할 때.

단 두 개의 판넬로 해결하는 방법!

그러나 판넬들이 화면을 꽉 채워야 한다는 조건도 있습니다. 실질적으로 속임수거든요 (!)

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
32
33
34
35
36
while (true)
{
    //컷씬이 여러장일 때 for문 실행
    for (int i = 1; i < CutSceneImage.Length; i++)
    {
        CutScenePannel2.GetComponent<Image>().sprite = CutSceneImage[i];
        CutScenePannel2.SetActive(true);
        for (float f = 0f; f < 1.2; f += 0.05f)
        {
            Color c = CutScenePannel2.GetComponent<Image>().color;
            c.a = f;
            CutScenePannel2.GetComponent<Image>().color = c;
            yield return null;
        }
        yield return new WaitForSeconds(2f);
 
        if (i + 1 < CutSceneImage.Length)
        {
            //다시 1번 판넬로 다음 이미지 준비
            CutScenePannel.GetComponent<Image>().sprite = CutSceneImage[++i];
            for (float f = 0f; f < 1.2; f += 0.05f)
            {
                //2번 판넬을 페이드 아웃 하면 1번이 페이드 인 되는 듯 보인다!
                Color c = CutScenePannel2.GetComponent<Image>().color;
                c.a = 1 - f;
                CutScenePannel2.GetComponent<Image>().color = c;
                yield return null;
            }
            CutScenePannel2.SetActive(false);
            yield return new WaitForSeconds(2f);
        }
        else
            break;
    }
    break;
}
cs

이 코드는 제가 레테에서 컷씬 보여줄 때 사용한 그대로인데요

여기서는 첫 번째 컷씬을 보여준 뒤,

컷씬이 한장인가? 두 장인가? 에 대한 판단도 이 코드가 하고있기 때문에 이런 구조입니다.

 

아래의 for문에서 i에 값을 더해줬기 때문에 다시 위쪽 for문으로 돌아갈 때,

겹치는 이미지가 등장하지 않고 제대로 각자 출력이 됩니다.

 

이 두 개의 판넬을 사용하는 방법은 2번 판넬이 1번 판넬보다 앞에 보이게 해야 잘 작동합니다.

하이러키 순서를 바꾸든 소트 레이어를 하든 우선도를 주기만 하면 됩니다.


 

프로젝트 정리하다가 나온 코드라 슬쩍 올려보는 건데

사실 유니티 매뉴얼에서도 나오지만 코루틴 하면 가장 기본적인 예시가 페이드인아웃이더라고요

코루틴에 대해 더 알고싶으시면 매뉴얼을 참고해보세요!

 

유니티 - 매뉴얼: 코루틴(Coroutine)

게임 오브젝트 생성 및 삭제 특수 폴더와 스크립트 컴파일 순서 코루틴(Coroutine) 함수를 호출하면 반환값을 반환하기 전에 실행 완료됩니다. 즉, 함수에서 수행되는 작업은 하나의 프레임에서 수

docs.unity3d.com

 

댓글