유니티/UI

유니티 Swipe Menu(Carousel) UI

민또배기 2022. 4. 7. 18:53
반응형

유니티 버전 : 2020.3.25 f1
작업환경 : Mac (Monterey 12.2.1)
 
Carousel은 회전목마라는 뜻입니다. 회전목마 UI 뭔가 계속 도는 느낌의 UI입니다.
이 UI는 실제로도 많이 사용하고 또 많이 보고 있습니다. 
 
애플 홈페이지에서 가져왔습니다. (제가 사고 싶어서... ㅎ)
상단에 있는 X표시는 빼고 좌우에 있는 화살표? 표시와 현재위치를 알려주는 하단의 원표시 이와 같은 형태를 캐로셀이라고 합니다.
슬라이더라고도 합니다. 
이미지, 슬라이드가 많을 때 사용하면 좋은 UI입니다.
 

Carousel UI Example (Apple)

 
그리드 작업할 때 영역을 나누는 것과 비슷하게 생각하시면 될 것 같습니다.
전체가 value가 1이고 안의 내용물이 5개라고 할 때, 각 내용물의 위치는 0, 0.2, 0.4, 0.6, 0.8, 1이 됩니다. 
만약 터치했을 때의 위치가 0.1 ~ 0.3 사이라고 하면 내용물의 위치는 0.2가 됩니다. 2번째에 있는 내용물이 화면에 표시됩니다.

Carousel Contents Position

이를 바탕으로 유니티로 구현해 본 Carousel UI 스크립트입니다.
유니티 에디터에서의 하이어라키는 하단의 영상을 참고 바랍니다.(제 거 아니에요)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Carousel : MonoBehaviour
{
    public GameObject scrollbar;
    float scroll_pos = 0;
    float[] pos;
    Scrollbar scroll;
    // Start is called before the first frame update
    void Start()
    {
        scroll = scrollbar.GetComponent<Scrollbar>();
    }

    // Update is called once per frame
    void Update()
    {
        pos = new float[transform.childCount];
        float distacne = 1f / (pos.Length - 1);
        for(int i = 0; i< pos.Length; i++)
        {
            pos[i] = distacne * i;
        }
        if (Input.GetMouseButton(0))
        {
            scroll_pos = scroll.value;
        }
        else
        {
            for(int i = 0; i< pos.Length; i++)
            {
                if(scroll_pos<pos[i] + (distacne/2)&&scroll_pos > pos[i] - (distacne / 2))
                {
                    scroll.value = Mathf.Lerp(scroll.value, pos[i], 0.1f);
                }
            }
        }

        for (int i = 0; i < pos.Length; i++)
        {
            if (scroll_pos < pos[i] + (distacne / 2) && scroll_pos > pos[i] - (distacne / 2))
            {
                transform.GetChild(i).localScale = Vector2.Lerp(transform.GetChild(i).localScale, new Vector2(1f, 1f), 0.1f);
                for(int j = 0; j < pos.Length; j++)
                {
                    if(j != i)
                    {
                        transform.GetChild(j).localScale = Vector2.Lerp(transform.GetChild(j).localScale, new Vector2(0.8f, 0.8f), 0.1f);
                    }
                }
            }
        }
    }
}

 
이 예제는 터치로만 동작되도록 되어 있어서 하단에 버튼을 누르면 이동하는 기능을 추가해서 만들어봤습니다.
소스코드의 효율은 아직 잘 몰라서... (더 배워야죠)
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Carousel : MonoBehaviour
{
    public GameObject scrollbar;
    public GameObject selectButton;
    float scroll_pos = 0;
    bool selectedBtn = false;
    float[] pos;
    Scrollbar scroll;
    
    void Start()
    {
        scroll = scrollbar.GetComponent<Scrollbar>();
    }

    void Update()
    {
        pos = new float[transform.childCount];
        float distacne = 1f / (pos.Length - 1);
        for(int i = 0; i< pos.Length; i++)
        {
            pos[i] = distacne * i;
        }

        if (Input.GetMouseButton(0))
        {
            scroll_pos = scroll.value;
        }
        else
        {
            if (!selectedBtn)
            {
                for (int i = 0; i < pos.Length; i++)
                {
                    if (scroll_pos < pos[i] + (distacne / 2) && scroll_pos > pos[i] - (distacne / 2))
                    {
                        scroll.value = Mathf.Lerp(scroll.value, pos[i], 0.1f);
                    }
                }
            }
        }

        for (int i = 0; i < pos.Length; i++)
        {
            if (scroll_pos < pos[i] + (distacne / 2) && scroll_pos > pos[i] - (distacne / 2))
            {
                transform.GetChild(i).localScale = Vector2.Lerp(transform.GetChild(i).localScale, new Vector2(1f, 1f), 0.1f);
                for(int j = 0; j < pos.Length; j++)
                {
                    if(j != i)
                    {
                        transform.GetChild(j).localScale = Vector2.Lerp(transform.GetChild(j).localScale, new Vector2(0.8f, 0.8f), 0.1f);
                    }
                }

                selectButton.transform.GetChild(i).localScale = Vector2.Lerp(selectButton.transform.GetChild(i).localScale, new Vector2(1f, 1f), 0.1f);
                for (int k = 0; k < selectButton.transform.childCount; k++)
                {
                    if (k != i)
                        selectButton.transform.GetChild(k).localScale = Vector2.Lerp(selectButton.transform.GetChild(k).localScale, new Vector2(0.7f, 0.7f), 0.1f);
                }
            }
        }    
    }

    public void ContentsPosition()
    {
        float distacne = 1f / (pos.Length - 1);
        int selectedValue = int.Parse(EventSystem.current.currentSelectedGameObject.transform.GetComponentInChildren<Text>().text)-1;
        StartCoroutine(selectBtn(selectedValue * distacne));
    }

    IEnumerator selectBtn(float targetValue)
    {
        selectedBtn = true;
        while (true)
        {
            yield return null;
            scroll.value = Mathf.Lerp(scroll.value, targetValue, 0.1f);
            if (Mathf.Abs(scroll.value - targetValue) <= 0.1f)
            {
                scroll_pos = scroll.value;
                selectedBtn = false;
                break;
            }
        }
    }
}

결과영상은 다음과 같습니다.
https://youtu.be/3AxTpn1Csmk

https://github.com/inbear-evan/Unity_Carousel

 

GitHub - inbear-evan/Unity_Carousel: Unity_Carousel UI

Unity_Carousel UI. Contribute to inbear-evan/Unity_Carousel development by creating an account on GitHub.

github.com

#참고자료
https://www.youtube.com/watch?v=GURPmGoAOoM 
 
https://kmong.com/gig/449118

 

유니티 기반 게임,앱 개발해 드립니다. | 1000000원부터 시작 가능한 총 평점 0점의 IT·프로그래밍,

0개 총 작업 개수 완료한 총 평점 0점인 민또배기의 IT·프로그래밍, 2D·3D 게임 서비스를 0개의 리뷰와 함께 확인해 보세요. IT·프로그래밍, 2D·3D 게임 제공 등 1000000원부터 시작 가능한 서비스

kmong.com

 

반응형

'유니티 > UI' 카테고리의 다른 글

유니티 텍스트 메쉬 프로(Text Mesh Pro)한글 사용하기  (0) 2023.03.07
유니티 UI - infinite scroll  (0) 2022.05.24
Unity TabMenu  (0) 2022.05.16
유니티 이중 스크롤 뷰  (0) 2022.04.18
Unity Circle Slider UI  (0) 2022.04.18