SettingsManager - Handhabung von Benutzereinstellungen in Unity

Im letzten Artikel haben wir uns mit dem Storage-Modul beschäftigt, das für die Speicherung einfacher Daten zuständig ist. Das Settings-Modul ist für die Verwaltung einer speziellen Form dieser Daten vorgesehen: Benutzereinstellungen. Dies können z.B. die gewünschte Auflösung, die Lautstärke, die Sprache und vieles mehr sein. Um die Speicherung dieser speziellen Daten zu verwalten, habe ich den SettingsService entwickelt.

Warum einen Extra-Service für Benutzereinstellungen?

Du hast dich sicher gefragt, warum ich einen extra Service für Benutzereinstellungen vorgesehen habe. Die StorageManager sind großartig und unter der Haube verwendet der SettingsManager den SimpleStorageManager, um die Daten zu speichern. Aber für Benutzereinstellungen gibt es ein paar zusätzliche Dinge, an die wir denken sollten.

Wenn der Benutzer Einstellungen ändert, wollen wir auf eine bestimmte Art und Weise darauf reagieren. Zum Beispiel wollen wir neue Sprachdateien laden, wenn der Benutzer die Sprache wechselt. Oder wir müssen die Lautstärke von AudioSources anpassen, wenn der Benutzer die Lautstärke ändert. Natürlich könnte man jedes Mal, wenn sich Daten im Spiel ändern, ein Ereignis auslösen. Aber dann herauszufinden, welche Daten für uns relevant sind, wäre ziemlich umständlich.

Außerdem werden viele von uns in Teams arbeiten. Deshalb wollen wir die gespeicherten Daten wahrscheinlich irgendwie strukturieren. Der Hauptgrund dafür ist, dass die Einstellungen irgendwo festgehalten werden müssen. Natürlich kann man einfach aufschreiben, welche Daten man wo gespeichert hat. Aber machen wir uns nichts vor. Dokumentation ist meist eine eher lästige Aufgabe und fällt gerne als erstes unter den Teppich. Es wäre doch viel schöner, wenn die Daten einfach in einer Klasse strukturiert wären und man sie gar nicht dokumentieren müsste.

Strukturierte Daten: SettingsData

Um die Benutzereinstellungen leicht zugänglich zu machen, können wir sie als Variablen in einer Klasse zusammenfassen. Diese Klasse können wir als serialisierbar deklarieren, so dass Unity sie über das JsonUtility in einen JSON-String umwandeln kann.

Awesome Accessories hat bereits eine SettingsData-Klasse mit allen Basis-Einstellungen, die für die verschiedenen Module notwendig sind.

    [System.Serializable]
    public class SettingsData : ISettingsData
    {
        public float masterVolume = 1f;
        public float musicVolume = 1f;
        public float soundVolume = 1f;
        public float voiceVolume = 1f;
        public string language = "EN";

        public ISettingsData FromJson(string jsonString)
        {
            return JsonUtility.FromJson<SettingsData>(jsonString);
        }
    }

Natürlich wirst du auch eigene Einstellungen registrieren wollen. Der beste Weg dafür ist, die Klasse zu erweitern. Das könnte z.B. so aussehen:

using Aureola.Settings;

[System.Serializable]
public class MyAwesomeSettingsData : SettingsData, ISettingsData
{
    public bool subtitles = true;
    public bool debugging = false;
    public string shadowQuality = "medium";
    public string textureQuality = "medium";

    new public ISettingsData FromJson(string jsonString)
    {
        return JsonUtility.FromJson<MyAwesomeSettingsData>(jsonString);
    }
}

Dann musst Du Deine eigene Settings-Klasse beim Manager registrieren und die Daten anschließend laden.

SettingsManager.service?.Register(new MyAwesomeSettingsData());
SettingsManager.service?.Load();

Das ist zugegebenermaßen noch etwas umständlich gelöst. Ich arbeite dahingehend noch an einem Automatismus.

Auf Einstellungen zugreifen

Wenn der SettingsManager eingerichtet ist und die Daten geladen sind, kannst Du auf alle Einstellungen zugreifen. Wichtig: Derzeit werden nur Integer, Float, String und Boolean unterstützt.

Du kannst Variablen mit den entsprechenden Set()-Methoden setzen:

SettingsManager.service?.Set("myFloatValue", myFloat);
SettingsManager.service?.Set("myStringValue", myString);
SettingsManager.service?.Set("myIntValue", myInt);
SettingsManager.service?.Set("myBooleanValue", myBoolean);

Sobald Du eine Einstellung verändert hast, werden die Daten sofort gespeichert. Im Anschluss wird der SettingsUpdated ausgelöst

Auf Daten zugreifen kannst Du mit den entsprechenden Get()-Methoden:

SettingsManager.service?.Get("myFloatValue", 0f);
SettingsManager.service?.Get("myStringValue", "");
SettingsManager.service?.Get("myIntValue", 0);
SettingsManager.service?.Get("myBooleanValue", false);

Event: SettingsUpdated

Wie zuvor erwähnt, müssen andere Manager & Behaviours auf Änderungen in den Einstellungen reagieren können. Darum wird bei jeder Änderung der Einstellungen der Event SettingsUpdated im Channel Settings veröffentlicht. Im TranslationManager (auf den ich in einem anderen Artikel zu sprechen kommen) sieht die Integration dann zum Beispiel so aus:

private void OnEnable()
{
    PubSubManager.service?.Subscribe(Channel.SETTINGS, typeof(SettingsUpdated), OnSettingsUpdated);
}

private void OnDisable()
{
    PubSubManager.service?.Unsubscribe(Channel.SETTINGS, typeof(SettingsUpdated), OnSettingsUpdated);
 }

private void OnSettingsUpdated(IGameEvent gameEvent)
{
    var SettingsUpdated = (SettingsUpdated) gameEvent;
    var settingsData = (SettingsData) SettingsUpdated.settings;

    _service.ChangeLanguage(settingsData.language);
}

Dein Feedback ist wichtig!

Was hältst Du von den hier vorgestellten Services? Fehlt Dir etwas oder funktioniert etwas nicht wie erwartet? Wie immer freue ich mich über Feedback. Lass mich gerne wissen was Du über dieses Modul denkst. Dafür kannst Du zum Beispiel die Kommentarfunktion unter dem Artikel nutzen. Weitere Kontakt-Möglichkeiten findest Du auf hier. Wenn Du einen Bug gefunden hast oder Dir eine Erweiterung wünscht, erstelle bitte einen Issue im GitHub-Repository. Weitere Dokumentation findest Du wie immer in der README des entsprechenden Moduls.

Noch keine Kommentare vorhanden.