Custom settings#
A custom settings section exposes project-wide configuration in the Settings window. Use one for values a designer sets once for the entire project.
Settings types#
A repository and asset provide the settings section. Add a drawer when you need a custom layout:
| Piece | Is |
|---|---|
| Repository | The data. A serializable class holding your settings. |
| Asset | The container. A ScriptableObject wrapping the repository. |
| Drawer | Optional. A custom Inspector for the repository. |
The repository#
This repository stores two project-wide values and exposes them as read-only properties:
using System;
using UnityEngine;
using VisualScript.Runtime;
[Serializable] [Repository(ID)]
public class MyRepository : TRepository<MyRepository>
{
public const string ID = "mygame.settings";
public override string Id => ID;
[SerializeField] private float m_DefaultVolume = 0.8f;
[SerializeField] private bool m_SkipIntro;
public float DefaultVolume => this.m_DefaultVolume;
public bool SkipIntro => this.m_SkipIntro;
}The [Repository] attribute's ID identifies the section and names the asset created in Resources. It must be unique, so prefix it with the project or package name.
Override OnInitialize() for work that must happen the first time the repository is loaded at runtime.
The asset#
This asset defines how the repository appears in the Settings window:
using UnityEngine;
using VisualScript.Icons;
using VisualScript.Runtime;
public class MyAsset : TAsset<MyRepository>
{
public override IIcon Icon => new IconCog(ColorTheme.Type.TextLight);
public override string Name => "My Game";
public override int Priority => 20;
}MyAsset names and orders the sidebar entry that opens MyRepository.
| Member | Controls |
|---|---|
Icon |
The sidebar icon. |
Name |
The sidebar label. |
Priority |
Sort order in the sidebar. Lower appears higher. |
IsFullScreen |
Whether the panel uses the full window width. |
The editor creates the asset on first load. No scene or manual asset placement is required.
Reading settings at runtime#
Resolve the repository through Settings.Get<T>() and read its public properties:
MyRepository settings = Settings.Get<MyRepository>();
float volume = settings.DefaultVolume;The repository is loaded once and cached. In the editor outside Play mode it's re-read each time, so changes in the Inspector take effect immediately.
Settings are read-only at runtime
A repository is authored data, like any other asset. Writing to it at runtime works in the editor, silently persists into your project, and does nothing in a build.
Anything the player changes belongs in a Global Variable saved to the Shared location — not in settings.
A custom drawer#
Without a custom drawer, Unity draws the repository's fields with its default Inspector.
For a custom layout, write a PropertyDrawer for the repository type. Return its VisualElement from CreatePropertyGUI; the layout implementation is omitted here:
[CustomPropertyDrawer(typeof(MyRepository))]
public class MyRepositoryDrawer : PropertyDrawer
{
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
// …
}
}Unity uses MyRepositoryDrawer instead of the default field layout whenever the repository is drawn.
What belongs here#
Use settings for authored project configuration, and keep runtime or per-object values in the systems that own them:
| Settings | Not settings |
|---|---|
| Project-wide defaults | Per-object configuration |
| Asset references a system needs | Runtime state |
| Feature toggles decided at build time | Player preferences |
| Tuning values shared across scenes | Anything that changes during gameplay |
Use a repository when every scene needs the same value. Per-object values belong on the object instead.
Version control#
Commit the generated asset under Resources so the team shares the same project configuration.
Changes to that asset affect the whole project. Personal preferences belong in Editor settings, which Unity stores per user.
Where to go next#
- Settings window — inspect the designer-facing configuration.
- Conventions — apply serialization and naming rules to the repository.
- Global Variables — store player-controlled values that change at runtime.