본문 바로가기
Development/C#

멋쟁이사자처럼부트캠프 Unity 게임 개발 3기 61일차

by Mobics 2025. 2. 25.

 

목차


    퀴즈 게임 만들기

    25.02.24

    StagePopupPanel 만들기

    : LevelPopupPanel에서 StagePopupPanel로 이름 변경

     

    >> MainPanelController.cs에 StagePopupPanel 바인딩

     

    >> Stage Button의 OnClick()에 함수 바인딩

     

    >> StagePopupPanelController.cs 생성

     

    >> StagePopupPanel에 StagePopupPanelController.cs 추가

     

    >> Scrollbar의 PosX 조정 및 Source Image 추가

     

    >> Handle의 Source Image 추가 및 Color 조정

    : Color는 (240, 240, 240, 255)로 바꾸고 Swatches에 저장

     

    >> Scroll View의 Source Image를 None으로 변경

     

    >> Content 조정

    : Cell Size의 Y를 300으로 바꾼 이유는 나중에 계산을 해야하는게 있어서 복잡하게 하지 않으려고

     

    >> Level Item Button들을 전부 삭제 후, 새로 Image로 'Stage Cell'을 만듦

     

    >> Stage Cell의 자식으로 'Normal', 'Clear', 'Lock' 생성

    : UI-Image로 생성, Stage Cell의 Image Component 삭제

    --> Anchor는 Alt + Shift

     

    >> Normal의 자식으로 'Stage Index Text', 'Stage Title Text' 생성

    : UI-Text로 생성, Stage Title Text의 Color는 배경색보다 조금 밝게 --> 임의로 (134, 138, 151, 255)

     

    >> Clear의 자식으로 'Stage Index Text' 생성

    : UI-Text로 생성

    --> 사진은 이름 변경 전, 'Stage Index Text'로 이름을 바꿈

     

    >> StageCellButton.cs 생성

     

    >> Stage Cell에 StageCellButton.cs 추가 및 바인딩

     

    >> 'Clear'에 Button을 추가한 뒤, OnClick()에 함수 바인딩

    : 어차피 코드로 Clear상태일 때만 Button이 동작하도록 만들었기 때문에, Stage Cell에 Button을 붙여도 상관없다.

     

    >> Stage Cell을 Prefab화 후, Hierarchy에서 Stage Cell 제거

     

    >> StagePopupPanelController.cs에 바인딩

     

    활동

    : Stage Popup Panel을 켰을 때 바로 마지막에 클리어한 Stage로 점프하도록 구현

    --> Hint : Content의 RectTransform을 어떻게 지정할 것인지? 계산해보자

     

    새 프로젝트 'Scroll-View-sample' 생성

    : 템플릿은 '2D (Built-In Render Pipeline)', 이름은 'scroll-view-sample'로 생성한 뒤, Github에 연결

     

    >> Build Settings에서 Android로 Switch Platform

     

    >> 'ScrollView'라는 이름의 새로운 Scene 생성

     

    UI의 Scroll View를 직접 만들어보기

    1. Canvas 생성

     

    2. 빈 게임 오브젝트로 'Scroll View' 생성

    : Anchor 조정 및 'Scroll Rect' Component 추가 후, 세팅

    --> Anchor는 Alt + Shift

     

    3. 'Scroll View'의 자식으로 빈 게임 오브젝트로 'Viewport' 생성

    : Anchor 조정 및 'Image'와 'Mask' Component 추가 후, Scroll Rect에 바인딩

    --> Mask Graphic은 원래 Viewport의 Image가 특별히 보일 이유가 없기 때문에 체크해제 하지만, 지금은 일단 체크해둠

    --> Anchor는 Alt + Shift

     

    4. 'Viewport'의 자식으로 빈 게임 오브젝트로 'Content' 생성

    : Anchor와 Height 조정 및 Scroll Rect에 바인딩

    --> Anchor는 Alt + Shift

     

    5. 'Content'의 자식으로 'Cell' 생성

    : UI-Panel로 추가

    --> Anchor는 Alt + Shift

    --> Color를 만드는 과정에서 구분하기 좋게 임의로 설정함

     

    6. 'Cell'의 자식으로 Image 생성

    : UI-Image로 추가 및 조정 --> Color는 만드는 과정에서 구분하기 좋게 임의로 설정

    --> Anchor는 Alt + Shift

     

    7. 'Cell'의 자식으로 'Title Text', 'Subtitle Text' 생성

    : UI-Text로 생성, Title Text의 Left는 Image의 Width가 260, PosX가 20이고 Image의 오른쪽도 20정도 간격을 두기 위해 20 +  260 + 20 = 300이다.

    --> Anchor는 Alt + Shift

     

    >> Cell.cs, ScrollViewController.cs, Item.cs 생성

     

    >> Cell Prefab화 후, Hierarchy에서 삭제하고 ScrollViewController.cs에 바인딩

     

     

    ※ MVC(Model View Controller) 패턴

    : Model은 데이터를 표현하는 것이고 View는 눈에 보이는 요소이며 Controller는 그 사이에 있는 것

    --> 내가 지금 짜고자 하는 클래스가 데이터의 역할을 하는 클래스인지, 보여주는 역할을 하는 클래스인지, 데이터를 보여주는 클래스의 객체에게 전달하기 위한 클래스인지 구분해서 프로그래밍하자는 것

     

    활동

    :  Object Pool 패턴을 이용한 Level 팝업 만들기 --> 기존에 있는 데이터를 코드로 출력하기까지만 해도 나쁘지 않다.

    • 기존 Level 팝업을 Object Pool 패턴을 이용해 만들어 보세요
    • 화면을 벗어나는 Cell은 비활성화 하고 새롭게 나오는 Cell은 표시하세요

    Hint

    1. Scroll View의 Scroll Rect에는 OnValueChanged()라는 Event함수가 있다.

    --> 스크롤 되는 지점에서 함수를 호출할 수 있다.

     

    2. Content의 높이와 Cell의 높이에 따라 Content의 화면에 Cell이 몇개 채워지는지 정해진다.

    --> 스크롤 하는 순간 Content의 RectTransform값을 이용하여 새로운 Cell이 필요한지 판단하는 코드가 필요하다.

     

    최종 코드

    >> Cell.cs

    using System.Collections;
    using System.Collections.Generic;
    using TMPro;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class Cell : MonoBehaviour
    {
        [SerializeField] private Image image;
        [SerializeField] private TMP_Text titleText;
        [SerializeField] private TMP_Text subtitleText;
    
        public void SetItem(Item item)
        {
            //image.sprite = Resources.Load<Sprite>(item.imageFileName);
            titleText.text = item.title;
            subtitleText.text = item.subtitle;
        }
    }

     

    >> ScrollViewController.cs

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    [RequireComponent(typeof(ScrollRect))]
    [RequireComponent(typeof(RectTransform))]
    public class ScrollViewController : MonoBehaviour
    {
        [SerializeField] private GameObject cellPrefab; // ObjectPool을 쓰면서 다른 곳으로 옮겨도 된다.
        
        private ScrollRect _scrollRect; // ScrollRect는 Content도 제어 가능하다
        private RectTransform _rectTransform;
        
        private List<Item> _items;
        
        private void Awake()
        {
            _scrollRect = GetComponent<ScrollRect>();
            _rectTransform = GetComponent<RectTransform>();
        }
    
        private void Start()
        {
            LoadData();
        }
    
        /// <summary>
        /// _items에 있는 값을 Scroll View에 표시하는 함수
        /// </summary>
        private void ReloadData()
        {
            
        }
    
        private void LoadData()
        {
            _items = new List<Item>()
            {
                new Item {imageFileName = "image1", title = "Title 1", subtitle = "Subtitle 1"},
                new Item {imageFileName = "image2", title = "Title 2", subtitle = "Subtitle 2"},
                new Item {imageFileName = "image3", title = "Title 3", subtitle = "Subtitle 3"},
                new Item {imageFileName = "image4", title = "Title 4", subtitle = "Subtitle 4"},
                new Item {imageFileName = "image5", title = "Title 5", subtitle = "Subtitle 5"},
                new Item {imageFileName = "image6", title = "Title 6", subtitle = "Subtitle 6"},
                new Item {imageFileName = "image7", title = "Title 7", subtitle = "Subtitle 7"},
                new Item {imageFileName = "image8", title = "Title 8", subtitle = "Subtitle 8"},
                new Item {imageFileName = "image9", title = "Title 9", subtitle = "Subtitle 9"},
                new Item {imageFileName = "image10", title = "Title 10", subtitle = "Subtitle 10"},
            };
            ReloadData();
        }
    
        #region Scroll Rect Events
    
        public void OnValueChanged(Vector2 value) // 스크롤 방향에 따라 0 아니면 1의 값이 들어온다.
        {
            // 아래 정보들을 가지고 어떤 Cell이 보여지고 어떤 Cell이 사라져야 하는지 판단할 수 있다.
            var x = _scrollRect.content.anchoredPosition.x;
            var y = _scrollRect.content.anchoredPosition.y;
            var width = _rectTransform.rect.width;
            var height = _rectTransform.rect.height;
            
            Debug.Log($"x : {x}, y : {y}, width : {width}, height : {height}");
        }
    
        #endregion
    }

     

    >> Item.cs

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public struct Item
    {
        public string imageFileName;
        public string title;
        public string subtitle;
    }

     


    C# 단기 교육 보강

    13일차

    장염 이슈로 추후 작성 예정..ㅜㅜ