Custom settings panels (SettingsPanel)
GraphicsSettingsPanel, AudioSettingsPanel and InputSettingsPanel share the base SettingsPanel<T>. Use it for a settings screen of your game, for example difficulty or accessibility options.
The base has these members:
| Member | Description |
|---|---|
Editing |
The options that the body edits. |
Applied |
The options of the last Apply, or the saved options. |
IsDirty |
True when Editing differs from Applied. Apply and Revert are enabled only then. |
ApplyAsync() |
Sets Editing on the game and saves it. True when the edits stay. |
Revert(), Defaults() |
Sets Editing to Applied, or to DefaultOptions(). |
PrefsKey (prefs-key) |
The PlayerPrefs key. The panel loads the saved options on the first attach. Empty: Apply does not save. |
ShowButtons (show-buttons) |
False hides the buttons, for a larger settings screen with its own buttons that call the methods. |
How to make a panel:
- Make a
[Serializable]subclass ofSettingsOptionswith public fields. Use thePropertyGridattributes:[Category],[Range],[Description],[InspectorName],[EnabledIf]. - Make a
[UxmlElement] partialsubclass ofSettingsPanel<T>. - Override
Capture()(the values in effect now),DefaultOptions()andApplyOptions(options). - Call
AddGrid()in the constructor for aPropertyGridofEditing.
[Serializable]
public class GameplayOptions : SettingsOptions
{
public static GameplayOptions Current = new();
[Category("Gameplay"), Range(0, 2), Description("0: easy, 2: hard.")]
public int Difficulty = 1;
[Category("Gameplay"), InspectorName("Show hints")]
public bool ShowHints = true;
}
[UxmlElement]
public partial class GameplaySettingsPanel : SettingsPanel<GameplayOptions>
{
public GameplaySettingsPanel() : base("mygame.gameplay") => AddGrid();
protected override GameplayOptions Capture() => (GameplayOptions)GameplayOptions.Current.Clone();
protected override GameplayOptions DefaultOptions() => new();
protected override void ApplyOptions(GameplayOptions options) => options.CopyTo(GameplayOptions.Current);
}
Tips:
SettingsOptionscopies, compares and saves withJsonUtility. Only the serialized fields count.- Override
ConfirmAsync(old, next)to ask the player before the edits stay.GraphicsSettingsPaneluses it for the display mode. - A panel without a
PropertyGridadds its own controls toBody, overridesShowEditing()to showEditingin them, and callsShowDirty()after an edit.InputSettingsPaneldoes this. SettingsOptions.Load(key)is virtual. Override it when a save must merge into the options, asInputBindingOptionsdoes with the binding ids.- Call
Reload()when the source ofCapture()changes, for example after a newActionsasset. It drops the edits and loads the saved options again. - A screen with several panels, such as the Settings screen of the GameMenu example, sets
show-buttons="false"on each panel. Its own Apply button awaitsApplyAsync()of each panel, and its dirty state is true when oneIsDirtyis true. - Give the panel a parent that grows. The body has a flex basis of 0 and a minimum height of 120 px, so it scrolls in a short parent. In a
TabView, also make the tab content container grow (seeSettings.ussin the example).
Styling
| Class | Element |
|---|---|
tb-settings-panel |
The panel, on every SettingsPanel. It grows to fill its parent. |
tb-graphics-settings |
Also on a GraphicsSettingsPanel. |
tb-audio-settings |
Also on an AudioSettingsPanel. |
tb-input-settings |
Also on an InputSettingsPanel. |
tb-input-settings__header |
The title row of an InputSettingsPanel: Action, Keyboard and mouse, Gamepad. Bold muted text and a bottom border. |
tb-input-settings__rows |
The ScrollView of the action rows. |
tb-input-settings__map |
The title of an action map, when the asset has more than one map. Bold, on --tb-color-surface-alt. |
tb-input-settings__row |
The row of one action. |
tb-input-settings__action |
The action name, 120 px wide. Also on the first header label. |
tb-input-settings__key |
The cell of a KeyBindingField. The two cells share the width that is left. Also on the two column header labels. |
tb-input-settings__key--none |
On a cell without a field: the action has no binding for that device. |
tb-settings-panel__body |
The body with the PropertyGrid. Its flex basis is 0, so it scrolls in a short panel. Its minimum height is 120 px, so some rows show when the parent does not grow. |
tb-settings-panel__buttons |
The row of the Defaults, Revert and Apply buttons, on the right. The buttons have the look of the MessageBox buttons. |