Contents
Lix Save System v2.0 – Full Documentation
Author: SillyLix
Version: 2.0.0
License: License
Unity Version: 6000.0.61f1+
Download: itch.io
1. Overview
The Lix Save System v2.0 is a robust and modular data persistence solution for Unity.
It has been completely rewritten to support dependency injection, modular encryption, and flexible
serialization.
For Beginner you may want to look at Example Usage and Tutorial
Supported Types: All C# primitive types, string, decimal,
and Unity structs Vector2, Vector3, Vector4, and
Quaternion.
Nulls & UnityEngine.Object: SaveSystem.Set skips null values and
rejects UnityEngine.Object references to avoid recursion.
Namespaces to Import:
using SillyLixStudio.SaveSystem;required to useGameData,SaveSystem, and related classes.using SillyLixStudio.SaveSystem.Interfaces;required if you implement custom handlers viaIFileIO,IGameSerializer, orISaveSystemEncryption.
2. Core Classes
GameData
GameData is the primary data container. It holds the dictionary of saved values
and the configuration settings (`gameDataConf`). You usually create one instance of
GameData
per save save file.
GameDataConf
GameDataConf manages all settings for a specific GameData instance, including
file paths, encryption keys, and the specific logic handlers (Encryption, Serialization, File I/O).
Defaults: file name LixSaveFile, encryption off, pretty print off, extension
.lixsave, handlers AESEncryption + JsonGameSerializer +
SaveFile. You can swap handlers via the interfaces below.
SaveSystem
SaveSystem is a static class that acts as the bridge between your game logic and the data.
It validates types through the configured serializer, offers Set/Get<T>,
HasKey, file lifecycle helpers (SaveFileExists,
DeleteSaveFile, ClearAllData), and marshals through the configured File I/O
and encryption handlers.
3. System & Helper Classes
Beyond the core classes, the system uses several helper classes located in the Systems
folder to handle specific tasks. While you rarely need to touch these directly, understanding them helps
when extending the system.
SavedValue
A wrapper class stored inside the GameData dictionary. It holds two things:
- Value: The actual data (e.g., the integer "100" for health).
- Type: The C# System Type of the data. This ensures that if you save an
int, you get an error if you try to load it as astring, preventing data corruption.
SaveFile (Implements IFileIO)
This is the default File I/O handler. It is responsible for:
- Taking the
GameDataobject. - Passing it to the Serializer to get a string/byte representation.
- Passing that result to the Encryption handler (if encryption is enabled).
- Writing the final result to the disk at the path specified in
GameDataConf.
JsonGameSerializer (Implements IGameSerializer)
The default serializer included with the asset. It uses JSON formatting to convert your C# objects into
text. It supports "Pretty Print" (via GameDataConf) for human-readable save files, which is
useful for debugging. Supported types: all primitives, string, decimal, and
Unity structs Vector2/Vector3/Vector4/Quaternion.
UnityEngine.Object references (MonoBehaviour, GameObject, Rigidbody, etc.) are rejected to avoid
serialization loops. You can extend support for additional types by supplying custom JSON converters in
your own serializer implementation (see Custom Serialization below); keep UnityEngine.Object references
out of converters to avoid recursion.
4. API Reference
🔹 SaveSystem Class API
The primary static methods for managing data.
| Method | Description |
|---|---|
Set(GameData data, string key, object value) |
Saves a value (primitives, string, decimal, Unity
Vector2/3/4, Quaternion) to the data object. Null or unsupported
types are skipped with a log. Updates if key exists.
|
Get<T>(GameData data, string key) |
Retrieves a value of type T. Returns default(T) if not found or type mismatch. |
HasKey(GameData data, string key) |
Returns true if the key exists in memory for the provided
GameData.
|
RemoveKey(GameData data, string key) |
Permanently removes a key and its value from the data object. |
ClearAllData(GameData data) |
Wipes all saved keys/values from memory (does not delete the file on disk). |
SaveFileExists(GameData data) |
Checks if a save file exists for the configured path/name. |
DeleteSaveFile(GameData data) |
Deletes the save file on disk for the provided GameData configuration. |
SaveToDisk(GameData data) |
Serializes and writes the current data to the file system based on configuration. |
LoadFromDisk(GameData data) |
Reads from the file system and populates the provided GameData object. |
🔹 GameDataConf Class API
Methods to configure how data is saved. Accessed via gameData.gameDataConf.
| Method | Description |
|---|---|
SetFileName(string name) / GetFileName() |
Set or Get the name of the save file (e.g., "SaveFile1"). |
SetSavePath(string path) / GetSavePath() |
Set a custom folder path. Defaults to Application.persistentDataPath. |
SetIsEncrypted(bool enable) / GetIsEncrypted() |
Enable or disable file encryption. |
SetEncryptionKey(string key) / GetEncryptionKey() |
Set the secret key used for encryption. |
SetEncryptionIV(string iv) / GetEncryptionIV() |
Set the Initialization Vector for AES encryption. |
SetSaveFileExtension(string ext) |
Set custom file extension (e.g., ".sav"). Only used for encrypted files. |
SetUseJsonPrettyPrint(bool enable) |
Enable readable JSON formatting (increases file size). |
SetEncryptionHandler(ISaveSystemEncryption handler) |
Inject a custom encryption logic (e.g., XOR, AES or custom). |
SetSerializer(IGameSerializer handler) |
Inject a custom serializer (e.g., JSON or custom). |
SetFileIOHandler(IFileIO handler) |
Inject a custom file writer (e.g., System.IO or custom). |
5. Customization & Interfaces
The Lix Save System is designed to be modular. You can replace core components by implementing the
following interfaces and injecting them into GameDataConf.
🧩 Custom Encryption (ISaveSystemEncryption)
To create your own encryption method (e.g., a simple Caesar Cipher or RSA), implement the
ISaveSystemEncryption interface.
using SillyLixStudio.SaveSystem.Interfaces;
public class MyCustomEncryption : ISaveSystemEncryption
{
public byte[] Encrypt(byte[] data, string key) { /* Your logic */ }
public byte[] Decrypt(byte[] data, string key) { /* Your logic */ }
}
// Usage:
gameData.gameDataConf.SetEncryptionHandler(new MyCustomEncryption());
🧩 Custom Serialization (IGameSerializer)
If you prefer BinaryFormatter, XML, or a different JSON library, implement IGameSerializer.
using SillyLixStudio.SaveSystem.Interfaces;
public class XMLSerializer : IGameSerializer
{
public string Serialize(T data) { /* Convert object to XML string */ }
public T Deserialize(string data) { /* Convert XML string to object */ }
}
// Usage:
gameData.gameDataConf.SetSerializer(new XMLSerializer());
You can also register custom converters in your serializer to support additional types. Only add types
that do not contain UnityEngine.Object references to avoid recursion and stack overflows.
🧩 Custom Storage (IFileIO)
To change where files are stored (e.g., saving to Steam Cloud, PlayerPrefs, or a Database), implement
IFileIO.
using SillyLixStudio.SaveSystem.Interfaces;
public class CloudStorage : IFileIO
{
public void Write(GameData data) { /* Upload to cloud */ }
public GameData Read(GameData data) { /* Download from cloud */ }
}
// Usage:
gameData.gameDataConf.SetFileIOHandler(new CloudStorage());
6. Example Usage
using UnityEngine;
using SillyLixStudio.SaveSystem;
public class SaveSystemExample : MonoBehaviour
{
private GameData mySaveData;
private void Start()
{
// 1. Create GameData instance
mySaveData = new GameData();
mySaveData.gameDataConf.SetFileName("PlayerSave1");
mySaveData.gameDataConf.SetIsEncrypted(true);
mySaveData.gameDataConf.SetEncryptionKey("unique-key-12345");
mySaveData.gameDataConf.SetEncryptionIV("unique-iv-67890");
}
void SaveData()
{
// 2. Save some data
SaveSystem.Set(mySaveData, "PlayerName", "Hero");
SaveSystem.Set(mySaveData, "HighScore", 1500);
SaveSystem.Set(mySaveData, "PlayerPosition", new Vector3(10f, 0f, 5f));
// 3. Write to disk
SaveSystem.SaveToDisk(mySaveData);
}
void Load()
{
// 4. Load from disk
if (SaveSystem.SaveFileExists(mySaveData))
{
SaveSystem.LoadFromDisk(mySaveData);
// 5. Retrieve data
// check if keys exist before getting
if (SaveSystem.HasKey(mySaveData, "PlayerName"))
{
// get values
string playerName = SaveSystem.Get(mySaveData, "PlayerName");
}
if (SaveSystem.HasKey(mySaveData, "HighScore"))
{
int highScore = SaveSystem.Get(mySaveData, "HighScore");
}
if (SaveSystem.HasKey(mySaveData, "PlayerPosition"))
{
Vector3 playerPosition = SaveSystem.Get(mySaveData, "PlayerPosition");
}
Debug.Log($"Player Name: {playerName}, High Score: {highScore}, Position: {playerPosition}");
}
else
{
Debug.Log("No save file found.");
}
}
}
Quick Notes:
- Namespaces: Add
using SillyLixStudio.SaveSystem;. For custom handlers, also addusing SillyLixStudio.SaveSystem.Interfaces;. - Supported Types: All primitives,
string,decimal, and UnityVector2/3/4,Quaternion. - Safety: Call
LoadFromDiskfirst, then check keys withSaveSystem.HasKey(data, key)beforeGet<T>. - Unsupported Types: Unsupported values are skipped and logged without crashing.
- Encryption: Use
SetIsEncrypted(true)in production and provide secure key/IV. - File Ops:
SaveFileExists,DeleteSaveFile,ClearAllDataare available for lifecycle management.
7. License
Overview: This license governs use of the provided assets and the rights granted to the Licensee.
1. Definitions
Asset(s): The files, code, and other materials provided by the Licensor.
End Product: A game, application, or other finished product in which the Asset is incorporated and distributed to end users.
2. Grant of License
The Licensor grants the Licensee a worldwide, non-exclusive, non-transferable license to:
- Use, reproduce, and modify the Asset as part of an End Product.
- Sell, distribute, or monetize the End Product containing the Asset.
3. Restrictions
Licensee may not:
- Distribute, sell, license, or make the Asset available in standalone form (source files) outside of an End Product.
- Claim the Asset as the Licensee’s own original work.
- Remove any required attribution or credits where specified by the Licensor.
- Redistribute the Asset as part of another asset pack, template, or library for resale or re-distribution.
4. Attribution
Attribution is NOT required for this asset, but it is very much so appreciated.
5. Ownership
Ownership: The Licensor retains all copyright and moral rights in the Asset. The Licensee receives only the rights expressly granted in this license.
6. Termination
Violation of any term of this license automatically terminates the rights granted. Upon termination the Licensee must cease using the Asset and remove it from any End Product distribution.
7. Disclaimer
Assets are provided "as is" without warranty of any kind. The Licensor is not responsible for any damages arising from the use of the Asset.
