Skip to content

develop SaveLoad

pianop edited this page Mar 11, 2023 · 17 revisions

유저 게임 데이터의 저장과 불러오기를 관리

Json 간략 설명

  • Json은"dataName": value 형태로 이루어져있고 문자열은 ""으로 감싸주어야합니다.
  • Json가 지원하는 자료형으로는 number(int, float), string, bool, object, array, null 등이 있습니다.

TODO:

목차

DefaultUserData.json

역할: 게임 첫 시작 혹은 데이터 리셋 시 불러올 기본 게임 데이터

image
Resources/GameData/DefaultUserData.json 파일

public class UserData
{
    public int Gold;
    public int[] Options;
    public int[] PowerUps;
    public bool[] Achievements;
    public bool[] Collection;
    public bool[] UnlockStages;
}

Json에서 사용한 변수의 이름과 같이 이름들을 설정해주어야 뒤에 나올 JsonUtility.FromJson(...)으로 파싱이 가능

UserDataManager

  • 역할: 유저의 게임 데이터에 대해 저장, 리셋, 불러오기, 불러온 데이터를 UserInfo클래스의 UserDataSet 변수에 파싱

Awake()에서 싱글톤 패턴 적용, DontDestroyOnLoad적용 , SavePath = Application.persistentDataPath + "/";으로 할당.
Start()에서 저장 파일이 있는지 확인, 없으면 위의 DefaultUserData를 불러와 새로 저장 파일 생성(DataReset), 있다면 기존 파일 불러오기

public void SaveData()
{
    string data = JsonUtility.ToJson(UserInfo.instance.UserDataSet);
    File.WriteAllText(SavePath + "UserSaveData.json", data);
}

public void LoadData()
{
    string data = File.ReadAllText(SavePath + "UserSaveData");
    UserInfo.instance.UserDataSet = JsonUtility.FromJson<UserData>(data);
}

public void DataReset()
{
    TextAsset textData = Resources.Load("GameData/DefaultUserData") as TextAsset;
    UserInfo.instance.UserDataSet = JsonUtility.FromJson<UserData>(textData.text);
    SaveData();
}

여기서 UserInfo.instance.UserDataSet은 위의 UserData타입임

외부 게임 데이터 파일 로드

public bool LoadData(string dataPath)
{
    string data = File.ReadAllText(dataPath);
    UserData tempData;
    try
    {
        tempData = JsonUtility.FromJson<UserData>(data);
    }
    catch (ArgumentException e)
    {
        return false;
    }

    UserInfo.instance.UserDataSet = tempData;
    SaveData();

    return true;
}

LoadData함수에 인자로 파일의 경로를 넣어줄 경우 해당 파일을 읽어와서 현재 저장 파일에 덮어쓴다.
파싱 실패시(잘못된 파일일 경우) false, 성공시 true 반환

UserInfo

  • 역할: 진행중인 게임 데이터(골드, 해금, 업적, 강화 현황 등)을 변수로 가지 해당 정보들의 업데이트와 무기, 악세서리, 캐릭터, 스테이지 등의 해금 유무를 알수 있게 하는 역할을 담당

Awake()에서 싱글톤 패턴 적용

void UpdateColldection(int collectionIndex)
{
    UserDataSet.Collection[collectionIndex] = true;
    UserDataManager.instance.SaveData();
}

collection, Achievement, Character는 위와 같이 해당 index를 넣어주면 유저 데이터가 바뀌도록 구현함, collection의 경우 무기와 악세서리 index를 넘겨주는 편이 더 쉬운 경우가 있을 거라 생각해서 아래의 함수를 추가해놓음.

void UnlockWeapon(int weaponIndex)
{
    UserDataSet.Collection[(weaponIndex << 1) | 1] = true;
    UserDataManager.instance.SaveData();
}
void UnlockAccessory(int accessoryIndex)
{
    UserDataSet.Collection[accessoryIndex + jumpAccessory] = true;
    UserDataManager.instance.SaveData();
}

배열 안의 수식은 해당 장비의 index로 collection 상에서의 index에 찾아가는 공식임
(순서가 궁금하다면 Script/Menu/CollectionItemInfo.cs 참고)

bool IsWeaponUnlock(int weaponIndex)
{
    return UserDataSet.Collection[(weaponIndex << 1) | 1];
}
bool IsAccessoryUnlock(int accessoryIndex)
{
    return UserDataSet.Collection[accessoryIndex + jumpAccessory];
}

반대로 해당 index의 장비가 해금 되었는지 쉽게 찾을 수 있도록 수식을 적용한 함수를 만들어줌.
character나 stage의 해금 유무는 index로 바로 접근해도 되기에 따로 함수를 만들어주지 않음

SystemDataLoad

image
image

public void LoadSystemData()
{
    string filePath = EditorUtility.OpenFilePanel("Json Explorer", "", "json");
    bool IsErrorFile;
    try
    {
        IsErrorFile = !UserDataManager.instance.LoadData(filePath);
    }
    catch (ArgumentException)
    {
        return;
    }

    WarningPanel.SetActive(false);
    if (IsErrorFile)
    {
        LoadParsingError();
    }
    else
    {
        SceneManager.LoadScene("MainScreen");
    }
}

MainScreen에서 Option -> data recovery -> System Data Load 클릭시 위의 경고 문구가 뜨고 Load를 누를 시 위의 LoadSystemData 함수가 호출, File Explorer로 연결된다.
image
다음과 같이 탐색 창이 나타난다.
위의 코드에서 try catch문은 파일 탐색창을 그냥 닫았을 경우를 처리한다.

위의 EditorUtility.OpenFilePanel 사용법)

public static string OpenFilePanel(string title, string directory, string extension);

Clone this wiki locally