Quick Links: Installation | Features | Editor Tools | Contributing
Managing game data in Unity often leads to fragmented solutions: scattered config files, tight coupling between data and logic, and cross-platform inconsistencies. This GameData package addresses these challenges:
| Problem | Solution |
|---|---|
| Scattered config management | Type-safe ConfigsProvider with O(1) lookups and versioning |
| Tight coupling to data changes | Observable types (ObservableField, ObservableList, ObservableDictionary) for reactive programming |
| Manual derived state updates | ComputedField for auto-updating calculated values with dependency tracking |
| Cross-platform float inconsistencies | Deterministic floatP type for reproducible calculations across all platforms |
| Backend sync complexity | Built-in JSON serialization with ConfigsSerializer for client/server sync |
| Dictionary Inspector editing | UnitySerializedDictionary for seamless Inspector support |
| Fragile enum serialization | EnumSelector stores enum names (not values) to survive enum changes |
Built for production: Minimal dependencies. Zero per-frame allocations in observable types. Used in real games.
- Unity 6000.0+ (Unity 6)
- Newtonsoft.Json (com.unity.nuget.newtonsoft-json v3.2.1) — automatically resolved
- TextMeshPro (com.unity.textmeshpro v3.0.6) — used by Samples~ UI scripts only
| Unity Version | Status |
|---|---|
| 6000.0+ (Unity 6) | ✅ Fully Tested |
| 2022.3 LTS |
- Open Unity Package Manager (
Window→Package Manager) - Click
+→Add package from git URL - Enter:
https://github.com/CoderGamester/com.gamelovers.gamedata.git
{
"dependencies": {
"com.gamelovers.gamedata": "https://github.com/CoderGamester/com.gamelovers.gamedata.git"
}
}| Component | Responsibility |
|---|---|
| ConfigsProvider | Type-safe config storage with O(1) lookups and versioning |
| ConfigsSerializer | JSON serialization for client/server config synchronization |
| ConfigTypesBinder | Whitelist-based type binder for secure deserialization |
| ObservableField | Reactive wrapper for single values with change callbacks |
| ObservableList | Reactive wrapper for lists with add/remove/update callbacks |
| ObservableDictionary | Reactive wrapper for dictionaries with key-based callbacks |
| ComputedField | Auto-updating derived values that track dependencies |
| floatP | Deterministic floating-point type for cross-platform math |
| MathfloatP | Math functions (Sin, Cos, Sqrt, etc.) for floatP |
| EnumSelector | Enum dropdown that survives enum value changes |
| UnitySerializedDictionary | Dictionary type visible in Unity Inspector |
| Tool | Menu | Purpose |
|---|---|---|
| Config Browser | Tools > Game Data > Config Browser | Browse configs, validate, export JSON, preview migrations |
| Observable Debugger | Tools > Game Data > Observable Debugger | Inspect live observables in play mode |
| ConfigsScriptableObject Inspector | Inspector (automatic) | Inline duplicate-key validation and Validate All action |
Type-safe, high-performance configuration storage.
varprovider=newConfigsProvider();provider.AddConfigs(item =>item.Id,itemConfigs);provider.AddSingletonConfig(newGameSettings{Difficulty=2});varitem=provider.GetConfig<ItemConfig>(42);varsettings=provider.GetConfig<GameSettings>();// Zero-allocation enumerationforeach(varenemyinprovider.EnumerateConfigs<EnemyConfig>())ProcessEnemy(enemy);JSON serialization with security modes.
varserializer=newConfigsSerializer();// TrustedOnly by defaultstringjson=serializer.Serialize(provider,"123");varrestored=serializer.Deserialize<ConfigsProvider>(json);serializer.RegisterAllowedTypes(new[]{typeof(EnemyConfig)});varscore=newObservableField<int>(0);score.Observe((prev,curr)=>UpdateScoreUI(curr));score.InvokeObserve((prev,curr)=>UpdateScoreUI(curr));// invokes immediately tooscore.Value=100;score.StopObservingAll(this);varbaseHp=newObservableField<int>(100);varbonus=newObservableField<int>(25);vartotalHp=newComputedField<int>(()=>baseHp.Value+bonus.Value);totalHp.Observe((prev,curr)=>Debug.Log($"HP: {curr}"));baseHp.Value=120;// totalHp auto-updates to 145totalHp.Dispose();varinventory=newObservableList<string>(newList<string>());inventory.Observe((index,prev,curr,type)=>RefreshUI(index,curr));inventory.Add("Sword");varstats=newObservableDictionary<string,int>(newDictionary<string,int>());stats.Observe("health",(key,prev,curr,type)=>Debug.Log($"{key}: {curr}"));stats.Add("health",100);floatPa=3.14f;floatPsum=a+2.0f;floatresult=(float)sum;uintraw=a.RawValue;// bit-exact for determinismfloatPcopy=floatP.FromRaw(raw);[Serializable]publicclassStringIntDictionary:UnitySerializedDictionary<string,int>{}[Serializable]publicclassItemTypeSelector:EnumSelector<ItemType>{publicItemTypeSelector():base(ItemType.Weapon){}}// ItemType type = selector; — implicit conversion// bool ok = selector.HasValidSelection();Import via Package Manager → GameLovers GameData → Samples
| Sample | Demonstrates |
|---|---|
| Reactive UI Demo | ObservableField, ObservableList, ComputedField, batched updates — uGUI and UI Toolkit |
| Designer Workflow | ConfigsScriptableObject, UnitySerializedDictionary, EnumSelector with PropertyDrawer |
| Migration | IConfigMigration, MigrationRunner, Config Browser migration workflow |
Contributions are welcome! Report bugs or request features via GitHub Issues. For development setup, architecture, coding standards, and test placement, see AGENTS.md.
| Document | Purpose |
|---|---|
| AGENTS.md | Contributor/agent guide (architecture, gotchas, workflows) |
| CHANGELOG.md | Version history |
- Issues: Report bugs or request features
- Discussions: Ask questions and share ideas
MIT — see LICENSE.md.