Database Entries
Every piece of game data in Spark is a SparkDatabaseEntry. This page covers how to create custom entry types, use nested data, and access entries at runtime.
Anatomy of a SparkDatabaseEntry
SparkDatabaseEntry is an abstract class that extends Unity's ScriptableObject. It provides these base fields:
id
string
Unique identifier. Auto-generated, read-only after creation.
entryName
string
Internal name for organization in the editor.
displayName
string
Player-facing name (shown in UI).
description
string
Player-facing description (tooltips, info panels).
icon
Sprite
Visual representation in UI elements.
All fields are serialized with [SerializeField] private and exposed through public getters. This is the standard pattern for Spark entries.
Creating a Custom Entry Type
To define a new database entry, inherit from SparkDatabaseEntry:
using UnityEngine;
[CreateAssetMenu(
fileName = "New Mount",
menuName = "Spark/Mounts/Mount Entry")]
public class MountEntry : SparkDatabaseEntry
{
[Section("Movement")]
[SerializeField] private float speed = 10f;
[SerializeField] private float sprintMultiplier = 1.5f;
[Section("Appearance")]
[SerializeField] private GameObject mountPrefab;
[SerializeField] private RuntimeAnimatorController animatorController;
[Section("Requirements")]
[DatabaseEntryDropdown(typeof(ClassEntry))]
[SerializeField] private string requiredClassId;
[ConditionalField("requiredClassId", "")]
[SerializeField] private int requiredLevel = 1;
public float Speed => speed;
public float SprintMultiplier => sprintMultiplier;
public GameObject MountPrefab => mountPrefab;
public RuntimeAnimatorController AnimatorController => animatorController;
public string RequiredClassId => requiredClassId;
public int RequiredLevel => requiredLevel;
}Key points:
Use
[Section("Title")]to group related fields under collapsible headers.Use
[DatabaseEntryDropdown(typeof(T))]to create a dropdown selector for entries of a specific type.Use
[ConditionalField("fieldName", value)]to show/hide fields based on another field's value.Use
[ReadOnly]to make a field visible but not editable.Always use
[SerializeField] privatewith public getter properties.
Entry Storage
Entries must be stored in a Resources/ folder so they can be loaded at runtime. The standard location is:
For example, mount entries would go in:
The Spark Editor handles creating entries in the correct location based on your plugin manifest configuration.
Accessing Entries at Runtime
SparkDatabaseRegistry provides O(1) access to any entry:
The registry caches entries on first access. In the editor, it uses AssetDatabase for discovery. In builds, it loads from Resources/ folders.
Nested Data
For complex entries that contain lists of sub-objects, use SparkDatabaseEntryNestedData:
Then reference it from your entry:
SparkDatabaseEntryNestedData tracks its parent entry and data type name for editor tooling. The [NestedData] attribute tells the Spark Editor to render it as an inline editable list.
Validation
Override OnValidate() to add custom validation to your entries:
This runs in the editor whenever a field is changed, providing immediate feedback.
Available Attributes
Here is a quick reference of attributes you can use on entry fields:
[Section("Title")]
Group fields under a collapsible header
[Section("Title", collapsible: true)]
Same, with explicit collapsible flag
[DisplayNameTooltip("Label", "Tip")]
Custom label and tooltip
[ReadOnly]
Non-editable field
[ConditionalField("field", value)]
Show only when another field matches a value
[ConditionalMultiField(...)]
Show based on multiple field conditions
[DatabaseEntryDropdown(typeof(T))]
Dropdown picker for entries of type T
[SparkDatabaseEntrySelector]
Generic entry picker (any type)
[ScriptableObjectDropdown(typeof(T))]
Dropdown for ScriptableObject assets
[InlineField]
Render nested object fields inline
[NestedData]
Render as editable nested data list
[TagField]
Unity tag dropdown
[Switch("field", "value1", "value2")]
Switch field rendering based on another field
See Custom Attributes Reference for the full details on each attribute.
Best Practices
Keep entry classes focused. If an entry has too many fields, consider splitting into a base entry and extensions.
Use
[Section]generously to keep the editor organized.Use conditional fields to hide irrelevant options. This reduces clutter for users.
Always validate serialized data in
OnValidate().Never store runtime state in entries. Entries are configuration data, not runtime data.
Use meaningful ID prefixes. The auto-generated ID format uses the entry name, but you can influence it by naming entries clearly.
Last updated
Was this helpful?
