[UGUI 연습] 데이터 저장, 불러오기 연습
2023. 9. 9.

-데이터 저장, 불러오기 연습을 하기위해 이전 포스팅 씬을 수정하려 한다.
 
먼저 구현해야 할 내용을 정리해보자.
 
- 신규 유저인지 기존 유저인지 확인한다.
-신규 유저라면, missionData.json에 있는 값의 진행 정도는 다 0으로 비워져야한다 : 초기화하자.
-기존 유저의 유저의 정보를 불러오도록 한다. 유저마다 진행 정도가 다를 것이다.
=> 유저의 정보를 담을 info.json가 있어야 한다. info.json이 없다면 생성하도록 코드 작성.
 
 
유저의 미션상태 정보는 다음과 같이 저장된다.
 
상태
0 : Doing (진행중)
1 : Done (완료 했지만 보상 아직 안받음)
2 : Complete (완료 했고 보상도 받음)
 

구현할 내용

이를 테스트하기 위해서 다음과 같이 수정했다.
-저장하기 버튼을 생성하고, slider 위에 텍스트로  value를 나타내도록 한다. 마우스로 value를 설정할 수 있다.
 
-------------------------------------------------------------------------------------------------------------------------------------------------------
ㅋㅋ 다 마무리하고 포스팅 끝낸 줄 알았는데 reward text안바꿔서 코드 수정을 좀 했다..한줄.

cell에 마지막 줄 추가

물론 rewardText는 넣어줘야한다. serializefield로 넣어줬다.
-------------------------------------------------------------------------------------------------------------------------------------------------------

infoManager 생성

 

main/ UImain

-main을 다음과 같이 작성했다. start에서 액션을 불러오므로 UIMain에서 start함수를 awake로 변경하고 코드를 수정했다.(start는 바로 호출되므로 start에서 알려주기 전에 awake에서 익명 메서드를 갖고있어야 참조할 수 있게 되기 때문이다.)
=> 뭔가 말이 안깔끔한데 뭐라고 써야될지 모르겠다...
 

스크롤뷰에서 데이터를 저장하도록 수정
cell의 Init을 수정해 기존 유저일 떄 인포를 가져오도록 수정한다.

-인포를 가져와 슬라이더에 나타내도록 값을 수정한다.

데이터 불러오기 결과

 

데이터 저장

 

cell에 멤버변수로 missionInfo를 선언해서 세이브 버튼을 누르면 onclick이벤트로 cell의 멤버 변수를 받으려고 했더니 못받아서 onclick한 걸 이벤트로 cell에 알려주도록 대리자를 새로 작성했다.

UIMain 코드수정

 

cell의 Init수정
InfoManager에 SaveMissionInfo 메서드 추가

 

저장 버튼을 누르면 저장됨. 다시 실행 시 저장된 것을 확인

-json이 잘 바뀌는지도 확인 완료했다.

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

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

    private Dictionary<int, MissionInfo> dicMissionInfos = new Dictionary<int, MissionInfo>();
    public bool LoadMissionInfo(){
        if (File.Exists("./Assets/Resources/mission_info.json"))//파일 존재여부 확인
        {
           string json = File.ReadAllText("./Assets/Resources/mission_info.json");
            Debug.Log("기존 유저 입니다. 정보를 로드합니다.");// 존재한다면 기존유저
            //missionInfo를 가져온다.
            MissionInfo[] missionInfos = JsonConvert.DeserializeObject<MissionInfo[]>(json);//MissionInfo에 json 가져옴
            this.dicMissionInfos = missionInfos.ToDictionary(x => x.id);

            return true;
     }
        else
        {//파일 생성
            Debug.Log("유저 정보가 없습니다. 신규 유저의 새로운 미션 정보를 등록합니다.");
            //새로운 missionInfo 생성
            
            return false;
        }
    }

    public List<MissionInfo> GetMissionInfo()
    {
        return this.dicMissionInfos.Values.ToList();
    }

    public void SaveMissionInfo(MissionInfo info)
    {
       
        List<MissionInfo> missionInfoList = this.dicMissionInfos.Values.ToList();      
        for(int i=0; i<missionInfoList.Count;i++)
        {
           
            if (missionInfoList[i].id == info.id)
            {
                Debug.Log(info.id);
                missionInfoList.RemoveAt(i);
                //missionInfoList.Add(info);
                missionInfoList.Insert(i,info);
            }
        }
        
        //직렬화
        string json = JsonConvert.SerializeObject(missionInfoList);
        File.WriteAllText("./Assets/Resources/mission_info.json", json);
        Debug.Log("Info 저장");
    }
}

 

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] TextMeshProUGUI rewardText;
    [SerializeField] Image cellIconImage;
    [SerializeField] Image rewardIconImage;
    [SerializeField] Button getRewardButton;
   
    [SerializeField] GameObject doingGo;
    [SerializeField] GameObject completeGo;
    [SerializeField] Slider sliderValue;
    public MissionInfo missionInfo = new MissionInfo();
    public int id;

    private Test06UIMain uiMain;
    private float value;
    
    // Start is called before the first frame update
    void Awake()
    {
        this.uiMain = FindAnyObjectByType<Test06UIMain>();
      
        this.getRewardButton.onClick.AddListener(() => {
            //doing 일때 미션을 모두 완료하면 reward icon 에서 버튼 생성
            //complete상태에서 버튼을 클릭하면 보상 아이템 획득
            // Debug.LogFormat("{0} clicked!",button);
            Debug.Log("보상을 획득하였습니다.");
           
            this.missionInfo.state = 2;
        });

     
    }
   
    public void Init(MissionData data,MissionInfo info)
    {//기존유저
     
        this.sliderValue.onValueChanged.AddListener((val) => {

            if (val == this.sliderValue.maxValue)
            {
                Debug.Log("missionCompleted!");
                this.doingGo.SetActive(false);
                this.completeGo.SetActive(true);
                this.missionInfo.state = 1;
            }
            this.missionInfo.count = (int)val;
            if (val != this.value)//데이터 로드했을 때 값이랑 다르면
            {
                this.uiMain.onSaveButtonClicked = () => {
                    this.missionInfo.id = info.id;
                    //Debug.LogFormat("id:{0},count:{1},state:{2}",this.missionInfo.id,this.missionInfo.count,this.missionInfo.state);
                    InfoManager.instance.SaveMissionInfo(this.missionInfo);
                };
            }
            else
            {
                Debug.Log("value not changed");
            }
        });
       
        this.missionText.text = data.name;   
        this.descText.text = string.Format(data.desc, data.goal);
        var atlas = AtlasManager.instance.GetAtlas("icon");

        //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);

        this.rewardText.text = data.reward_amount.ToString();

        //기존 유저이므로 인포를 가져온다.
        this.sliderValue.maxValue = data.goal;
        this.value = info.count;
        this.sliderValue.value = value;
        // Debug.LogFormat("data: {0},value: {1} /maxValue: {2}", data.name,this.sliderValue.value,this.sliderValue.maxValue);
       

    }
  
    public void newInit(MissionData data)
    {
        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");

        //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);

        this.rewardText.text = data.reward_amount.ToString();
    }
}

 

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


public class Test06Main : MonoBehaviour
{
    private bool isInfoExist;
    public System.Action onLoadExistInfo;
    public System.Action onLoadNewInfo;

    // Start is called before the first frame update
    void Start()
    {
        this.isInfoExist = InfoManager.instance.LoadMissionInfo();
        if (this.isInfoExist)
        {//기존 유저라면
            //데이터 로드
            this.onLoadExistInfo();
        }
        else
        {//신규 유저라면
         //데이터 초기화
            this.onLoadNewInfo();
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
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>();
    
    //  private List<MissionData> data = new List<MissionData>();

    // 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();
        List<MissionInfo> missionInfo = InfoManager.instance.GetMissionInfo();//기존 유저이므로 인포를 가져옴
        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>());
           // Debug.Log(missionInfo[i].id);
            this.uiCellList[i].Init(data[i],missionInfo[i]);//매개변수를 통해 데이터 전달, 미션 정보 전달
            
        }
      

    }
    public void newInit()
    {
        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].newInit(data[i]);//매개변수를 통해 데이터 전달
        }
    }

}
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.U2D;
public class Test06UIMain : MonoBehaviour
{
    [SerializeField] Test06UIMissionCell missionCell;
    [SerializeField] Test06UIScrollView scrollView;
    [SerializeField] Test06Main main;
    public Button saveDataButton;
    public System.Action onSaveButtonClicked;
    MissionInfo info;
    // Start is called before the first frame update
    void Awake()
    {
        AtlasManager.instance.LoadAtlases();

        this.main.onLoadExistInfo = () => {        
            DataManager.instance.LoadMissionData();
            this.scrollView.Init();
        };
        
        this.main.onLoadNewInfo = () =>
        {
            
            DataManager.instance.LoadMissionData();
            this.scrollView.newInit();
            //초기화하도록 수정
        };

        this.saveDataButton.onClick.AddListener(() =>
        {
            this.onSaveButtonClicked();//cell에 알려줌
        });

        // SpriteAtlas atlas = AtlasManager.instance.GetAtlas("icon");
        //Sprite[] arr = new Sprite[atlas.spriteCount];
        //var cnt = atlas.GetSprites(arr);
        //Debug.LogFormat("cnt : {0}", cnt);
        //for (int i = 0; i < arr.Length; i++)
        //{
        //    var sp = arr[i];
        //    Debug.LogFormat("i: {0} , sp -> {1}", i, sp);

        //    var a = sp.name.Replace("(Clone)", "");

        //    if (a == "icon_coins_pouch") {
        //        Debug.LogFormat("<color=lime>==> {0}</color>", a);
        //    }
        //}

        //var sp1 = atlas.GetSprite("icon_coins_pouch");
        //Debug.LogFormat("=============> <color=yellow>{0}</color>", sp1);



        //var json = Resources.Load<TextAsset>("mission_data").text;
        //Debug.LogFormat("==> {0}", json);

        //var con = json.Contains("icon_coins_pouch");
        //Debug.LogFormat("===========> {0}", con);

        ////---------------------- 여기부터 문제 생김 -----------------------------
        //var arr1 = JsonConvert.DeserializeObject<MissionData[]>(json);
        ////----------------------------------------------------------------------
        ////foreach (var aa in arr1)
        ////{
        ////    Debug.LogFormat("<color=cyan>=====> {0}, {1}, {2}</color>", aa.icon_name, aa.icon_name.Equals("icon_coins_pouch"), aa.icon_name == "icon_coins_pouch");
        ////}

        //string iconName = arr1[0].icon_name;

        //Debug.LogFormat(iconName);
        //Debug.LogFormat("icon_coins_pouch");
        //Debug.LogFormat("{0}", iconName.TrimStart() == "icon_coins_pouch");

        //for (int i = 0; i < iconName.Length; i++)
        //{
        //    char c = iconName[i];
        //    Debug.LogFormat("====>>>>> {0}, {1}", iconName[i], (int)c);
        //}


        //var dic = arr1.ToDictionary(x => x.id);
        //var data = dic[1000];
        //Debug.LogFormat("===> {0}, ==> {1}", data.icon_name, data.icon_name == "icon_coins_pouch");

    }
 
}
myoskin