Editorial illustration: Audio settings that survive scene changes

Audio settings that survive scene changes

The problem I needed to solve

Audio preferences should not disappear when moving from the menu into Hokm. I needed shared state that persists and informs active consumers when it changes.

Implementation in this snapshot

CardGameSettingsService lazily loads sound, music, vibration and language from PlayerPrefs. SetMusicEnabled and other setters call SaveAndNotify only when their values change.

The design decision and its cost

SettingsChanged delivers a complete CardGameSettingsState. Persian is the default language, while a previously saved language is retained; switching language changes the central preference.

Current boundaries

Local persistence is not a cloud account or cross-device synchronization. A vibration preference also does not prove haptic feedback is implemented on every device.

Shared preferences, consumer-specific reactions

When a player disables music in the menu and enters Hokm, the preference should follow them. EnsureLoaded reads PlayerPrefs lazily, and CurrentState combines sound, music, vibration and language. Setters return early for unchanged values, so a UI refresh sending the same value does not necessarily save or publish another event. Newly activated listeners must read current state rather than wait only for future changes.

CardGameAudioManager demonstrates consumption: OnEnable subscribes to SettingsChanged and immediately applies CurrentState; OnDisable unsubscribes. Music and effects use separate AudioSources, and PlaySfx checks sound preference before PlayOneShot. ApplySettings mutes disabled music and pauses it if playing. These details explain preference application without supplying measurements of audio quality, latency or behavior across devices. Shared settings are distinct from audio-experience evaluation.

SaveAndNotify writes four keys, calls PlayerPrefs.Save and then publishes the complete state. ResetToDefaults enables all options and selects Persian immediately. Saved language is read through a direct enum cast without range validation in this service, so local loading does not automatically repair every invalid value. Vibration remains a stored preference; proving haptic execution requires its hardware consumer and call path. A saved boolean alone does not implement that capability.

What this stage taught me

For me, this creates continuity. Menu and game should understand the same person’s preferences, while each consumer remains responsible for correctly applying them to its own audio or text.

Explore Dalo

Latest devlogs

Editorial illustration: Pasur launch and telemetry in the shared structure

Pasur launch and telemetry in the shared structure

Adding Pasur needs both a correct mode handoff and valid public telemetry.

Read article
Editorial illustration: Pasur bot decisions from capture options

Pasur bot decisions from capture options

My teammate’s Pasur bot chooses among legal options without inspecting hidden opposing cards.

Read article
Editorial illustration: Capturing table cards in Pasur

Capturing table cards in Pasur

In my teammate’s implementation, Pasur combines selecting a hand card with selecting table cards. Its rules must produce valid sets and prohibit ignoring an available capture.

Read article
Dalo