The Settings view set is built from three abstractions: a SettingsDataSO bundling many SettingsDataSections (model), and a SettingsMenuView hosting many SettingsMenuViewSections (view). Each pair handles a category — Graphics, Audio, Localization, etc. The GameFull sample ships a complete working example you can fork.

Settings

Architecture

Settings System

LayerClassPurpose
Model — bundleSettingsDataSOScriptableObject holding a dictionary of SettingsDataSections.
Model — sectionSettingsDataSectionAbstract SO. One per category; loads/saves to PlayerPrefs and applies values at runtime.
View — rootSettingsMenuViewThe host MonoBehaviour. Add view sections as children.
View — sectionSettingsMenuViewSectionAbstract MonoBehaviour. One per category; binds UXML controls to its model section.

SettingsDataSO

Holds the full settings model — a KeyValueDatabase<string, SettingsDataSection> whose keys identify each section.

Settings Data

SettingsDataSection

Abstract ScriptableObject. One subclass per category. You override:

MethodPurpose
SaveToPlayerPrefs(string key)Write each field with a per-section key prefix.
LoadFromPlayerPrefs(string key)Read each field back.
CopyValuesFrom(SettingsDataSection)Deep-copy fields from another instance (used for "discard changes").
ApplySettings(SettingsDataSection)Push values from another instance into the live game (e.g. update audio mixer, locale).
Equals(object) / GetHashCode()Power the "settings changed?" diff that gates the Apply button.

Example

csharp
[CreateAssetMenu(fileName = "SectionGameplay", menuName = "CupkekGames/Settings/SectionGameplay")] public class SettingsDataSectionGameplay : SettingsDataSection { [SerializeField] private float _cursorSensitivity; public float CursorSensitivity { get => _cursorSensitivity; set { _cursorSensitivity = value; // Apply at runtime: e.g. Cursor.sensitivity = value; } } public override bool Equals(object obj) => obj is SettingsDataSectionGameplay b && _cursorSensitivity == b._cursorSensitivity; public override int GetHashCode() => _cursorSensitivity.GetHashCode(); public override void SaveToPlayerPrefs(string key) { PlayerPrefs.SetFloat($"{key}_CursorSensitivity", _cursorSensitivity); PlayerPrefs.Save(); } public override void LoadFromPlayerPrefs(string key) { if (PlayerPrefs.HasKey($"{key}_CursorSensitivity")) _cursorSensitivity = PlayerPrefs.GetFloat($"{key}_CursorSensitivity"); } public override void CopyValuesFrom(SettingsDataSection section) { if (section is SettingsDataSectionGameplay copy) _cursorSensitivity = copy._cursorSensitivity; } public override void ApplySettings(SettingsDataSection section) { if (section is SettingsDataSectionGameplay copy) CursorSensitivity = copy._cursorSensitivity; } }

SettingsMenuView

Root host. Add SettingsMenuViewSection MonoBehaviours as children — one per category.

SettingsMenuViewSection

Abstract MonoBehaviour. One subclass per category. Override:

MethodPurpose
Awake()Resolve UXML controls. Call base.Awake().
ApplySettingsToUI()Push current _changedSettings values into the UI controls.
Per-control change handlersPush UI changes back into _changedSettings.Dictionary[<key>].

Example

csharp
using UnityEngine.UIElements; using CupkekGames.Systems; public class SettingsMenuViewAudio : SettingsMenuViewSection { private Slider _sliderCursorSensitivity; protected override void Awake() { base.Awake(); _sliderCursorSensitivity = UIDocument.rootVisualElement.Q<Slider>("CursorSensitivitySlider"); } public void OnEnable() => _sliderCursorSensitivity.RegisterValueChangedCallback(OnSliderChanged); public void OnDisable() => _sliderCursorSensitivity.UnregisterValueChangedCallback(OnSliderChanged); public override void ApplySettingsToUI() { var gameplay = (SettingsDataSectionGameplay)_changedSettings.Dictionary["gameplay"]; _sliderCursorSensitivity.value = gameplay.CursorSensitivity; } private void OnSliderChanged(ChangeEvent<int> evt) { var gameplay = (SettingsDataSectionGameplay)_changedSettings.Dictionary["gameplay"]; gameplay.CursorSensitivity = evt.newValue; } }

See also

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL