[UGUI연습] 미션(동적 스크롤뷰 활용)
2023. 9. 8.

빈오브젝트 (content) 만들고

앵커프리셋 시프트 + 알트 좌상단

컴포넌트 Content Size Fitter 붙이고

스크롤뷰에 ScrollRect붙이고 Vertical 만 체크, scrollrect에 content를 넣어준다.스크롤 뷰에 마스크 추가

스크롤뷰 구조

 - 기존에 만들었던 cell들은 한개만 남겨두고 지운 뒤, 남은 하나의 cell을 가이드에 맞춰 제작한 후 프리팹화한다.

- 마찬가지로 프리팹화한 cell은 동적으로 생성할 것이므로 삭제한다.

프리팹으로 만든 cell

 -어제 작성한 DataManager를 수정한다.

 -LoadMissionData메서드를 통해 mission_data.json의 데이터를 가져온다. Test06UIMain.cs에서 호출하도록 한다.

-미션 셀을 doing과 complete를 가지도록 수정하였다.

-이제 cell에 데이터를 연동한다.

-먼저 데이터를 받아와서 cell 프리팹의 인스턴스를 생성하는 코드를 작성했다. 이 때 content 오브젝트의 자식으로 생성되도록 한다.

-이미지도 받아오기 위해 아틀라스를 생성한다.

아틀라스 생성

-메인에서 아틀라스를 로드하고, cell에서 가져다 쓸 수 있도록 코드를 수정한다.

추가 수정

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json;
using System.IO;
using System.Linq;

public class DataManager 
{
    public static readonly DataManager Instance = new DataManager();
    private List<ChestData> chestDatas = new List<ChestData>();
    private Dictionary<int, MissionData> dicMissionDatas;

    public void LoadChestData()
    {
        string json = File.ReadAllText("./Assets/Resources/chest_data.json");//파일 읽기
        // Debug.Log(json);
        this.chestDatas = JsonConvert.DeserializeObject<List<ChestData>>(json);//역직렬화

    }
    public List<ChestData> GetChestDatas()
    {
       return this.chestDatas;
    }

    //미션 데이터 로드 하기 
    public void LoadMissionData()
    {
        //Resources 폴더에서 mission_data 에셋 (TextAsset) 을 로드 
        TextAsset asset = Resources.Load<TextAsset>("mission_data");
        //json 문자열 가져오기 
        string json = asset.text;
        Debug.Log(json);
        //역직렬화 
        MissionData[] arrMissionDatas = JsonConvert.DeserializeObject<MissionData[]>(json);
        Debug.LogFormat("arrMissionDatas.Length: {0}", arrMissionDatas.Length);

        //사전에 넣기
        this.dicMissionDatas = arrMissionDatas.ToDictionary(x => x.id); //배열에 있는 요소로 새로운 사전을 만듬 
        Debug.LogFormat("this.dicMissionDatas.Count: {0}", this.dicMissionDatas.Count);
    }

    public List<MissionData> GetMissionDatas()
    {
        return this.dicMissionDatas.Values.ToList();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test06UIScrollView : MonoBehaviour
{
    [SerializeField] GameObject uiMissionCellGo;
    [SerializeField] GameObject contentGo;
    private List<Test06UIMissionCell> uiCellList = new List<Test06UIMissionCell>();
    // Start is called before the first frame update
    void Start()
    {
        for(int i = 0; i<uiCellList.Count; i++)
        {
            //uiCellList[i].onButtonClick = () =>
            //{
            //    Debug.LogFormat("{0} Clicked!", uiCellList[i]);
            //};
        }
    }

    public void Init()
    {
        List<MissionData> data = DataManager.Instance.GetMissionDatas();
        for(int i=0;i<data.Count; i++)
        {
            GameObject go = Instantiate<GameObject>(this.uiMissionCellGo, this.contentGo.transform);
            //cell프리팹 생성. content오브젝트의 자식으로 넣는다.
            this.uiCellList.Add(go.GetComponent<Test06UIMissionCell>());
            this.uiCellList[i].Init(data[i]);//매개변수를 통해 데이터 전달
        }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MissionData
{
    public int id;
    public string name;
    public string desc;
    public int goal;
    public string icon_name;
    public int reward_amount;
    public string reward_icon_name;
    public int width;
    public int height;
    public int reward_icon_width;
    public int reward_icon_height;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class Test06UIMissionCell : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI missionText;
    [SerializeField] TextMeshProUGUI descText;
    [SerializeField] Image cellIconImage;
    [SerializeField] Image rewardIconImage;
    [SerializeField] Button button;
    [SerializeField] GameObject doingGo;
    [SerializeField] GameObject completeGo;
    [SerializeField] Slider sliderValue;
    public System.Action onButtonClick;
    // Start is called before the first frame update
    void Start()
    {
       
        this.button.onClick.AddListener(() => {
            //doing 일때 미션을 모두 완료하면 reward icon 에서 버튼 생성
            //complete상태에서 버튼을 클릭하면 보상 아이템 획득
            // Debug.LogFormat("{0} clicked!",button);
            Debug.Log("보상을 획득하였습니다.");
        });
    }
    private void Update()
    {
        if(this.sliderValue.value == 1)
        {
           // Debug.Log("value = 1, missionCompleted!");
            this.doingGo.SetActive(false);
            this.completeGo.SetActive(true);
        }
    }
    public void Init(MissionData data)
    {

        //var atlas = AtlasManager.instance.GetAtlas("icon");
        //var sp = atlas.GetSprite(data.icon_name);
        //Debug.LogFormat("====> icon_name: {0}, sp: {1}", data.icon_name, sp);



        //   Debug.Log(data.id);
        this.missionText.text = data.name;
        // Debug.Log(data.icon_name);     
        this.descText.text = string.Format(data.desc, data.goal);
        var atlas = AtlasManager.instance.GetAtlas("icon");

        //var a = data.icon_name.Trim();
        //var b = "icon_coins_pouch".Trim();

        //Debug.LogFormat("{0},{1}: <color=yellow>{2}</color>", a, b, a == b);
        //icon 이미지 변경
        this.cellIconImage.sprite = atlas.GetSprite(data.icon_name);
        this.cellIconImage.SetNativeSize();
        Vector2 vector = new Vector2(data.width, data.height);
        this.cellIconImage.rectTransform.sizeDelta = vector;
        //보상 아이콘 이미지 변경
        this.rewardIconImage.sprite = atlas.GetSprite(data.reward_icon_name);
        this.rewardIconImage.SetNativeSize();
        this.rewardIconImage.rectTransform.sizeDelta = new Vector2(data.reward_icon_width, data.reward_icon_height);
    }
}
myoskin