Datenvolumen sparen

Hinweis

Bevor Sie Realtime Database verwenden können, müssen Sie Folgendes tun:

  • Registrieren Sie Ihr Unity-Projekt und konfigurieren Sie es für die Verwendung von Firebase.

    • Wenn Ihr Unity-Projekt bereits Firebase verwendet, ist es bereits registriert und für Firebase konfiguriert.

    • Wenn Sie kein Unity-Projekt haben, können Sie eine Beispiel-App herunterladen.

  • Fügen Sie Ihrem Unity-Projekt das Firebase Unity SDK (FirebaseDatabase.unitypackage) hinzu.

Das Hinzufügen von Firebase zu Ihrem Unity-Projekt umfasst Aufgaben in der Firebase Konsole und in Ihrem geöffneten Unity-Projekt (Sie laden beispielsweise Firebase-Konfigurationsdateien aus der Konsole herunter und verschieben sie dann in Ihr Unity-Projekt).

Daten speichern

Es gibt fünf Methoden zum Schreiben von Daten in die Firebase Realtime Database:

Methode Gängige Einsatzmöglichkeiten
SetValueAsync() Daten in einen definierten Pfad schreiben oder ersetzen, z. B. users/<user-id>/<username>.
SetRawJsonValueAsync() Daten mit unformatiertem JSON schreiben oder ersetzen, z. B. users/<user-id>/<username>.
Push() Einer Datenliste hinzufügen. Jedes Mal, wenn Sie Push() aufrufen, generiert Firebase einen eindeutigen Schlüssel, der auch als eindeutige ID verwendet werden kann, z. B. user-scores/<user-id>/<unique-score-id>.
UpdateChildrenAsync() Einige der Schlüssel für einen definierten Pfad aktualisieren, ohne alle Daten zu ersetzen.
RunTransaction() Komplexe Daten aktualisieren, die durch gleichzeitige Aktualisierungen beschädigt werden könnten.

DatabaseReference abrufen

Um Daten in die Datenbank zu schreiben, benötigen Sie eine Instanz von DatabaseReference:

using Firebase;
using Firebase.Database;

public class MyScript: MonoBehaviour {
  void Start() {
    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

Daten an einer Referenz schreiben, aktualisieren oder löschen

Grundlegende Schreibvorgänge

Für grundlegende Schreibvorgänge können Sie SetValueAsync() verwenden, um Daten an einer bestimmten Referenz zu speichern und alle vorhandenen Daten an diesem Pfad zu ersetzen. Mit dieser Methode können Sie Typen übergeben, die den verfügbaren JSON-Typen entsprechen:

  • string
  • long
  • double
  • bool
  • Dictionary<string, Object>
  • List<Object>

Wenn Sie ein typisiertes C#-Objekt verwenden, können Sie mit der integrierten Funktion JsonUtility.ToJson() das Objekt in unformatiertes JSON konvertieren und SetRawJsonValueAsync() aufrufen. Beispiel: Sie haben eine Nutzerklasse, die so aussieht:

public class User {
    public string username;
    public string email;

    public User() {
    }

    public User(string username, string email) {
        this.username = username;
        this.email = email;
    }
}

Sie können einen Nutzer mit SetRawJsonValueAsync() so hinzufügen:

private void writeNewUser(string userId, string name, string email) {
    User user = new User(name, email);
    string json = JsonUtility.ToJson(user);

    mDatabaseRef.Child("users").Child(userId).SetRawJsonValueAsync(json);
}

Wenn Sie SetValueAsync() oder SetRawJsonValueAsync() auf diese Weise verwenden, werden Daten am angegebenen Speicherort überschrieben, einschließlich aller untergeordneten Knoten. Sie können jedoch weiterhin ein untergeordnetes Element aktualisieren, ohne das gesamte Objekt neu zu schreiben. Wenn Sie Nutzern erlauben möchten, ihre Profile zu aktualisieren, können Sie den Nutzernamen so aktualisieren:

mDatabaseRef.Child("users").Child(userId).Child("username").SetValueAsync(name);

Einer Datenliste anhängen

Verwenden Sie die Methode Push(), um Daten an eine Liste in Mehrnutzeranwendungen anzuhängen. Die Methode Push() generiert jedes Mal einen eindeutigen Schlüssel, wenn der angegebenen Firebase-Referenz ein neues untergeordnetes Element hinzugefügt wird. Wenn Sie diese automatisch generierten Schlüssel für jedes neue Element in der Liste verwenden, können mehrere Clients gleichzeitig untergeordnete Elemente am selben Speicherort hinzufügen, ohne dass es zu Schreibkonflikten kommt. Der von Push() generierte eindeutige Schlüssel basiert auf einem Zeitstempel, sodass Listenelemente automatisch chronologisch sortiert werden.

Sie können die von der Methode Push() zurückgegebene Referenz auf die neuen Daten verwenden, um den Wert des automatisch generierten Schlüssels des untergeordneten Elements abzurufen oder Daten für das untergeordnete Element festzulegen. Wenn Sie Key für eine Push()-Referenz aufrufen, wird der Wert des automatisch generierten Schlüssels zurückgegeben.

Bestimmte Felder aktualisieren

Wenn Sie gleichzeitig in bestimmte untergeordnete Elemente eines Knotens schreiben möchten, ohne andere untergeordnete Knoten zu überschreiben, verwenden Sie die Methode UpdateChildrenAsync().

Wenn Sie UpdateChildrenAsync() aufrufen, können Sie untergeordnete Werte auf niedrigerer Ebene aktualisieren, indem Sie einen Pfad für den Schlüssel angeben. Wenn Daten an mehreren Speicherorten gespeichert sind, um besser zu skalieren , können Sie alle Instanzen dieser Daten mit Data Fan-Out aktualisieren. Beispiel: Ein Spiel hat möglicherweise eine Klasse LeaderboardEntry wie diese:

public class LeaderboardEntry {
    public string uid;
    public int score = 0;

    public LeaderboardEntry() {
    }

    public LeaderboardEntry(string uid, int score) {
        this.uid = uid;
        this.score = score;
    }

    public Dictionary<string, Object> ToDictionary() {
        Dictionary<string, Object> result = new Dictionary<string, Object>();
        result["uid"] = uid;
        result["score"] = score;

        return result;
    }
}

Um einen Eintrag in der Bestenliste zu erstellen und ihn gleichzeitig mit dem aktuellen Feed der Ergebnisse und der eigenen Liste der Ergebnisse des Nutzers zu aktualisieren, verwendet das Spiel Code wie diesen:

private void WriteNewScore(string userId, int score) {
    // Create new entry at /user-scores/$userid/$scoreid and at
    // /leaderboard/$scoreid simultaneously
    string key = mDatabase.Child("scores").Push().Key;
    LeaderBoardEntry entry = new LeaderBoardEntry(userId, score);
    Dictionary<string, Object> entryValues = entry.ToDictionary();

    Dictionary<string, Object> childUpdates = new Dictionary<string, Object>();
    childUpdates["/scores/" + key] = entryValues;
    childUpdates["/user-scores/" + userId + "/" + key] = entryValues;

    mDatabase.UpdateChildrenAsync(childUpdates);
}

In diesem Beispiel wird Push() verwendet, um einen Eintrag im Knoten mit Einträgen für alle Nutzer unter /scores/$key zu erstellen und gleichzeitig den Schlüssel mit Key abzurufen. Der Schlüssel kann dann verwendet werden, um einen zweiten Eintrag in den Ergebnissen des Nutzers unter /user-scores/$userid/$key zu erstellen.

Mit diesen Pfaden können Sie mit einem einzigen Aufruf von UpdateChildrenAsync() gleichzeitige Aktualisierungen an mehreren Speicherorten in der JSON-Struktur vornehmen. In diesem Beispiel wird der neue Eintrag an beiden Speicherorten erstellt. Gleichzeitige Aktualisierungen, die auf diese Weise vorgenommen werden, sind atomar: Entweder sind alle Aktualisierungen erfolgreich oder alle Aktualisierungen schlagen fehl.

Daten löschen

Die einfachste Möglichkeit, Daten zu löschen, besteht darin, RemoveValue() für eine Referenz auf den Speicherort dieser Daten aufzurufen.

Sie können auch löschen, indem Sie null als Wert für einen anderen Schreibvorgang wie SetValueAsync() oder UpdateChildrenAsync() angeben. Sie können diese Technik mit UpdateChildrenAsync() verwenden, um mehrere untergeordnete Elemente in einem einzigen API-Aufruf zu löschen.

Wissen, wann Ihre Daten übernommen wurden

Wenn Sie wissen möchten, wann Ihre Daten auf dem Firebase Realtime Database Server übernommen wurden, können Sie eine Fortsetzung hinzufügen. Sowohl SetValueAsync() als auch UpdateChildrenAsync() geben eine Task zurück, mit der Sie wissen, wann der Vorgang abgeschlossen ist. Wenn der Aufruf aus irgendeinem Grund nicht erfolgreich ist, ist IsFaulted für die Aufgaben „true“ und die Eigenschaft Exception gibt an, warum der Fehler aufgetreten ist.

Daten als Transaktionen speichern

Wenn Sie mit Daten arbeiten, die durch gleichzeitige Änderungen beschädigt werden könnten, z. B. inkrementelle Zähler, können Sie einen Transaktionsvorgang verwenden. Sie geben diesem Vorgang eine Func. Diese Func für die Aktualisierung verwendet den aktuellen Zustand der Daten als Argument und gibt den neuen gewünschten Zustand zurück, den Sie schreiben möchten. Wenn ein anderer Client an den Speicherort schreibt, bevor Ihr neuer Wert erfolgreich geschrieben wurde, wird Ihre Aktualisierungsfunktion noch einmal mit dem neuen aktuellen Wert aufgerufen und der Schreibvorgang wird wiederholt.

In einem Spiel könnten Sie Nutzern beispielsweise erlauben, eine Bestenliste mit den fünf höchsten Ergebnissen zu aktualisieren:

private void AddScoreToLeaders(string email, 
                               long score,
                               DatabaseReference leaderBoardRef) {

    leaderBoardRef.RunTransaction(mutableData => {
      List<object> leaders = mutableData.Value as List<object>

      if (leaders == null) {
        leaders = new List<object>();
      } else if (mutableData.ChildrenCount >= MaxScores) {
        long minScore = long.MaxValue;
        object minVal = null;
        foreach (var child in leaders) {
          if (!(child is Dictionary<string, object>)) continue;
          long childScore = (long)
                      ((Dictionary<string, object>)child)["score"];
          if (childScore < minScore) {
            minScore = childScore;
            minVal = child;
          }
        }
        if (minScore > score) {
          // The new score is lower than the existing 5 scores, abort.
          return TransactionResult.Abort();
        }

        // Remove the lowest score.
        leaders.Remove(minVal);
      }

      // Add the new high score.
      Dictionary<string, object> newScoreMap =
                       new Dictionary<string, object>();
      newScoreMap["score"] = score;
      newScoreMap["email"] = email;
      leaders.Add(newScoreMap);
      mutableData.Value = leaders;
      return TransactionResult.Success(mutableData);
    });
}

Durch die Verwendung einer Transaktion wird verhindert, dass die Bestenliste falsch ist, wenn mehrere Nutzer gleichzeitig Ergebnisse aufzeichnen oder der Client veraltete Daten hatte. Wenn die Transaktion abgelehnt wird, gibt der Server den aktuellen Wert an den Client zurück, der die Transaktion mit dem aktualisierten Wert noch einmal ausführt. Dies wird wiederholt, bis die Transaktion akzeptiert wird oder zu viele Versuche unternommen wurden.

Daten offline schreiben

Wenn ein Client die Netzwerkverbindung verliert, funktioniert Ihre App weiterhin ordnungsgemäß.

Jeder Client, der mit einer Firebase-Datenbank verbunden ist, verwaltet eine eigene interne Version aller aktiven Daten. Wenn Daten geschrieben werden, werden sie zuerst in diese lokale Version geschrieben. Der Firebase-Client synchronisiert diese Daten dann nach bestem Bemühen mit den Remote-Datenbankservern und anderen Clients.

Daher lösen alle Schreibvorgänge in die Datenbank sofort lokale Ereignisse aus, bevor Daten auf den Server geschrieben werden. Das bedeutet, dass Ihre App unabhängig von Netzwerklatenz oder Verbindung reaktionsschnell bleibt.

Sobald die Verbindung wiederhergestellt ist, erhält Ihre App die entsprechenden Ereignisse, sodass der Client mit dem aktuellen Serverstatus synchronisiert wird, ohne dass Sie benutzerdefinierten Code schreiben müssen.

Nächste Schritte