이번에는 게임 중간부터 이어서 할수 있는 기능을 추가합니다. 지금까지는 씬이 변경된 후 변수의 값을 유지하기 위해 static 변수를 활용했습니다. static도 게임이 종료하면 없어지므로 데이터를 저장해서 다시 시작할때 불러서 사용하겠습니다.

저장할 데이터는 소지한 아이템수, 플레이어의 HP, 현재의 씬 이름, 배치된 아이템, 들어간 문의 번호, 열린 문, 쓰러뜨린 적입니다. 게임 데이터는 씬을 이동할 때 자동으로 저장되도록 합니다.

 

PlayerPrefs로 데이터 저장하기 및 불러오기

Unity가 제공하는 PlayerPrefs클래스를 사용하여 게임데이터를 저장하고 불러올수 있습니다.

int : PlayerPrefs.SetInt(키, 수치), PlayerPrefs.GetInt(키)

float: PlayerPrefs.SetFloat(키, 수치), PlayerPrefs.GetFloat(키)

string: PlayerPrefs.SetString(키, 수치), PlayerPrefs.GetString(키)

아이템 수 저장하기 및 불러오기 만들기

Item수는 itemKeeper클래스에서 관리하고 있어 itemKeeper스크립트에 다음 기능을 추가합니다.

ItemKeeper.cs
0.00MB

변수

키의 개수와 화살의 개수를 저장하는 변수입니다. 이건 이미 있었던 변수입니다.

public static int hasKeys = 0;          //열쇠 수
public static int hasArrows = 0;        //화살 소지수

Start()

PlayerPrefs 클래스를 이용 Keys와 Arrows의 저장된 값을 불러옵니다.

void Start()
{
    //아이템 불러오기
    hasKeys = PlayerPrefs.GetInt("Keys");
    hasArrows = PlayerPrefs.GetInt("Arrows");
}

SaveItem()

PlayerPrefs 클래스를 이용 Keys와 Arrows의 값을 저장합니다.

public static void SaveItem()
{
    PlayerPrefs.SetInt("Keys", hasKeys);
    PlayerPrefs.SetInt("Arrows", hasArrows);
}

 

플레이어 HP 저장하기및 불러오기 기능 만들기

HP는 PlayerController.cs에서 관리하고 HP를 저장하고 불러오는 기능을 추가합니다.

PlayerController.cs
0.01MB

시작시 PlayerPrefs클래스를 이용 HP를 읽어 저장합니다.

void Start()
{
	~생략
    hp = PlayerPrefs.GetInt("PlayerHP");
}

GetDamage()

피해를 입고 HP값이 변경되면 PlayerPrefs.SetInt메서드로 값을 저장합니다.

void GetDamage(GameObject enemy)
{
    if (gameState == "playing")
    {
        hp--;   //HP감소
        //HP 갱신
        PlayerPrefs.SetInt("PlayerHP", hp);
	~ 생략
    }
}

ItemData.cs의 OnTriggerEnter2D() 메써드

ItemData.cs
0.00MB

생명 아이템을 획득하고 hp가 변경되었을때 PlayerPrefs를 이용 hp를 저장합니다.

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.gameObject.tag == "Player")
    {
        if (type == ItemType.key)  {  }
        else if (type == ItemType.arrow) {   }
        else if (type == ItemType.life)   {
            //생명
            if (PlayerController.hp < 3)  {
                //HP가 3이하면 추가
                PlayerController.hp++;
                //HP 갱신
                PlayerPrefs.SetInt("PlayerHP", PlayerController.hp);
            }
        }
        //++++ 아이템 획득 연출 ++++
        //충돌 판정 비활성
        //아이템의 Rigidbody2D가져오기
        //중력 젹용
        //위로 튀어오르는 연출
        //0.5초 뒤에 제거
        //배치 Id 기록
    }
}

JSON을 사용해 씬의 상태 기록하기

아이템의 갯수는 PlayerPrefs를 사용하면 되지만 씬에 배치된 오브젝트는 저장할 수 없습니다.  예제에서는 JSON이라는 데이터 형식으로 배치된 데이터를 저장합니다.

JSON이란 텍스트 형식으로 쓰인 데이터 형식이빈다. 단순한 구조로 앱이나 인터넷에서 데이터 저장, 전달에 널리 사용됩니다.

JSON의 구체적인예

{
"hp":100,
"name":"유니",
"speed":10.3,
"isMoving":true
}

다룰수 있는 데이터형은 ,숫자,문자열,논리형, null, 배열 등입니다. {}로 감싼 데이터 자체를 값으로 가질 수도 있습니다.

유니티는 JsonUtility라는 클래스가 있어 쉽게JSON 형식을 사용할 수 있습니다.

배치 데이터를 저장하려면 JsonUtility 클래스를 사용 JSON형식(텍스트)으로 변환하고 PlayerPrefs 클래스를 활용 텍스트로 저장합니다, JSON자체는 텍스트이므로 PlayerPrefs클래스의 SetString메서드로 읽고 쓸수있습니다.

예제에서는 열린문, 열린상자, 획득한 아이템, 쓰러트린적 의 정보를 저장합시다. 저장하는 정보는 게임오브젝트를 식별할 수 있는 번호와 종류입니다. 번호는 9장까지 만들었던 Door, ItemBox, ItemData, EnemyController클래스의 arrnageID변수를 사용합니다. 종류는 각 게임오브젝트의 태그를 이용합니다.

 

배치된 정보를 기록하는 스크립트 만들기

JSON을 기록하려면 먼저 저장할 JSON과 같은 구조를 가진 클래스를 정의해야 합니다. SaveData라는 이름의 스크립트를 RoomManager폴더에 만들고 다음과 같이 작성합니다.

SaveData.cs
0.00MB

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

[System.Serializable]
public class SaveData
{
    public int arrangeId = 0;       //배치 ID
    public string objTag = "";      //배치된 오브젝트의 태그
}

[System.Serializable]
public class SaveDataList
{
    public SaveData[] saveDatas;    //SaveData 배열
}

[System.Serializable]는 이 클래스는 저장할 대상입니다를 의미합니다. JSON으로 만들기 위해 필요한 것이라고 합시다.

SaveData 클래스는 배치된 오브젝트 하나를 나타내고. SaveDataList는 이들을 여러개 배열로 저장하는 데이터입니다.

두 클래스는 JSON형식(텍스트) 데이터를 클래스로 변환했을 때의 형을 정의합니다.

 

다음은 JSON데이터를 읽거나 써서 배치된 데이터를 관리하는 스크립트를 만들어보겠습니다.

 SaveDataManager  스크립트를 RoomManager폴더에 만들고 RoomManager의 프리팹에 어태치합니다. 

SaveDataManager.cs
0.00MB

변수

SaveDataList클래스의 객체를 public static으로 선언합니다.

public static SaveDataList arrangeDataList;    //베치 데이터

Start메서드

 

 void Start() {
    //SaveDataList 초기화 
    arrangeDataList = new SaveDataList();
    arrangeDataList.saveDatas = new SaveData[] { };
    //씬 이름 불러오기
    string stageName = PlayerPrefs.GetString("LastScene");
    //씬 이름을 키로하여 저장 데이터 읽어오기
    string data = PlayerPrefs.GetString(stageName);
    if (data != "")   {
        //--- 저장 된 데이터가 존재할 경우  ---
        //JSON에서 SaveDataList로 변환하기
        arrangeDataList = JsonUtility.FromJson<SaveDataList>(data);
        for (int i = 0; i < arrangeDataList.saveDatas.Length; i++)  {
            SaveData savedata = arrangeDataList.saveDatas[i]; //배열에서 가져오기
            //태그로 게임 오브젝트 찾기
            string objTag = savedata.objTag;
            GameObject[] objects = GameObject.FindGameObjectsWithTag(objTag);
            for (int ii = 0; ii < objects.Length; ii++) {
                GameObject obj = objects[ii]; //배열에서 GameObject 가져오기
                //GameObject의 태그 확인하기
                if (objTag == "Door") {      //문 
                    Door door = obj.GetComponent<Door>();
                    if (door.arrangeId == savedata.arrangeId) {
                        Destroy(obj);  //arrangeId가 같으면 제거
                    }
                } else if (objTag == "ItemBox") {  //보물 상자
                    ItemBox box = obj.GetComponent<ItemBox>();
                    if (box.arrangeId == savedata.arrangeId) {
                        box.isClosed = false;   //arrangeIdd가 같으면 열기
                        box.GetComponent<SpriteRenderer>().sprite = box.openImage;
                    }
                }  else if (objTag == "Item") {     //아이템
                    ItemData item = obj.GetComponent<ItemData>();
                    if (item.arrangeId == savedata.arrangeId) {
                        Destroy(obj);   //arrangeId가 같으면 제거
                    }
                }
                else if (objTag == "Enemy") {      //적
                    EnemyController enemy = obj.GetComponent<EnemyController>();
                    if (enemy.arrangeId == savedata.arrangeId)  {
                        Destroy(obj);   //arrangeId가 같으면 제거
                    }
                }
            }
        }
    }
}

+ Recent posts