SingletonScriptableObject

Abstract generic ScriptableObject singleton with a two-step lazy-initialization chain: load from Resources → create new instance. Ideal for global configuration data or registries that need Inspector editing and asset persistence. Automatically creates and saves the .asset file in the editor when missing. Extends ParagonScriptableObject.

Definition

Namespace: Paragon Assembly: Paragon.dll

[SingletonSettings]
public abstract class SingletonScriptableObject<T> : ParagonScriptableObject
    where T : SingletonScriptableObject<T>

Inheritance: SerializedScriptableObjectParagonScriptableObject → SingletonScriptableObject<T>

Remarks

SingletonScriptableObject<T> is designed for data singletons — settings, registries, databases — that need to be configured in the Unity Inspector and persisted as project assets. Its resolution chain on first Instance access:

  1. Return cached — If instance is already set, return it.

  2. Load from ResourcesResources.Load<T>(AssetPath). Requires AssetPath set in [SingletonSettings].

  3. Create newScriptableObject.CreateInstance<T>(). In the editor, automatically saves the asset at Assets/Resources/{AssetPath}.asset.

After loading or creating, Initialize() is called to set the static instance and register the application quit handler.

Unlike SingletonBehaviour, there is no "find in scene" step — ScriptableObjects don't exist in scenes.

Quick Lookup

Goal
How

Access the singleton

MySettings.Instance

Define a new singleton

Subclass SingletonScriptableObject<T>, add [SingletonSettings(AssetPath = "...")]

Persist as a project asset

Set AssetPath — the asset is auto-created in Assets/Resources/

Initialize at startup

Set InitializeOnLoad = true in [SingletonSettings]

Edit in Inspector

Select the .asset file in the Project window

Properties

Instance

Static accessor for the singleton. Triggers lazy initialization on first access.

Implementation Requirements

When subclassing SingletonScriptableObject<T>, you MUST:

  1. Apply [SingletonSettings(AssetPath = "...")] to the concrete class

  2. Use the CRTP pattern: class MySettings : SingletonScriptableObject<MySettings>

You SHOULD:

  • Set a meaningful AssetPath for Inspector discoverability

  • Use [OdinSerialize] or public fields for Inspector-visible configuration

  • Set InitializeOnLoad = true if the singleton must be available before scene code runs

You SHOULD NOT:

  • Create instances manually — always use Instance

  • Rely on OnEnable() / OnDisable() for singleton lifecycle — use Application.quitting (handled automatically)

Type Parameters

Parameter
Constraint
Description

T

SingletonScriptableObject<T>

The concrete subclass type (CRTP pattern)

Common Pitfalls

circle-exclamation
circle-exclamation
circle-exclamation
circle-exclamation

Examples

Global Settings

Factory Registry

See Also

Last updated