Home

Awesome

Key-Value Store for Unity

openupm

Simple to use Key-Value Store interface and implementations for Unity, suitable for save systems.

Key-Value Stores provide a simple and effective way of persisting arbitrary data mapped to string keys. Possible implementations of Key-Value Stores include, but are not limited to: C# Dictionary, PlayerPrefs, LiteDB / UltraLiteDB, FASTER KV, LMDB, SQLite, iCloud KVS, macOS/iOS Keychain, Android Keystore ...

Features

Implementations

Key-Value Stores:

Object serializers:

How to install

Either:

Basic usage

using Gilzoide.KeyValueStore;
using UnityEngine;

// 1. Instantiate one of the IKeyValueStore implementations
IKeyValueStore kvs = new DictionaryKeyValueStore
{
    FilePath = Application.persistentDataPath + "/MySaveFile.json",
};


// 2. (optional) If Key-Value Store supports saving, load previous data
if (kvs is ISavableKeyValueStore savableKvs)
{
    savableKvs.Load();
}


// 3. Set/Get/Delete values
kvs.SetBool("finishedTutorial", true);
kvs.SetString("username", "gilzoide");

Debug.Log("Checking if values exist: " + kvs.HasKey("username"));
Debug.Log("Getting values: " + kvs.GetInt("username"));
Debug.Log("Getting values with fallback: " + kvs.GetString("username", "default username"));
// Like C# Dictionary, this idiom returns a bool if the key is found
if (kvs.TryGetString("someKey", out string foundValue))
{
    Debug.Log("'someKey' exists: " + foundValue);
}

kvs.DeleteKey("someKey");


// 4. (optional) If the Key-Value Store supports saving, save the data
if (kvs is ISavableKeyValueStore savableKvs)
{
    savableKvs.Save();
}

Automatic saving

using Gilzoide.KeyValueStore;
using UnityEngine;

// 1. Instantiate one of the ISavableKeyValueStore implementations
ISavableKeyValueStore wrappedKvs = new DictionaryKeyValueStore
{
    FilePath = Application.persistentDataPath + "/MySaveFile.json",
};


// 2. Wrap the store into an AutoSaveKeyValueStoreWrapper and use it instead
IKeyValueStore kvs = new AutoSaveKeyValueStoreWrapper(wrappedKvs);


// 3. Whenever you set or delete values, `wrappedKvs.Save()` is automatically
// called in the next frame. Notice that we skip a frame to avoid making lots
// of I/O if you change lots of data in a single frame.
kvs.SetBool("will this be saved automatically next frame?", true);

Class/struct serialization

using System.Collections.Generic;
using Gilzoide.KeyValueStore;
using Gilzoide.KeyValueStore.ObjectSerializers;
using UnityEngine;

IKeyValueStore kvs = new DictionaryKeyValueStore();

// 1. Set/Get objects
kvs.SetObject("aVector", new Vector3(1, 2, 3));
if (kvs.TryGetObject("lastPosition", out Vector3 lastPosition))
{
    Debug.Log("Last position was: " + lastPosition);
}


// 2. (optional) Use custom serializers
var newtonsoftJsonSerializer = new NewtonsoftJsonSerializer();
kvs.SetObject(newtonsoftJsonSerializer, "jsonList", new List<int> { 1, 3, 5, 9 });
List<int> anotherJsonList = kvs.GetObject<List<int>>(newtonsoftJsonSerializer, "someKey");


// 3. (optional) Add serializers to the default serializer map
// This makes them be used even when not passed explicitly
ObjectSerializerMap.DefaultSerializerMap.SetObjectSerializer<List<int>>(newtonsoftJsonSerializer);

kvs.SetObject("jsonList", new List<int> { 1, 3, 5, 9 });
List<int> yetAnotherJsonList = kvs.GetObject<List<int>>("someKey");


// 4. (optional) Use your own ObjectSerializerMap
var unityMathTextSerializer = new UnityMathTextSerializer();
var serializerMap = new ObjectSerializerMap
{
    DefaultSerializer = newtonsoftJsonSerializer,
    TypeToSerializerMap = new Dictionary<Type, IObjectSerializer>
    {
        [typeof(Vector2)] = unityMathTextSerializer,
        [typeof(Vector3)] = unityMathTextSerializer,
        [typeof(Vector4)] = unityMathTextSerializer,
    },
};

kvs.SetObject(serializerMap, "uses UnityMathTextSerializer", new Vector2(10, 5));
kvs.SetObject(serializerMap, "uses NewtonsoftJsonSerializer", new int[] { 1, 2, 3 });

// (tip) to avoid the annoyance of adding all math types manually, call this:
unityMathTextSerializer.RegisterInSerializerMap(serializerMap);