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:

Field
Type
Description

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] private with 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:

Attribute
Purpose

[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?