유니티 심화

LearnUGUI - Test06 [저장/불러오기]

다모아 2023. 9. 11. 15:29


Test06UIPageMission

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

public class Test06UIPageMission : MonoBehaviour
{
    [SerializeField]
    private Test06UIMissionScrollView uIMissionScrollView;
    [SerializeField]
    private Button btnSave;
    private string fileName = "mission_infos.json";
    private string path;
    private List<MissionInfo> missionInfos = new List<MissionInfo>();
    public Action onClick;
    public void Init()
    {
        this.path = string.Format("{0}/{1}", Application.persistentDataPath, this.fileName);

        this.btnSave.onClick.AddListener(() => {
            //Test06InfoManager.instnace.SaveInfo();
            this.Save();
        });

        if (this.IsNewbie())
        {
            List<MissionData> missionDatas = Test06DataManager.instance.GetMissionDataList();
            foreach(var data in missionDatas)
            {
                MissionInfo info = new MissionInfo(data.id, 0);
                this.missionInfos.Add(info);
            }
        }
        else
        {
            this.LoadMissionInfos();
        }

        this.uIMissionScrollView.Init(this.missionInfos);
    }

    private void LoadMissionInfos()
    {
        string json = File.ReadAllText(path);
        //역직렬화
       this.missionInfos = JsonConvert.DeserializeObject<MissionInfo[]>(json).ToList();
    }

    private bool IsNewbie()
    {
        Debug.Log(path);
        if(File.Exists(path))
        {
            return false;
        }
        else
        {
            return true;
        }
    }

    private void Save()
    {
        Debug.Log("Save");
        Debug.Log(Application.persistentDataPath);

        //직렬화
        //대상 MissionCell의 id와 count
        List<Test06UIMissionCell> cells = this.uIMissionScrollView.GetMissionCells();
        //직렬화 대상 객체 만들기
        List<MissionInfo> missionInfos = new List<MissionInfo>();
        foreach(Test06UIMissionCell cell in cells)
        {
            Debug.LogFormat("Id: {0}, Count: {1}", cell.Id, cell.Count);
            MissionInfo info = new MissionInfo(cell.Id, cell.Count);
            missionInfos.Add(info);
        }
        //직렬화
        string json = JsonConvert.SerializeObject(missionInfos);
        Debug.Log(json);

        //파일로 저장
        Debug.Log(path);

        File.WriteAllText(path, json);

        Debug.Log("<color=yellow>SAVED!</color>");

        EditorUtility.RevealInFinder(Application.persistentDataPath);
    }
}

 

Test06DataManager

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

public class Test06DataManager
{
    public static readonly Test06DataManager instance = new Test06DataManager();

    private Dictionary<int, MissionData> dicMissionDatas = new Dictionary<int, MissionData>();

    public void LoadMissionData()
    {
        TextAsset asset = Resources.Load<TextAsset>("mission_data");
        string json = asset.text;
        MissionData[] missionDatas = JsonConvert.DeserializeObject<MissionData[]>(json);
        this.dicMissionDatas = missionDatas.ToDictionary(x => x.id);
        Debug.LogFormat("{0}개의 MissionData로드 완료", this.dicMissionDatas.Count);
    }

    public List<MissionData> GetMissionDataList()
    {
        return this.dicMissionDatas.Values.ToList();
    }

    public MissionData GetMissionData(int id)
    {
        return this.dicMissionDatas[id];
    }
}

 

Test06UIMissionCell

using System.Collections;
using System.Collections.Generic;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;
public class Test06UIMissionCell : MonoBehaviour
{
    public enum eCellType
    {
        Doing, Done, Complete
    }

    private eCellType cellType;

    public eCellType CellType
    {
        get
        {
            return this.cellType;
        }
    }
    //mission_icon
    [SerializeField]
    private Image missionIcon;
    //txtMissionName
    [SerializeField]
    private TMP_Text txtMissionName;
    //txtMissionDesc
    [SerializeField]
    private TMP_Text txtMissionDesc;
    //complete_reward_icon
    [SerializeField]
    private Image completeRewardIcon;
    //doing_reward_icon
    [SerializeField]
    private Image doingRewardIcon;
    //doing_txtAmount
    [SerializeField]
    private TMP_Text doingTxtAmount;
    //complete_txtAmount
    [SerializeField]
    private TMP_Text completeTxtAmount;
    [SerializeField]
    private TMP_Text txtProgress;
    //Slider
    public Slider slider;
    //desc
    public string desc;
    private MissionData data;
    private MissionInfo info;

    public int Id
    {
        get
        {
            return this.data.id;
        }
    }

    private int count;
    public int Count
    {
        get
        {
            return this.count;
        }
    }
    public void Init(MissionInfo info)
    {
        this.LoadData(info);

        float progress = (float)this.info.count / this.data.goal;
        Debug.LogFormat("{0}, {1} <color=lime>{2}%</color>", this.data.id, this.data.name, progress);
        this.slider.value = progress;
    }

    public void Init(MissionData data)
    {
        this.LoadData(data);

        float progress = (float)this.info.count / this.data.goal;
        Debug.LogFormat("{0}, {1} <color=lime>{2}%</color>", this.data.id, this.data.name, progress);
        this.slider.value = progress;
    }

    private void LoadData(MissionInfo info)
    {
        this.info = info;
        this.data = Test06DataManager.instance.GetMissionData(info.id);
        Debug.Log(this.info.id);
        //MissionName
        this.txtMissionName.text = data.name;
        this.txtProgress.text = string.Format("{0} / {1}", this.info.count, this.data.goal);
        //Collect {0} Golds란 말이지 Debug.LogFormat("Collect {0} Golds", data.goal); 을 하면 되는데
        //Collect {0} Golds가 data.desc임
        this.desc = string.Format(data.desc, data.goal);
        //MissionDesc
        this.txtMissionDesc.text = this.desc;
        //doing_txtAmount
        this.doingTxtAmount.text = data.reward_amount.ToString();
        //complete_txtAmount
        this.completeTxtAmount.text = data.reward_amount.ToString();
        //SpriteAtlas 할당해주기
        SpriteAtlas atlas = Test06AtlasManager.instance.GetAtlas("Test06UIAtlas");
        //mission_icon
        this.missionIcon.sprite = atlas.GetSprite(data.icon_name);
        this.missionIcon.SetNativeSize();
        this.missionIcon.rectTransform.sizeDelta = new Vector2(data.mission_icon_width, data.mission_icon_height);
        //doing_reward_icon
        this.doingRewardIcon.sprite = atlas.GetSprite(data.reward_icon_name);
        this.doingRewardIcon.SetNativeSize();
        this.doingRewardIcon.rectTransform.sizeDelta = new Vector2(data.reward_icon_width, data.reward_icon_height);
        //complete_reward_icon
        this.completeRewardIcon.sprite = atlas.GetSprite(data.reward_icon_name);
        this.completeRewardIcon.SetNativeSize();
        this.completeRewardIcon.rectTransform.sizeDelta = new Vector2(data.reward_icon_width, data.reward_icon_height);
    }

    private void LoadData(MissionData data)
    {
        this.data = data;
        Debug.Log(this.data.id);
        //MissionName
        this.txtMissionName.text = data.name;
        this.txtProgress.text = string.Format("{0} / {1}", this.info.count, this.data.goal);
        //Collect {0} Golds란 말이지 Debug.LogFormat("Collect {0} Golds", data.goal); 을 하면 되는데
        //Collect {0} Golds가 data.desc임
        this.desc = string.Format(data.desc, data.goal);
        //MissionDesc
        this.txtMissionDesc.text = this.desc;
        //doing_txtAmount
        this.doingTxtAmount.text = data.reward_amount.ToString();
        //complete_txtAmount
        this.completeTxtAmount.text = data.reward_amount.ToString();
        //SpriteAtlas 할당해주기
        SpriteAtlas atlas = Test06AtlasManager.instance.GetAtlas("Test06UIAtlas");
        //mission_icon
        this.missionIcon.sprite = atlas.GetSprite(data.icon_name);
        this.missionIcon.SetNativeSize();
        this.missionIcon.rectTransform.sizeDelta = new Vector2(data.mission_icon_width, data.mission_icon_height);
        //doing_reward_icon
        this.doingRewardIcon.sprite = atlas.GetSprite(data.reward_icon_name);
        this.doingRewardIcon.SetNativeSize();
        this.doingRewardIcon.rectTransform.sizeDelta = new Vector2(data.reward_icon_width, data.reward_icon_height);
        //complete_reward_icon
        this.completeRewardIcon.sprite = atlas.GetSprite(data.reward_icon_name);
        this.completeRewardIcon.SetNativeSize();
        this.completeRewardIcon.rectTransform.sizeDelta = new Vector2(data.reward_icon_width, data.reward_icon_height);
    }

    public void ApplyCount(int count)
    {
        this.info.count = count;
        Debug.LogFormat("{0}/{1} 미션을 {2}개 진행했습니다.", this.data.id, this.data.name, this.info.count);
        this.count = count;
        //0 ~ 1
        float percent = (float)this.info.count / this.data.goal;
        this.slider.value = percent;

        this.txtProgress.text = string.Format("{0} / {1}", this.info.count, this.data.goal);
    }

    public int GetGoal()
    {
        if (this.data == null) return -1; //커스텀 인스펙터에서 계속 호출하므로 아직 data가 없는 상태
        return this.data.goal;
    }
}

 

UIMissionCellOnInspector

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(Test06UIMissionCell))]
public class UIMissionCellOnInspector : Editor
{
    private int sliderValue;
    public override void OnInspectorGUI() // update처럼 호출
    {
        base.OnInspectorGUI(); //기존꺼

        Test06UIMissionCell cell = this.target as Test06UIMissionCell; //커스텀 에디트 대상 컴포넌트

        GUILayout.Space(10); //10픽셀 띄우기

        //플레이를 했을 때만 보여주기
        if (Application.isPlaying)
        {
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label("0");
            this.sliderValue = EditorGUILayout.IntSlider(this.sliderValue, 0, cell.GetGoal());
            //GUILayout.Label("Test"); //추가한거
            GUILayout.Label(cell.GetGoal().ToString());
            EditorGUILayout.EndHorizontal();

            if (GUILayout.Button("Apply Count"))
            {
                Debug.Log("미션 진행 수를 반영합니다.");
                cell.ApplyCount(this.sliderValue); // Test06UIMissionCell의 ApplyCount메서드 호출
            }
        }
    }
}

 

MissionInfo

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

public class MissionInfo
{
    public int id;
    public int count;
    public int state;

    public MissionInfo(int id, int count)
    {
        this.id = id;
        this.count = count;
    }
}

 

MissionData

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 mission_icon_width;
    public int mission_icon_height;
    public int reward_amount;
    public string reward_icon_name;
    public int reward_icon_width;
    public int reward_icon_height;
}

 

Test06AtlasManager

using System.Collections;
using System.Collections.Generic;
using UnityEditor.U2D;
using UnityEngine;
using UnityEngine.U2D;

public class Test06AtlasManager : MonoBehaviour
{
    public static Test06AtlasManager instance;

    [SerializeField]
    private string[] arrAtlasNames;

    private Dictionary<string, SpriteAtlas> dicAtlas = new Dictionary<string, SpriteAtlas>();
    private void Awake()
    {
        if(instance != null && instance != this)
        {
            Destroy(this.gameObject);
        }    
        else
        {
            instance = this;
        }

        DontDestroyOnLoad(this.gameObject);
    }

    public void LoadAtlasData()
    {
        foreach (string atlasName in arrAtlasNames)
        {
            SpriteAtlas asset = Resources.Load<SpriteAtlas>(atlasName);
            this.dicAtlas.Add(atlasName, asset);
        }
        Debug.LogFormat("{0}개의 Atlas를 로드했습니다.", this.dicAtlas.Count);
    }

    public SpriteAtlas GetAtlas(string atlasName)
    {
        return this.dicAtlas[atlasName];
    }
}

 

Test06UIMain

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

public class Test06UIMain : MonoBehaviour
{
    [SerializeField]
    private Test06UIPageMission uIPageMission;

    private void Start()
    {
        Test06InfoManager.instnace.LoadMissionInfo();
        Test06AtlasManager.instance.LoadAtlasData();
        Test06DataManager.instance.LoadMissionData();

        this.uIPageMission.Init();
    }
}

 

Test06UIMissionScrollView

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Test06UIMissionScrollView : MonoBehaviour
{
    [SerializeField]
    private GameObject uiMissionCellPrefab;
    //위치지정
    [SerializeField]
    private Transform contentTr;

    private List<Test06UIMissionCell> cellList = new List<Test06UIMissionCell>();

    public void Init(List<MissionInfo> missionInfos)
    {
        foreach(var missionInfo in missionInfos)
        {
            this.CreateUIMissionCell(missionInfo);
        }
    }

    private void CreateUIMissionCell(MissionInfo info)
    {
        //프리팹 만들자
        GameObject go = Instantiate<GameObject>(this.uiMissionCellPrefab, this.contentTr);
        //cell에다가 컴포넌트 넣어주기
        Test06UIMissionCell cell = go.GetComponent<Test06UIMissionCell>();
        cell.Init(info);

        this.cellList.Add(cell);
    }

    private void CreateUIMissionCell()
    {
        //데이터 받아와서
        List<MissionData> missionDatas = Test06DataManager.instance.GetMissionDataList();
        //foreach 돌리면서 프리팹 만들기
        foreach (MissionData missionData in missionDatas)
        {
            //null 값의 Test06UIMissionCell 만들어줘서 넣어주자고
            Test06UIMissionCell cell = null;
            //프리팹 만들자
            GameObject go = Instantiate<GameObject>(this.uiMissionCellPrefab, this.contentTr);
            //cell에다가 컴포넌트 넣어주기
            cell = go.GetComponent<Test06UIMissionCell>();
            //Init
            cell.Init(missionData);
            this.cellList.Add(cell);

            Debug.LogFormat("data.icon_name : {0}", missionData.icon_name);
            Debug.LogFormat("{0}, {1}, {2}%", missionData.id, missionData.name, cell.slider.value);
            Debug.LogFormat("{0}", cell.desc);
        }
    }

    public List<Test06UIMissionCell> GetMissionCells()
    {
        return this.cellList;
    }
}