Skip to content
One Last Click Docs

How It Works

OneLastClick Project Settings builds on Unity’s existing ScriptableObject and serialization systems to make project settings feel like native Unity settings.

The package handles four main responsibilities:

  1. Discovering ScriptableObject types marked with [ProjectSettings].
  2. Storing their data in ProjectSettings without using the Asset Database.
  3. Displaying them in the Project Settings window using the standard inspector.
  4. Making runtime settings available in builds without requiring manual asset references.

When the editor initializes, the package finds all ScriptableObject types marked with [ProjectSettings].

For each type, the package creates or loads its corresponding settings instance when it is required.

This means there is no need to manually create a .asset file in the Assets folder.

Project settings are stored using Unity’s internal asset serialization APIs rather than the normal AssetDatabase workflow.

This allows the serialized settings to live directly inside the project’s:

ProjectSettings/

instead of:

Assets/

The settings still use Unity’s normal ScriptableObject serialization, so standard serializable fields and Unity object references work as expected.

For every [ProjectSettings] type, the package registers a Unity SettingsProvider.

The provider loads the corresponding ScriptableObject and draws its normal Unity inspector.

This means the settings page uses the same serialization and inspector behaviour as a regular ScriptableObject.

For example:

[ProjectSettings]
public class GraphicsProjectSettings : ScriptableObject
{
[SerializeField] private Material DefaultMaterial;
[SerializeField] private int QualityLevel;
}

The fields are displayed using Unity’s standard inspector without requiring a custom inspector for the settings type.

Changes made in the Project Settings window are serialized back to the settings file automatically.

Editor settings cannot be referenced directly by a built player because they are stored outside the normal Assets asset pipeline.

To make runtime settings available, the package prepares them during the build process.

Before the build starts, all non-editor-only project settings are loaded.

[ProjectSettings]
↓
Discover Types
↓
Load Settings

Settings marked with editorOnly: true are excluded.

The package creates copies of the settings objects and places them inside a temporary Unity asset.

ProjectSettings/
ExampleProjectSettings
↓ build
BuiltProjectSettingsContainer.asset
├── ExampleProjectSettings
├── GraphicsProjectSettings
└── ...

The temporary asset exists inside Assets only for the duration of the build process.

3. The Container Is Referenced by the First Scene

Section titled “3. The Container Is Referenced by the First Scene”

During scene processing, a small registerer object is injected into the first scene of the build.

It holds a reference to the generated settings container.

Because the scene now references the container, Unity’s build pipeline knows that the settings and their dependencies must be included in the build.

When the application starts, the registerer makes each settings instance available through the runtime database.

var settings = ProjectSettingsDatabase.Get<ExampleProjectSettings>();

This provides runtime access without requiring developers to create or maintain references to the settings themselves.

When entering Play Mode directly from the Unity Editor, the normal build pipeline is not run.

To provide the same runtime API, the package registers the settings before the first scene is loaded.

This means the following works consistently in both the Editor and a built player:

var settings = ProjectSettingsDatabase.Get<ExampleProjectSettings>();

The generated build asset is temporary.

After the build completes, the package removes the generated files from the project, leaving only the original project settings in ProjectSettings.

The overall flow can be simplified to:

[ProjectSettings] types
↓
Discover settings
↓
Load / create editor instances
↓
Project Settings
│
└── Editor inspector
│
↓
Build
↓
Create runtime copies
↓
Generate temporary container
↓
Inject reference into first scene
↓
Build Player
↓
Register settings
↓
ProjectSettingsDatabase.Get<T>()

The result is a ScriptableObject-based settings system that retains Unity’s familiar serialization and inspector workflow while keeping project configuration outside the Assets folder.