Skip to content

Settings

Charles edited this page Jun 5, 2026 · 5 revisions

Introduction

Settings help make your game more accessible; however, they're often cumbersome to code on a short timeframe due in large part to the difficulty synchronizing the UI, save data, and the nodes they affect. To make this process as painless as possible, ProtoJam provides a data-driven settings framework that makes adding a new setting as simple as configuring a resource.

This framework is comprised of two components: the SettingsManager and the AbstractSetting-based settings you define. The SettingsManager is a static a class which reduces the tedium and loading/saving your settings to a pair of simple functions. AbstractSetting and its various subclasses are resources which both define the properties of a setting and act as handles to get or set its value.

ProtoJam provides the following setting types out of the box but you can create your own by extending AbstractSetting:

  • BooleanSetting - A simple on/off setting
  • RangeSetting - A floating point number constrained to a defined range and step amount
  • AudioBusVolumeRangeSetting - A variation of RangeSetting designed to store the linear volume of an audio bus

Note

This framework is intended for game settings only. All other save data should use the save game framework instead.

Using SettingsManager

The SettingsManager class is static and requires no setup to use; however, you can optionally change the location where a user's game settings are stored by modifying addons/proto_jam/settings/file_path in the project settings.

When starting the game, it's recommended to make a call to SettingsManager.load_settings() to load the user's settings. If successful, this will automatically update the value of any setting resource; otherwise, their values will be left at the defaults.

While each setting is immediately applied as it is changed, their current value will not be saved until a call to SettingsManager.save_settings() is made. This function will save the current value of all settings or return an error if they could not be saved.

Finally, a call to SettingsManager.clear_settings() may be made to immediately restore the default value of all settings. A subsequent call to SettingsManager.save_settings() is needed to save this change if desired.

Note

It is recommended to load save data from the main scene before anything else to ensure the user's volume and accessibility settings are applied as soon as possible. Furthermore, it is recommended to NOT save settings at shutdown or otherwise without the user's consent as this may be confusing.

Using AbstractSetting

AbstractSetting is the base resource which all settings extend. It provides a unique key to identify the setting in the save file, functions to get and set the value, and a value_changed signal which will be emitted any time the value changes (including when loading).

Important

No two settings may have the same key. Doing so will cause loading/saving conflicts.

Creating custom setting types

Several setting types derived from AbstractSetting are provided with ProtoJam but you may wish to create your own. Doing so is very easy and requires only four steps:

  1. Extend AbstractSetting
  2. Implement AbstractSetting.from_raw(value)
  3. Implement AbstractSetting.to_raw(value)
  4. Invoke AbstractSetting.emit_value_changed(value) as needed (see below)

Implementing to_raw and from_raw

The parameter to_raw accepts and from_raw returns define the type of the setting's value and may be any type (including classes); however, these functions must be capable of convert this type to and from a serializable (aka raw) representation respectively.

The following are the only valid return types for a to_raw implementation:

  • int
  • float
  • bool
  • null
  • String
  • StringName
  • Array (must only contain one of the above types)
  • Dictionary (must only contain the above types as keys or values)

The from_raw implementation must accept the same type to_raw returned; furthermore, it must gracefully handle null. In most cases, receiving null should result in a default value being returned.

When to call emit_value_changed

🚧 WIP

Examples

🚧 WIP

Clone this wiki locally