MOST Database

A lightweight, designer‑friendly save/state framework. You define named data entries (Int, Float, Bool, String) in one ScriptableObject; at runtime it seeds from your InitialValues on first launch, then auto‑loads/auto‑saves JSON under Application.persistentDataPath/MOST/. It includes range clamping, best‑score tracking, safe file writes, and simple lookup APIs.


Quick Start

  1. Create: Right‑click → Create → MOST → Database → name it (e.g., M_Database).

  1. Configure key (optional): In the inspector, set Database Key (used for save filename). Otherwise, the asset name is used.

  2. Add Entries: Use the list to add IntData, FloatData, BoolData, or StringData. Fill DataName and InitialValue; set Min/Max if needed.

  1. Press Play: First run seeds from InitialValue and writes JSON. Future runs load from JSON automatically.

The Initialized flag in the inspector tells you whether a save exists and has been applied this session.


Concepts & Terminology

  • Entry / Data: A single variable (Int/Float/Bool/String) with a DataName and a unique generated ID.

  • InitialValue: Author‑time default; used only for seeding when there is no save file yet, or as baseline before applying saved values.

  • Value: Current runtime value (read‑only in inspector during play; modified by API).

  • HighestValue (Int/Float): Auto‑tracked peak (useful for best scores or max currencies).

  • EnableMin/Max: Optional clamping bounds; any Set/Add/Subtract passes through Clamp.

  • Database Key: A file key used to build a save file path (MOST/<key>.json). Safe characters enforced.

  • Context Menu: Delete Save File (This DB) removes the JSON for this database key (Editor‑only helper).


Persistence Lifecycle (no code needed)

  • On first Play: If no save exists, the DB seeds Value from InitialValue (and clamps), then saves JSON.

  • On subsequent Plays: The DB loads JSON, overlays values onto a fresh InitialValue baseline, and marks Initialized = true.

  • On Quit: Auto‑saves the latest values. Writes to a temporary *.tmp then atomically replaces the main file to avoid corruption.

  • File Location: {Application.persistentDataPath}/MOST/<DatabaseKey>.json

  • Multiple Databases: Each asset gets its own file based on its key; all loaded DBs will be saved on quit.


API & Live Example?

  1. Current Level: Start Level = 1 and Minimum ≥ 0 (No Level 0)

  2. Score: Minimum> 0 (No negative score), and record the highest score

  3. Currency: Init with 100 currency (Coins, Gems)

Bootstrap MonoBehaviour > inspector?

// Hook database
public MOST_Database Database;
// Then drag the Database asset into a bootstrap MonoBehaviour.
//
// Get a specific data
public MOST_Database Database;
// Then drag the Database asset into a bootstrap MonoBehaviour.

// Get data by ID
var data = Database.GetById(int id);


// Get data by Name
var data = Database.GetByName(int id);


// Get by Typed lookups (The best way for type-specific) (return null if not found)
// for int data
IntData data = Database.Get<IntData>(int id); // by id
IntData data = Database.Get<IntData>(string name); // by data name

// for float data
FloatData data = Database.Get<FloatData>(int id); // by id
FloatData data = Database.Get<FloatData>(string name); // by data name

// for bool data
BoolData data = Database.Get<BoolData>(int id); // by id
BoolData data = Database.Get<BoolData>(string name); // by data name

// for float data
StringData data = Database.Get<StringData>(int id); // by id
StringData data = Database.Get<StringData>(string name); // by data name

// _________________________________________________//

// Check for data, Try-get pattern
bool isFound = Database.TryGet(int id, out MData result); // for any type of data
bool isFound = Database.TryGet(int id, out IntData result); // for int data
bool isFound = Database.TryGet(int id, out FloatData result); // for float data
bool isFound = Database.TryGet(int id, out BoolData result); // for bool data
bool isFound = Database.TryGet(int id, out StringData result); // for string data

// Check if the database is initialized
bool isInit = Database.Initialized;

Important (Save/Load)

//
Database.SaveToJson(); // writes current Values to disk (safe temp+replace)
Database.LoadFromJson(); // re-loads file (overlays on InitialValue baseline)

Opreations

//
// Get a specific data
public MOST_Database Database;
// Then drag the Database asset into a bootstrap MonoBehaviour.

// For Int Data
IntData data = Database.Get<IntData>(string name); // by data name "Currency" for ex

data.Get(); or data.Value // returns data Value
data.HighestValue; // returns data's Highest Value
data.MinValue; // return or set the minimum value that this data can be
data.MaxValue; // return or set the maximum value that this data can be
data.EnableMin; // return, enable or disable Minimum control 
data.EnableMax; // return, enable or disable Maximum control 

data.Set(int v); or data.Value  // sets Value (clamped), updates HighestValue
data.Add(int delta); // Add (negative becomes Subtract)
data.Subtract(int delta); // Subtract (negative becomes Add)
data.TrySubtract(int amount); // return boolean > safe spend check against min/0
data.SetIfGreater(int candidate); // return boolean > best-score style update
data.ClampMinZero(); // floor at 0

// For Float Data
FloatData data = Database.Get<FloatData>(string name); // by data name "Currency" for ex

data.Get(); or data.Value // returns data Value
data.HighestValue; // returns data's Highest Value
data.MinValue; // return or set the minimum value that this data can be
data.MaxValue; // return or set the maximum value that this data can be
data.EnableMin; // return, enable or disable Minimum control 
data.EnableMax; // return, enable or disable Maximum control 

data.Set(float v); or data.Value // sets Value (clamped), updates HighestValue
data.Add(float delta); // Add (negative becomes Subtract)
data.Subtract(float delta); // Subtract (negative becomes Add)
data.TrySubtract(float amount); // return boolean > safe spend check against min/0
data.SetIfGreater(float candidate); // return boolean > best-score style update
data.ClampMinZero(); // floor at 0


// For Bool Data
BoolData data = Database.Get<BoolData>(string name); // by data name

data.Value; // return or set the data value
data.ToggleValue(); // Toggle current bool value
data.SetBool(bool value); // Set the data value

// For string value
StringData data = Database.Get<StringData>(string name); // by data name

data.Value; // return or set the data value

FAQ

Q: Do I need to manually load on start? A: No. The database auto‑initializes on play, loads if a file exists, otherwise seeds and saves.

Q: Can I have multiple databases? A: Yes—each gets its own JSON by key/asset name. All loaded DBs are saved on quit.

Q: What if I rename DataName after shipping? A: Saves are keyed by id, not by name. Renaming the display name is safe; removing or re‑ordering entries may affect semantics. Prefer adding new entries instead of recycling IDs.

Q: Is the file safe from corruption? A: Writes use a temporary file then File.Replace where available; this minimizes corruption risk.

Q: When is Initialized true? A: After the DB loads from disk or writes a first save during the current play session.

Last updated