[Unity] UI 3 : DownLoad

로고.png

UI DownLoad

etc-image-1
다운로드 UI. 오른쪽에 프로그램에 대한 설명이 나와 있다.

UI DownLoad의 역할

  • 설치한 프로그램들을 나열해 준다.
  • 나열된 프로그램을 클릭하면 오른쪽에 이미지, 프로그램 이름, 설명, 변경되는 능력치가 나온다.
  • 제거 버튼을 누르면 해당 프로그램이 삭제되고, 변경되었던 능력치들이 원상태로 복구된다.

 

필요한 변수들 선언

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

public class UI_2_DownLoad : MonoBehaviour
{
    private static UI_2_DownLoad instance = null;

    // UI Window
    public GameObject UI_W_DownLoad = null;

    // Detail
    public GameObject Button_Program_Prefab;
    public GameObject i_Program_Detail_Image_Prefab;
    public Text t_Program_Detail_Name_Prefab;
    public Text t_Program_Detail_Explanation_Prefab;
    public Text t_Program_Detail_PowerExplanation_Prefab;

    public Transform ContentProgramGroup;
    public Button ProgramDeleteButton;
    private int CurrentProgram = -1;

    // Manager
    private ProgramManager programManager;

    public static UI_2_DownLoad Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<UI_2_DownLoad>();

                if (instance == null)
                {
                    GameObject singletonObject = new GameObject(typeof(UI_2_DownLoad).Name);
                    instance = singletonObject.AddComponent<UI_2_DownLoad>();
                    DontDestroyOnLoad(singletonObject);
                }
            }
            return instance;
        }
    }

    ...
}

중요한 역할을 하는 변수들은 다음과 같다.

  • instance
    • UI_2_DownLoad 클래스의 싱글톤 인스턴스를 저장하고 관리하며, 전역적으로 접근 가능한 정적 변수
  • ContentProgramGroup
    • 프로그램 버튼들이 생성될 그룹

 

기본 함수(Awake, Start, Update)

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

public class UI_2_DownLoad : MonoBehaviour
{
    ...

    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        programManager = ProgramManager.Instance;
    }

    // Update is called once per frame
    void Update()
    {

    }
    
    ...
}

Awake()

싱글톤 인스턴스 설정과 씬 전환 시 객체를 유지하게 만들고, 현재 오브젝트가 기존 인스턴스와 다른 경우 파괴하도록 만들어줬다.

Start()

ProgramList를 ProgramManger에서 관리한다. UI에서 프로그램 버튼들을 생성할 때 사용 가능하도록 인스턴스를 가지고 왔다.

 

UI Active 관련 함수

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

public class UI_2_DownLoad : MonoBehaviour
{
    ...

    public void OpenUI()
    {
        if (UI_W_DownLoad != null)
        {
            UI_W_DownLoad.SetActive(true);
            GenerateProgramList();
        }
    }

    public void CloseUI()
    {
        if (UI_W_DownLoad != null)
        {
            UI_W_DownLoad.SetActive(false);
        }
    }

    ...
}

UI 매니저에서 각각의 UI 요소들의 Active 상태를 제어하는 OpenUI, CloseUI 함수를 정의해  유지보수성을 높였다.

상태 변화를 제어하는 것을 이 함수들을 사용하는 것으로 한정해 불필요한 활성화/비활성화로 부작용을 방지하도록 만들었다.

프로그램 창을 열 경우에만 프로그램 리스트를 생성하면 되므로 Open 함수 호출 시 GenerateProgramList()를 호출해 줬다.

 

ProgramList Generator 함수

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

public class UI_2_DownLoad : MonoBehaviour
{
    ...

    public void GenerateProgramList()
    {
        // 자손 제거
        foreach (Transform child in ContentProgramGroup)
        {
            Destroy(child.gameObject);
        }

        for (int i = 0; i < programManager.ProgramList.Count; i++)
        {
            GameObject newButton = Instantiate(Button_Program_Prefab, ContentProgramGroup);

            PInformation programInfo = programManager.ProgramList[i];
            Image buttonImage = newButton.GetComponent<Image>();

            if (buttonImage != null)
            {
                SetSpriteFromSheet(buttonImage, programInfo.spriteSheetName, programInfo.spriteIndex);
            }
            else
            {
                Debug.LogError("Error");
            }

            int index = i;
            newButton.GetComponent<Button>().onClick.AddListener(() => OnProgramClick(newButton));
        }

        // Delete Button Activation
        if (programManager.ProgramList.Count == 0)
            ProgramDeleteButton.gameObject.SetActive(false);
    }

    void OnProgramClick(GameObject clickedButton)
    {
        int index = clickedButton.transform.GetSiblingIndex();
        OpenProgramDetail(index);
    }

    ...
}

GenerateProgramList()

  • 가장 먼저 기존에 있던 프로그램 버튼들을 모두 삭제한다.
  • 이후 ProgramManger에서 ProgramList에 있는 ProgramInfomation들을 참고해 버튼을 생성한다.

OnProgramClick()

클릭된 버튼의 순서를 프로그램의 자세한 정보를 띄워주는 함수로 보내준다. 이 함수에서 디테일 정보를 표시하지 않고, 다른 함수에서 보여주도록 만들었다.

 

Detail Panel 관련 함수

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

public class UI_2_DownLoad : MonoBehaviour
{
    ...

    public void OpenProgramDetail(int index)
    {
        CurrentProgram = index;
        // Detail Setting
        t_Program_Detail_Name_Prefab.text = programManager.ProgramList[index].ProgramName;
        t_Program_Detail_Explanation_Prefab.text = programManager.ProgramList[index].Explanation;
        t_Program_Detail_PowerExplanation_Prefab.text = programManager.ProgramList[index].PowerExplanation;

        // Image Setting
        Image detailImage = i_Program_Detail_Image_Prefab.GetComponent<Image>();

        if (detailImage != null)
        {
            Sprite[] sprites = Resources.LoadAll<Sprite>(programManager.ProgramList[index].spriteSheetName);

            if (sprites != null && programManager.ProgramList[index].spriteIndex >= 0 && programManager.ProgramList[index].spriteIndex < sprites.Length)
            {
                detailImage.sprite = sprites[programManager.ProgramList[index].spriteIndex];
                Debug.Log("Detail Image sprite set: " + sprites[programManager.ProgramList[index].spriteIndex].name);
            }
            else
            {
                Debug.LogError("Sprite not found or invalid index for spriteSheetName: " + programManager.ProgramList[index].spriteSheetName);
            }
        }
        else
        {
            Debug.LogError("i_Program_Detail_Image_Prefab does not have an Image component.");
        }

        ProgramDeleteButton.gameObject.SetActive(true);

        Debug.Log("OpenProgramDetail");
    }

    public void FDelete_Button()
    {
        if (CurrentProgram != -1)
        {
            programManager.RemoveProgram(CurrentProgram);
            CurrentProgram = -1;

            t_Program_Detail_Name_Prefab.text = "";
            t_Program_Detail_Explanation_Prefab.text = "";
            t_Program_Detail_PowerExplanation_Prefab.text = "";

            ProgramDeleteButton.gameObject.SetActive(false);

            GenerateProgramList();
        }

        Image detailImage = i_Program_Detail_Image_Prefab.GetComponent<Image>();

        if (detailImage != null)
        {
            detailImage.sprite = null;
        }
        else
        {
            Debug.LogError("Image component not found");
        }
    }
}

OpenProgramDetail()

ProgramManager에서 index로 List의 Information을 받아와 텍스트들을 설정해 주고, 이미지를 설정해 줬다.

FDelete_Button()

프로그램을 삭제하고, 텍스트와 이미지 값들을 없애주도록 만들었다.

이후 프로그램 버튼 그룹을 갱신해 줬다.

 

Image Setting 함수

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

public class UI_2_DownLoad : MonoBehaviour
{
    ...

    public void SetSpriteFromSheet(Image buttonImage, string spriteSheetName, int spriteIndex)
    {
        Sprite[] sprites = Resources.LoadAll<Sprite>(spriteSheetName);

        if (sprites != null && spriteIndex >= 0 && spriteIndex < sprites.Length)
        {
            buttonImage.sprite = sprites[spriteIndex];
            Debug.Log("Sprite loaded: " + sprites[spriteIndex].name);

        }
        else
        {
            Debug.LogError("Sprite not found or invalid index for spriteSheetName: " + spriteSheetName);
        }
    }

    ...
}

프로그램 이미지를 설정하는 함수이다. 이미지 이름과 이미지 인덱스 값을 받아와 리소스 폴더에서 검색 후 설정해 준다. 

 

참고 사항

UI Manager

https://gdoo.tistory.com/39

 

[Unity] UI Manager 구현

UI ManagerUI Manager 기본정보큰 UI의 틀이 있고 버튼을 통해 총 7개의 화면 전환이 있어야 한다.기본 정보를 보여주는 UI게임 기능인 프로그램의 정보를 띄워주는 UI인벤토리처럼 획득한 아이템 리스

gdoo.tistory.com

 

마무리하며..

프로그램 창은 이미지를 설정하는 부분에서 최적화를 더 할 수 있을 것 같다.

'Unity > Hackers Window' 카테고리의 다른 글

[Unity] UI 6 : Control(환경설정 UI)  (1) 2024.11.23
[Unity] UI 3 : MyDocument(Inventory UI)  (0) 2024.11.22
[Unity] UI 2 : MyPC(Status UI)  (0) 2024.11.20
[Unity] UI 1 : HUD  (0) 2024.11.19
[Unity] UI Manager 구현  (0) 2024.11.18