---
# System prepended metadata

title: 外部存檔
tags: [Unity 存檔]

---

###### tags: `Unity 存檔`
[toc]
# 外部存檔
存檔其實就是在本地端把需要儲存的資料寫進檔案裡。所以會需要用到開檔/讀檔的功能。

## 序列化

序列化程序會將物件轉換成位元組資料流，以將物件儲存或傳輸到記憶體、資料庫或檔案。簡單來說就是將資料轉換成可以傳輸的格式。

- Binary
    
    - 較不易閱讀

- XML

- json
    
    - 較好閱讀且好用的儲存格式。

## 反序列化

其實就是將轉化成傳輸格式的資料轉回原本的資料。

## 作法

1. 創建一個class，列出所有需要儲存的資料。

    [Data Class 不能繼承 MonoBehaviour ](https://answers.unity.com/questions/1308015/jsonutility-cannot-deserialize-json-to-new-instanc.html)
    不能繼承 `MonoBehaviour`，意味著這個程式碼不能掛在物件底下，也不能使用 `MonoBehaviour` 提供的 `start()` 、 `Update()` 功能。但這並不會影響任何事情，因為我們只需要很單純的創建一個Data Class，不需要掛在任何物件底下。

```csharp=
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


[System.Serializable]   
//添加此行來讓PlayerData是可序列化的資料。 

public class PlayerData //class不能繼承MonoBehaviour。 Class必須是public
{
    public string Name;
    public int Level;
    public bool TakeBook, TakeCandy;
    public Vector3 PlayerPosition;
    
    public PlayerData()    //default constructure ((看個人決定要不要寫反正我寫了
    {
        Name = "No Name";
        Level = 0;
        TakeBook = false;
        TakeCandy = false;
        PlayerPosition = new Vector3(0, 1, 0);
    }
}

```

2. 利用剛剛建立的Data class 來賦予值，最後再把Data class轉換成json來儲存。將json轉換成原本的資料來讀取。

- 創建 / 覆蓋檔案，寫入全部的文字

```csharp=
File.WriteAllText(檔案位置,string 要寫入的string格式);
```

- 讀所有檔案的文字

```csharp=
File.ReadAllText(檔案位置)
```

- 序列化
    
    轉換成json格式
        
    ```csharp=
    string json_data = JsonUtility.ToJson(Class_Data , true);
    ```
- 反序列化
    
    將json格式轉回原本的資料
        
    ```csharp=
     Class_Data data = JsonUtility.FromJson<Class_Data>(string json_data);  
    ```

```csharp=
using UnityEngine;
using System.IO;
using UnityEngine.UI;

public class SaveLoadSystem : MonoBehaviour
{
    public InputField InputName, InputLevel;
    public Toggle ToggleCandy, ToggleBook;
    public GameObject player;

    public void Save()
    {
        PlayerData data = new PlayerData();
        data.Name = InputName.text;
        data.Level = int.Parse(InputLevel.text);
        data.TakeCandy = ToggleCandy.isOn;
        data.TakeBook = ToggleBook.isOn;
        data.PlayerPosition = player.transform.position;

        string json_data = JsonUtility.ToJson(data, true);  //將data轉換成json。序列化。
        File.WriteAllText(Application.dataPath + "/PlayerData.sav", json_data);
        //把轉換成json的格式內容寫進PlayerData.sav檔案
        //副檔名可隨意取
        //若在Application.dataPath底下沒有PlayerData.sav檔案則創建，有則覆蓋
    }

    public void Load()
    {
        string json_data = File.ReadAllText(Application.dataPath + "/PlayerData.sav");  
        //將檔案的json內容全部讀出來並存到json_data這個變數，讀出的文字是json格式
        
        PlayerData data = JsonUtility.FromJson<PlayerData>(json_data);  
        //將這個json格式的字串轉換成PlayerData並用PlayerData Class儲存。

        InputName.text = data.Name;
        InputLevel.text = data.Level.ToString();
        ToggleCandy.isOn = data.TakeCandy;
        ToggleBook.isOn = data.TakeBook;
        player.transform.position = data.PlayerPosition;
    }
}

```

3. 創建的檔案

- Application.dataPath 

    儲存的位置會在 `專案目錄/Asset` 裡面

    ![](https://i.imgur.com/plfottQ.png)
    
## 成果
{%youtube YOBIFbOx7qI %}