Programmer:)

[Unity] Scroll View Script로 컨트롤 하기 본문

DEV/Unity

[Unity] Scroll View Script로 컨트롤 하기

ryeggg 2022. 3. 28. 15:31
반응형

스크롤뷰 사용할때마다 컨트롤 스크립트를 작성하는게 귀찮아 모듈식으로 사용 가능하도록 작성

 

일단 가로형, 세로형 선택 가능하도록 enum을 만들어 놓았다.

 

Inspector를 통해 설정이 가능하다.

ScrollDiraction :  원하는 방향을 설정

Item : 아이템으로 등록된 오브젝트가 갯수에 맞춰 생성된다. item안에 스크립트를 넣어 item 각각을 컨트롤하면 된다.

Content Object : Scroll View안의 Content 오브젝트를 넣어주면된다.

Total Item :  총 몇개를 생성할지 넣으면 된다. (코드로 정해도 상관없다)

Once Create Item Num : 한번에 몇개 생성될 것인지. 예를들어 5를 넣으면 5개씩 4번 생성된다. (총 20개 생성이라고 가정하에) 스크롤바가 끝에 지점으로 오면 5개가 생성되는 식이다.

Click Item Num : 지금 클릭한 아이템이 누구인지를 저장한다. (이건 커스터마이징 조금 필요)

Item Interval : 스크롤뷰 안에서 아이템간의 간격을 정할 수 있다. 

 

빠른게 스크롤을 내릴경우 풀링이 꼬이는 현상이 발생해서 생성은 오브젝트풀링이 아닌 Instantiate로 생성했다. 

(하지만 생각해보니 풀링으로 최대 갯수 생성컨트롤 부분을 추가하여 이 이슈부분을 최소화 할 수 있겠다는 생각이 든다 .)

 

스크롤뷰 안의 RectSize 를 Item에 맞춰 자동으로 계산하여 조정 할 수 있도록 했다.

 

 

전체 코드는 아래와 같다.

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

public enum Diraction
{
    None,
    Horizontal,
    Vertical
}


public class ScrollViewManager : MonoBehaviour
{
    public Diraction m_scrollDiraction = Diraction.None; //방향
    public GameObject m_item;

    public GameObject m_contentObject;
    private Scrollbar m_scrollbar;
    private ScrollRect m_scrollRect;

    public int m_totalItem; //생성되어야 하는 아이템 갯수
    public int m_onceCreateItemNum; //한번에 생성되어야 하는 아이템 갯수
    private int m_nowItemNum; //현재 생성한 아이템 넘버
    public int m_clickItemNum; //선택한 아이템 넘버

    private List<GameObject> m_itemList = new List<GameObject>(); //생성된 아이템 리스트

    private float m_contentHeight; //스크롤영역 높이
    private float m_contentWidth; //스크롤영역 넓이
    public float m_itemInterval; //아이템간의 간격
    private bool m_isCreating = false; //생성중인가??

    #region Instance
    private static ScrollViewManager m_ScrollViewManager;
    public static ScrollViewManager Instance
    {
        get
        {
            if (m_ScrollViewManager == null)
                m_ScrollViewManager = GameObject.Find("ScrollView").GetComponent<ScrollViewManager>();
            return m_ScrollViewManager;
        }
    }
    #endregion
    
    private void Start()
    {
        Init();
    }

    private void Update()
    {
       if(m_scrollbar.value >= 1 && !m_isCreating && m_itemList.Count < m_totalItem)
        {
            StartCoroutine(AddNewItem());
        }
    }

    private void Init()
    {
        m_scrollRect = this.gameObject.GetComponent<ScrollRect>();

        m_nowItemNum = 1;
        m_clickItemNum = 0;
        
        SetDirection();

        if (m_totalItem <= m_onceCreateItemNum)
            AllAddItem();
        else
            StartCoroutine(AddNewItem());

    }

    private void SetDirection()
    {
        if (m_scrollDiraction == Diraction.Horizontal)
        {
            m_scrollRect.verticalScrollbar.gameObject.SetActive(false);
            m_scrollRect.vertical = false;

            m_scrollRect.horizontalScrollbar.gameObject.SetActive(true);

            m_scrollRect.horizontal = true;
            m_scrollbar = m_scrollRect.horizontalScrollbar;
        }
        else //vertical
        {
            m_scrollRect.horizontalScrollbar.gameObject.SetActive(false);
            m_scrollRect.horizontal = false;

            m_scrollRect.verticalScrollbar.gameObject.SetActive(true);
            m_scrollRect.vertical = true;

            m_scrollbar = m_scrollRect.verticalScrollbar;
        }
    }

    private void SetContentSize()
    {
        if (m_scrollDiraction == Diraction.Horizontal)
        {
            m_contentWidth = (m_item.GetComponent<RectTransform>().sizeDelta.x) * m_itemList.Count + m_itemInterval * m_itemList.Count;
            m_contentObject.GetComponent<RectTransform>().sizeDelta = new Vector2(m_contentWidth, m_contentObject.GetComponent<RectTransform>().sizeDelta.y);
        }
        else //vertical
        {
            m_contentHeight = (m_item.GetComponent<RectTransform>().sizeDelta.y) * m_itemList.Count + m_itemInterval*m_itemList.Count;
            m_contentObject.GetComponent<RectTransform>().sizeDelta = new Vector2(m_contentObject.GetComponent<RectTransform>().sizeDelta.x, m_contentHeight);
        }

        m_isCreating = false;

    }

    private IEnumerator AddNewItem()
    {

        m_isCreating = true;
        yield return new WaitForSeconds(1f);
        //로딩 이미지 구현예정
        PartAddItems();
    }

    //한번에 or 나눠서생성
    public void AllAddItem()
    {
        for (int i = 0; i <= m_totalItem; i++)
        {
            CreateItem();
            m_nowItemNum++;
        }

        SetContentSize();

    }
    public void PartAddItems()
    {
        int next;
        if (m_itemList.Count == 0)
            next = 1;
        else
            next = m_nowItemNum + 1;

        int max = next + m_onceCreateItemNum-1;
        if (max >= m_totalItem)
            max = m_totalItem;

        for (int i = next; i <= max; i++)
        {
            m_nowItemNum = m_itemList.Count+1;
            CreateItem();
        }
        SetContentSize();
    }
    private void CreateItem()
    {
        GameObject item = Instantiate(m_item, m_contentObject.transform);
        item.name = m_nowItemNum.ToString();

        m_itemList.Add(item);
    }
    
}

 

반응형
Comments