9 Kasım 2016 Çarşamba

Unity3D: Save / Load Data(JSON)



Başlangıç

Unity3D de oyun/uygulama içinde veri kaydetmek istediğimizde Unity bize PlayerPrefs gibi bir seçenek sunuyor. Ben bundan farklı olarak .json dosyası oluşturmak ve buradan verileri okumakla ilgili bir örnek paylaşacağım.

Bu şekilde daha organize bir data yapısı kullanabilirsiniz.

Gereksinimler

NewtonSoft.Json : Bu linkden indireceğiniz dll dosyasını Assets>Plugins içine atınız. Yada ReadAndWriteJson.unitypackage linkinden indireceğiniz unitypackage dosyasını açmış olduğunuz boş bir projeye import edip oradan alabilir ve yapmış olduğum örneği inceleyebilirsiniz.


Yaptığım örnekde Scene'e, 2 tane InputField, 2 tane Button, 1 tane Text ekledim. Bir tane boş GameObject ekledim. GameObject için FileOperations adında bir tane script oluşturdum.


FileOperations.cs içinde UI elementleri için field ları oluşturalım.

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

public class FileOperations : MonoBehaviour
{

    public Button LoadBtn;
    public Button SaveBtn;
    public Text text;

    
    private SaveData saveData;

    public InputField IdText;
    public InputField NameText;
}

Scene içerisinde bulunan ilgili UI elementlerini Hierarchy de FileOperations.cs da bulunan ilgili yerlere sürükleyip bırakalım. UI butonlar için ilgili event listenerları ekleyelim.

public void Awake()
{
    LoadBtn.onClick.AddListener(LoadGameBtnListener);
    SaveBtn.onClick.AddListener(SaveGameBtnListener);        
}

private void LoadGameBtnListener()
{
}

private void SaveGameBtnListener()
{
}

Save ve Read işlemlerini yapmak için Application.persistentDataPath kullanıyoruz. Kullanacağımız data dosyasının ismi SaveData.json olsun. Bu durumda dosya adresimiz aşağıdaki gibi olacak ve bunu Awake içine ekleyelim.

private string fileName;

public void Awake()
{
    .......
    fileName = Application.persistentDataPath + "/SaveData.json";
}

Application.persistentDataPath adresi PC için C:\Users\[UserName]\AppData\LocalLow\[CompanyName]\[ProductName] şeklindedir. Bu adresi kendi PC nizde  Debug.Log(Application.persistentDataPath) yazarak görebilirsiniz.

Şimdi SaveData.json dosyasının önceden yaratılıp yaratılmadığına bakmak için Awake içine ChechDataFile metodu nu çağıralım. Bu metod json dosyanız oyununuz/uygulamanız ilk çalıştırıldığında yaratılmadığı için yaratacak ve sonraki çalıştırmalarda yeni bir dosya yaratılmasını önleyecek.

public void Awake()
{
    .......
    ChechDataFile();
}

private void ChechDataFile()
{
    try
    {
        if(!File.Exists(fileName))
        {
            FileStream fs = File.Create(fileName);
            fs.Close();
        }
    }
    catch (Exception e)
    {
        Debug.Log("Exeption: " + e);
    }
}


Şimdi saklayacağımız veri ile ilgili scriptimiz için SaveData.cs yaratalım. Bu Script'i aşağıdaki gibi yazalım. Json Dosyamız bu scriptler üzerinde Serialize/Deserialize edilecek. Yani içeride kullanacağımız veri yapılarına dönüştürülecek. Burada InventoryItemlar'ı listeleyeceğiz. Her item'ın bir ID ve Name değeri olacak. Bu itemlar bir liste içerisinde tutulacak.

using System.Collections.Generic;

public class SaveData
{
    public List<InventoryItem> Items { get; set; }
}

public class InventoryItem
{
    public int ID { get; set; }
    public string Name { get; set; }
}


FileOperations.cs içerisine yaratılacak json dosyasını okuyup string değerini alacağımız Metodu ekleyelim.

private string saveDataJson;

private void ReadDataFile()
{
    saveDataJson = string.Empty;
    
    try
    {
        if(File.Exists(fileName))
        {
            saveDataJson = File.ReadAllText(fileName);
        }
    }
    catch (Exception e)
    {
        Debug.Log("Exeption: " + e);
    }
}


Load butonuna basıldığı zaman aşağıdaki işlemleri yapsın ve ekrana json dosyamızın içeriğini yazdırsın.
private void LoadGameBtnListener()
{
    ReadDataFile();

    text.text = saveDataJson;
}


Ekran üzerinde ID kısmına rakam ve Name kısmına isim yazdığımızda Save butonuna basacağız ve bu verileri json dosyamıza kaydedeceğiz. Aynı zamanda json dosyamızın son halini ekrana yazdıracağız.

private void SaveGameBtnListener()
{
    ReadDataFile();

    if(IdText.text == string.Empty || NameText.text ==string.Empty)
    {
        return;
    }

    int x = 0;

    if (Int32.TryParse(IdText.text, out x) == false)
    {
        return;
    }

    if (saveDataJson != string.Empty)
    {
        saveData = JsonConvert.DeserializeObject<SaveData>(saveDataJson);
    }
    else
    {
        saveData = new SaveData();
        saveData.Items = new List<InventoryItem>();
    }

    InventoryItem inventoryItem;

    inventoryItem = saveData.Items.Find(item =< item.ID == Int32.Parse(IdText.text));

    if(inventoryItem == null)
    {
        inventoryItem = new InventoryItem();
        inventoryItem.ID = Int32.Parse(IdText.text);
        inventoryItem.Name = NameText.text;
        saveData.Items.Add(inventoryItem);
    }
    else
    {
        //Update Data
        inventoryItem.Name = NameText.text;
    }
        
    saveDataJson = JsonConvert.SerializeObject(saveData);

    try
    {
        File.WriteAllText(fileName, saveDataJson);
    }
    catch (Exception e)
    {
        Debug.Log("Exeption: " + e);
    }

    LoadGameBtnListener();
}

Bu projenin çalışır halini ReadAndWriteJson.unitypackage linkinden indireceğiniz unitypackage dosyasını boş bir Unity projesi içine import edip inceleyebilirsiniz.