# Save System

## How it's work

namespace **`Game.Core;`**

{% hint style="success" %}
Save system is automated, no need to call Save() or Load() methods on iOS/Android. It will be called automaticaly on OnApplicationFocus(bool) event (on mobile devices when player return to home to close game it raises).

\
On PC you should call Save() manualy when neccessary, because no guaranty that OnApplicationFocus(bool) will be executed by player.
{% endhint %}

{% hint style="info" %}
Save system is powered with **BinaryFormatter and NewtonsoftJson**, that serialize and desialize data.

You can find SaveBinarySerializer.cs in:\
**Assets\_Main\Scripts\Common\SaveSystem\Serializers**

Also you can implement your own serializer with ISaveSerializer.cs interface.\
To change serializer -> set it in SaveSystem.cs code (***field saveSerializer***)
{% endhint %}

* You can access SaveSystem any way in code and take data by **Data** property.\
  **Data** is SaveData class that holds all neccessary data that should be stored between game sessions.
* You can delete save by different ways:

1\. pressing 'Delete' key on keyboard while running the game in editor;\
2\. manualy delete file in AppData\LocalLow\Company\_Name\Game\_Name\\**gameData.sqw**. FileName by default is **gameData.sqw**, but you can change it in SaveSystem.cs in FileName readonly string value.

> ```csharp
>     /// <summary>
>     /// Save data file name in <see cref="Application.persistentDataPath"/>
>     /// </summary>
>     private readonly string FileName = "gameData.sqw";
> ```

3\. from Inspector menu on SaveSystem object script:

<figure><img src="https://1613353771-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fygjewtla1W7kzTTIpGWq%2Fuploads%2F9tUHq8vbKoKlv8L34Evf%2Fimage.png?alt=media&#x26;token=dd1e232c-5578-4b92-8d78-1050ee79eca4" alt=""><figcaption><p>Save and Delete btns in inspector (select SaveSystem obj)</p></figcaption></figure>

* Here is how default SaveData class looks (separate SaveData.cs file):

{% code lineNumbers="true" %}

```csharp
[System.Serializable]
public class SaveData {
    /// <summary>
    /// version check here <see cref="VersionValidator"/>
    /// </summary>
    public string GameVersion;

    /// <summary>
    /// Users currency, to manipulate use <see cref="CashManager"/> API
    /// Start values in Currency Settings config
    /// </summary>
    public Dictionary<Currencies, float> Currencies = null;

    public Languages Language = Languages.English;

#if UNITY_EDITOR
    public void LogAdditionalData() {
        System.Text.StringBuilder info = new System.Text.StringBuilder("Save additional data: \n");

        info.Append(Newtonsoft.Json.JsonConvert.SerializeObject(Currencies) + "\n");

        UnityEngine.Debug.Log(info.ToString());
    }
#endif
}
```

{% endcode %}

{% hint style="danger" %}
Note that SaveData class has decorator \[System.Serializable]. This decorator must be on every class that will be serialized into binary format and saved into file. Above example SaveData has basic types (string, int, bool) which by default are Serializable.
{% endhint %}

## How to Serialize custom classes

{% hint style="warning" %}
Unity classes and structs are not serializable.&#x20;

For example Vector3 is not serializable, \
use **SerializableVector3 / SerializableVector2 / SerializableQuaternion** in Serializable class instead of Vector3 / Vector2 / Quaternion.

*Custom classes that used to serialized Unity structures or classes are in:*\
**Assets\_Main\Scripts\Common\SaveSystem\UnitySerializable folder.**\
\
Check examples in project to see how it's implemented.
{% endhint %}

{% code lineNumbers="true" %}

```csharp
[System.Serializable] //must be
public class PlayerData {
    // default player Level, 
    // if user lanch game first time then what we wrote here
    // will be as default
    public int Level = 1;
    
    // you can pre-init data structures for save access
    public List<WeaponData> Weapons = new List<WeaponData>();
    
    public SerializableVector3 Position; // Vector3 is not serializable
    public SerializableQuaternion Rotation; // so use Serializable_Type_ 
                             // Serializable_Type_ is custom implemented struct
}

[System.Serializable] //must be
public class WeaponData {
    public WeaponType Type;
    public int BulletsAmount;
    public string CustomName;
    ..
}

[System.Serializable] //must be
public enum WeaponType {
    Melee,
    Pistol
    ..
}
```

{% endcode %}

And in SaveData it will be like this:

{% code lineNumbers="true" %}

```csharp
[System.Serializable]
public class SaveData {
    // here add your custom class
    public PlayerData PlayerData;
}
```

{% endcode %}

Now you need to access it and change it. Saves on iOS/Android will be automaticaly so after game restart you will remain PlayerData info in SaveData.

## Access Data in code

You can access SaveSystem.Instance.Data in **Awake()** unity function, because of script execution order in ProjectSettings.\
\
And it will looks like this:

{% code lineNumbers="true" %}

```csharp
public void Awake() {
    int currencies = SaveSystem.Instance.Data.Currencies;
    
    // or you can do it like this (if you need to access Data multiple times)
    var saveData = SaveSystem.Instance.Data;
    var currencies = saveData.Currencies;
    var playerData = saveData.PlayerData;
    
    // set new data
    SaveSystem.Instance.Data.PlayerData.Position = transform.position;
}
```

{% endcode %}

More examples you can find in **Assets/\_Main/\_Examples/Save System.**
