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: SerializedScriptableObject → ParagonScriptableObject → 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:
Return cached — If
instanceis already set, return it.Load from Resources —
Resources.Load<T>(AssetPath). RequiresAssetPathset in[SingletonSettings].Create new —
ScriptableObject.CreateInstance<T>(). In the editor, automatically saves the asset atAssets/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
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:
Apply
[SingletonSettings(AssetPath = "...")]to the concrete classUse the CRTP pattern:
class MySettings : SingletonScriptableObject<MySettings>
You SHOULD:
Set a meaningful
AssetPathfor Inspector discoverabilityUse
[OdinSerialize]orpublicfields for Inspector-visible configurationSet
InitializeOnLoad = trueif the singleton must be available before scene code runs
You SHOULD NOT:
Create instances manually — always use
InstanceRely on
OnEnable()/OnDisable()for singleton lifecycle — useApplication.quitting(handled automatically)
Type Parameters
T
SingletonScriptableObject<T>
The concrete subclass type (CRTP pattern)
Common Pitfalls
Duplicate instance assertion Initialize() asserts that instance == null. Loading the same asset twice (e.g., via Resources.Load outside the singleton system) can trigger this.
AssetPath must be a Resources-relative path The AssetPath is passed to Resources.Load<T>(), so it must be relative to a Resources/ folder. Do not include Assets/Resources/ or the file extension.
Editor auto-creation saves to Assets/Resources/ When no asset exists and AssetPath is set, CreateSingleton() auto-saves an asset at Assets/Resources/{AssetPath}.asset. Ensure the directory exists.
Instance is cleared on Application.quitting The static instance is set to null during the Application.quitting event. Accessing Instance during or after quit may trigger re-creation.
Examples
Global Settings
Factory Registry
See Also
SingletonBehaviour<T> — MonoBehaviour variant
SingletonObject<T> — plain C# object variant
SingletonSettingsAttribute — configuration attribute
SingletonInitializer — startup bootstrap
ParagonScriptableObject — base class
Singletons Subsystem — subsystem overview
Last updated