Recent Posts
Recent Comments
Link
Today
Total
05-20 06:06
관리 메뉴

채린씨의 티스토리

[졸업프로젝트] Unity UI 본문

Projects/졸업프로젝트

[졸업프로젝트] Unity UI

채린씨 2021. 5. 18. 23:20

*** 기술블로그 제출용 통합본 ***

 

<Part1. 인트로 로딩 씬 만들기>

프로그램을 시작할 때 프로그램 이름이나 제작자 등을 표시하기 위한 인트로 로딩 씬을 만들어 보았다.

 

1. Intro 씬과 Main 씬을 만든다.

  - Intro 씬에서 프로그램이 실행되면 원하는 시간동안 로딩이 진행된 후 자동으로 Main 씬으로 넘어가도록 할 것이다.

  - 나중에 Main 씬임을 알아볼 수 있도록 아무 이미지나 올려두자.

 

Main 씬임을 알기 쉽도록 아무 이미지나 올려두었다.

 

2. Intro 씬에서 UI > Canvas를 추가한다.

 

3. Canvas에 배경이 될 Panel을 올린다.

 

4. Panel에 Image나 Text(TMP)를 올린다.

 

여기까지 진행한 결과는 다음과 같다.

 

Image와 Text(TMP)가 차례로 나타났다가 사라지도록 하기 위해서 겹치게 배치했다.

 

5. IntroManager라는 C# 스크립트 파일을 하나 만든다.


using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using UnityEngine.SceneManagement;

public class IntroManager : MonoBehaviour
{
    // can ignore the update, it's just to make the coroutines get called for example

    [SerializeField] Image image = null;
    [SerializeField] TextMeshProUGUI text = null;

    void Start()
    {
        StartCoroutine(FadeTextToFullAlpha(1.5f, image, text));
    }

    void Update()
    {
    }

    public IEnumerator FadeTextToFullAlpha(float t, Image i, TextMeshProUGUI j)
    {
        i.color = new Color(i.color.r, i.color.g, i.color.b, 0);
        j.color = new Color(j.color.r, j.color.g, j.color.b, 0);

        while (i.color.a < 1.0f)
        {
            i.color = new Color(i.color.r, i.color.g, i.color.b, i.color.a + (Time.deltaTime / t));
            yield return null;
        }
        i.color = new Color(i.color.r, i.color.g, i.color.b, 1);
        while (i.color.a > 0.0f)
        {
            i.color = new Color(i.color.r, i.color.g, i.color.b, i.color.a - (Time.deltaTime / t));
            yield return null;
        }
        
        while (j.color.a < 1.0f)
        {
            j.color = new Color(j.color.r, j.color.g, j.color.b, j.color.a + (Time.deltaTime / t));
            yield return null;
        }
        j.color = new Color(j.color.r, j.color.g, j.color.b, 1);
        while (j.color.a > 0.0f)
        {
            j.color = new Color(j.color.r, j.color.g, j.color.b, j.color.a - (Time.deltaTime / t));
            yield return null;
        }

        SceneManager.LoadScene("Main");
    }

}

 

- 변수 t는 이미지나 텍스트가 나타나거나 사라지는 데 소요되는 시간을 의미한다. 즉, Image i가 1.5초동안 천천히 나타났다가 1.5초동안 천천히 사라지고, 이후 Text(TMP) j가 1.5초동안 천천히 나타났다가 1.5초동안 천천히 사라진다.

- 이미지나 텍스트의 r, g, b 값은 그대로 두고, 투명도를 의미하는 a값을 0에서 1까지 증가시켰다가 1에서 0까지 감소시키는 방식으로 나타남과 사라짐을 구현하였다.


 

6. Create Empty 버튼을 이용해 IntroManager라는 빈 오브젝트를 생성한 후 IntroManager 스크립트를 적용한다.

 

7. Inspector에서 Image 칸과 Text 칸에 아까 Panel에 올려두었던 Image와 Text(TMP)를 적용한다.

 

여기까지 진행한 결과는 다음과 같다.

 

우측 inspector에서 Image와 Text(TMP)가 적용된 것을 볼 수 있다.

 

8. 실행 전에, File > Build Settings에서 실행할 모든 씬을 Scenes In Build에 추가해야 한다.

  - 그냥 마우스로 드래그하면 된다.

 

Intro 씬과 Main 씬을 끌어다 넣고 창을 닫으면 된다.

 

9. 실행한다!

 

Image가 나타났다가 사라지고, Text(TMP)가 나타났다 사라진 후 Main 씬으로 넘어가는 것을 확인할 수 있다.

 

끝!! 다음시간에는 로딩 진행 현황을 보여주는 프로그레스바도 추가해보자~!~!!

 

 

 

 

 

<Part2. 인트로 로딩 씬에 프로그레스바(진행표시줄) 추가하기>

지난 포스팅에 이어서 이번에는 로딩 진행상황을 나타내는 프로그레스 바(진행표시줄)을 추가해보자.

실제 로딩 진행상황을 나타내는 것은 아니고, 원하는 시간 동안 프로그레스 바가 채워지는..

눈속임이다.

 

1. Panel에 Slider를 올린 후 Slider에 포함되는 오브젝트 중 Handle Slide Area의 Handle은 삭제한다.

 

2. 로딩이 몇 퍼센트 진행되었는지 표시하기 위한 Text(TMP)를 추가한다.

 

3. Fill Area 의 Fill을 선택한 후 Inspector에서 Image의 컬러를 원하는 색으로 설정한다.

  - 이후 로딩이 진행될 때 이 색으로 프로그레스 바가 채워진다.

 

여기까지 진행한 결과는 다음과 같다.

 

 

4. 지난 포스팅에서 사용한 스크립트를 살짝만 수정하여 프로그레스 바 관련 코드를 추가해준다.


using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System.Collections;
using UnityEngine.SceneManagement;

public class IntroManager : MonoBehaviour
{
    // can ignore the update, it's just to make the coroutines get called for example

    [SerializeField] Image image = null;
    [SerializeField] TextMeshProUGUI text = null;
    [SerializeField] Slider slider = null;
    [SerializeField] TextMeshProUGUI text_percentage = null;

    private float time_loading = 6;
    private float time_current;
    private float time_start;

    void Start()
    {
        time_current = time_loading;
        time_start = Time.time;
        Set_FillAmount(0);
        StartCoroutine(FadeTextToFullAlpha(1.5f, image, text));
    }

    void Update()
    {
        Check_Loading();
    }

    public IEnumerator FadeTextToFullAlpha(float t, Image i, TextMeshProUGUI j)
    {
        i.color = new Color(i.color.r, i.color.g, i.color.b, 0);
        j.color = new Color(j.color.r, j.color.g, j.color.b, 0);

        while (i.color.a < 1.0f)
        {
            i.color = new Color(i.color.r, i.color.g, i.color.b, i.color.a + (Time.deltaTime / t));
            yield return null;
        }
        i.color = new Color(i.color.r, i.color.g, i.color.b, 1);
        while (i.color.a > 0.0f)
        {
            i.color = new Color(i.color.r, i.color.g, i.color.b, i.color.a - (Time.deltaTime / t));
            yield return null;
        }
        
        while (j.color.a < 1.0f)
        {
            j.color = new Color(j.color.r, j.color.g, j.color.b, j.color.a + (Time.deltaTime / t));
            yield return null;
        }
        j.color = new Color(j.color.r, j.color.g, j.color.b, 1);
        while (j.color.a > 0.0f)
        {
            j.color = new Color(j.color.r, j.color.g, j.color.b, j.color.a - (Time.deltaTime / t));
            yield return null;
        }
       
    }

    private void Check_Loading()
    {
        time_current = Time.time - time_start;
        if (time_current < time_loading)
        {
            Set_FillAmount(time_current / time_loading);
        }
        else
        {
            End_Loading();
        }
    }

    private void End_Loading()
    {
        Set_FillAmount(1);
        SceneManager.LoadScene("Main");
    }

    private void Set_FillAmount(float _value)
    {
        slider.value = _value;
        string txt = (_value.Equals(1) ? "Finished.. " : "Loading.. ") + (_value).ToString("P");
        text_percentage.text = txt;
    }

}

5. IntroManager의 Inspector에서 Slider 칸과 Text_percentage 칸에 아까 Panel에 올려두었던 Slider와 Text(TMP)를 적용한다.

 

6. 실행한다!

 

그런데 프로그레스 바가 끝까지 채워지지 않고 로딩이 끝나버린다!!

 

아마 Handle을 삭제하면서 Handle에 가려져 있던 부분이 보여서 그런게 아닐까..

하지만.. 완벽주의자는 용납할 수 없다..

 

7. Fill Area의 길이를 조금씩 조정하며 딱 맞아 떨어질때까지 실행 > 확인 과정을 반복한다..ㅎ

 

이 선택된 Fill Area의 왼쪽은 그대로 두고 오른쪽부분을 조금씩 조정한다.

 

8. 실행한다!

 

프로그레스 바의 길이가 감쪽같이 맞아떨어지는 것을 확인할 수 있다!

 

끝!!

 

 

 

 

 

<Part3. 탭 메뉴 만들기>

오늘은 유니티 UI중에 탭 메뉴를 만들어 보자.

이미 완성된 UI 에셋들이 유니티 에셋스토어에 많이 올라와 있기는 하지만..

우리가 산 에셋에는 탭 메뉴가 없어서 내가 직접 만들었다.. 흙..

 

1. TabMenu라는 새로운 Scene을 하나 만들어주자.

 

2. UI > Canvas를 만들어주자.

 

3. Canvas 위에 배경이 될 Panel 하나를 올려주자.

 

4. Panel 위에 Text(TMP)를 올려 제목도 하나 써주자.

 

여기까지 진행한 결과는 다음과 같다.

 

 

5. 이제 탭 버튼이 될 세 개의 버튼 그룹을 만들자.

   Hierarchy 창에서 Create Empty를 눌러 빈 오브젝트를 생성한 후 이름을 Buttons로 바꿔주자.

   그리고 Canvas 위로 올려주자!

   Buttons 안에 세 개의 버튼을 생성한 후 아래와 같이 적당히 위치와 크기를 조절해 주자.

 

 

6. 이제 탭 판넬이 될 세 개의 판넬 그룹을 만들자.

   Hierarchy 창에서 Create Empty를 눌러 빈 오브젝트를 생성한 후 이름을 Panels로 바꿔주자.

   그리고 Canvas 위로 올려주자!

   Panels 안에 크기가 같은 세 개의 판넬을 생성한 후 아래와 같이 겹치게 배치한다.

   마지막으로, 각 판넬을 구분할 수 있도록 이미지를 넣어주자!

 

 

7. 이제 각 버튼을 눌렀을 때 해당 버튼과 관련된 판넬이 가장 앞에 오도록 하기만 하면 된다!

   * 겹쳐있는 모든 object는 Hierarchy의 아래에 있을 수록 가장 위에! (즉, 눈과 가까이에!) 존재한다 *

   이 사실만 알면 코드 없이, 어렵지 않게 탭 메뉴를 만들 수 있다.

   각 버튼을 누를 때마다 해당 버튼과 관련된 판넬의 그룹 내 Hierarchy 순서가 가장 아래로 오게 하면 된다!

   그리고 유니티에서는 이 기능을 아주 간단하게 제공한다.

   버튼의 Inspector에서 버튼이 클릭되었을 때 할 일을 정해주는 OnClick() 부분을 추가(+)한다.

   그리고 그 버튼에 해당하는 판넬을 None이라고 되어 있는 칸에 드래그해서 넣어준다!

   마지막으로, No Function이라고 되어 있는 칸을 RectTransform>SetAsLastSibling 으로 바꿔준다!

 

 

   이를 나머지 두 버튼에도 적용하면 끝!

 

 

코드 없이, 쉽고 간단하게 탭 메뉴 만들기 완료~!

 

 

 

 

 

<Part4. 상하 스크롤뷰 만들기>

오늘은 유니티에서 상하 스크롤뷰를 만들어 볼 것이다.

그냥 스크롤뷰를 만드는 건 어렵지 않지만, 우리의 목표는 스크롤뷰 안의 콘텐츠가 자동정렬 되록 하는 것!

어렵지 않으니 따라해보자!

 

1. Scroll이라는 새로운 Scene을 하나 만들어주자.

 

2. UI > Canvas를 만들어주자.

 

3. Canvas 위에 배경이 될 Panel 하나를 올려주자.

 

4. Panel 위에 Text(TMP)를 올려 제목도 하나 써주자.

 

여기까지 진행한 결과는 다음과 같다.

 

 

5. 이제 Panel 위에 Scroll View를 하나 만들어준 후 아래와 같이 크기와 위치를 적당히 조절해준다.

 

 

6. 우리는 상하 스크롤뷰를 만들 것이므로 Hierarchy 창에서 Scrollbar Horizontal을 삭제한다.

   Scroll View의 Inspector 창에서도 Scroll Rect > Horizontal을 체크 해제한다.

 

 

7. Scrollbar Vertical의 길이를 적당히 조절해준다.

 

 

8. 이제 스크롤뷰 안에 들어갈 콘텐츠를 Scroll View > Viewport > Content 안에 넣어주면 된다.

   나는 그냥 아무 이미지를 생성해서 넣어주었다.

 

 

9. Scroll View > Viewport > Content의 Inspector에서 Add Component 버튼을 눌러 Grid Layout Group을 추가해준다.

   이는 스크롤뷰의 콘텐츠들이 자동으로 정렬되도록 한다.

   Cell Size의 X값과 Y값을 조정해 각 콘텐츠의 크기를 설정한다.

   Spacing의 X값과 Y값을 조정해 각 콘텐츠 사이의 간격을 설정한다.

   가운데 정렬을 하고 싶다면 Child Alignment를 Upper Center로 설정하면 된다.

 

 

    콘텐츠가 자동정렬되는지 확인하기 위해 콘텐츠를 추가해보자!

 

Content에 이미지를 네 개 더 추가하였는데, 이미지들이 자동정렬되고 Scroll View 범위 밖을 벗어나는 이미지는 보이지 않음을 확인할 수 있다.

 

10. Scroll View > Viewport > Content의 Inspector에서 Add Component 버튼을 눌러 Content Size Fitter를 추가해준다.

    이는 스크롤뷰의 콘텐츠들의 크기와 개수에 따라 스크롤바의 크기를 자동으로 적절하게 조정해준다.

    우리는 세로 스크롤뷰를 만들 것이므로 Vertical Fit만 Preferred Size로 설정해준다.

스크롤바의 길이가 적당히 조절된 것을 확인할 수 있다.

 

결과 확인!

 

마우스 스크롤로 위-아래 이동중인데 너무 느리다.. 속도를 높여야겠다..

 

Scroll View의 Inspector 창에서 Scroll Sensitivity를 높여준다!

 

 

결과 확인!!

 

훨씬 더 자연스러운 스크롤이 가능해졌다.

 

여기까지 유니티 스크롤뷰 만들기 끝~!

 

 

 

 

 


마지막 마무리는 우리가 직접 만든 프로그램 데모동영상..

위의 요소들이 어디에 숨어있는지 한번 찾아보자!!!

 

 

Comments