Avant de commencer
Avant de pouvoir utiliser Realtime Database, vous devez :
Enregistrez votre projet Unity et configurez-le pour utiliser Firebase.
Si votre projet Unity utilise déjà Firebase, il est déjà enregistré et configuré pour Firebase.
Si vous n'avez pas de projet Unity, vous pouvez télécharger un exemple d'application.
Ajoutez le SDK Firebase Unity (plus précisément
FirebaseDatabase.unitypackage
) à votre projet Unity.
Notez que l'ajout de Firebase à votre projet Unity implique des tâches à la fois dans la console Firebase et dans votre projet Unity ouvert (par exemple, vous téléchargez des fichiers de configuration Firebase depuis la console, puis vous les déplacez dans votre projet Unity).
Enregistrer des données
Il existe cinq méthodes pour écrire des données dans Firebase Realtime Database :
Méthode | Utilisations courantes |
---|---|
SetValueAsync() |
Écrivez ou remplacez des données dans un chemin défini, tel que users/<user-id>/<username> . |
SetRawJsonValueAsync() |
Écrivez ou remplacez des données avec du code JSON brut, par exemple users/<user-id>/<username> . |
Push() |
Ajoutez-les à une liste de données. Chaque fois que vous appelez Push() , Firebase génère une clé unique qui peut également être utilisée comme identifiant unique, par exemple user-scores/<user-id>/<unique-score-id> . |
UpdateChildrenAsync() |
Mettez à jour certaines clés d'un chemin défini sans remplacer toutes les données. |
RunTransaction() |
Mettez à jour des données complexes qui pourraient être corrompues par des mises à jour simultanées. |
Obtenir un DatabaseReference
Pour écrire des données dans la base de données, vous avez besoin d'une instance de 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; } }
Écrire, mettre à jour ou supprimer des données au niveau d'une référence
Opérations d'écriture de base
Pour les opérations d'écriture de base, vous pouvez utiliser SetValueAsync()
pour enregistrer des données dans une référence spécifiée, en remplaçant toutes les données existantes à ce chemin d'accès. Vous pouvez utiliser cette méthode pour transmettre des types correspondant aux types JSON disponibles, comme suit :
string
long
double
bool
Dictionary<string, Object>
List<Object>
Si vous utilisez un objet C# typé, vous pouvez utiliser JsonUtility.ToJson()
intégré pour convertir l'objet en JSON brut et appeler SetRawJsonValueAsync()
.
Par exemple, vous pouvez avoir une classe User qui se présente comme suit :
public class User { public string username; public string email; public User() { } public User(string username, string email) { this.username = username; this.email = email; } }
Vous pouvez ajouter un utilisateur avec SetRawJsonValueAsync()
comme suit :
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); }
L'utilisation de SetValueAsync()
ou SetRawJsonValueAsync()
de cette manière écrase les données à l'emplacement spécifié, y compris les nœuds enfants. Toutefois, vous pouvez toujours mettre à jour un enfant sans réécrire l'intégralité de l'objet. Si vous souhaitez autoriser les utilisateurs à modifier leur profil, vous pouvez modifier leur nom d'utilisateur comme suit :
mDatabaseRef.Child("users").Child(userId).Child("username").SetValueAsync(name);
Ajouter des données à une liste
Utilisez la méthode Push()
pour ajouter des données à une liste dans les applications multi-utilisateurs.
La méthode Push()
génère une clé unique chaque fois qu'un enfant est ajouté à la référence Firebase spécifiée. En utilisant ces clés générées automatiquement pour chaque nouvel élément de la liste, plusieurs clients peuvent ajouter des enfants au même emplacement en même temps sans conflits d'écriture. La clé unique générée par Push()
est basée sur un code temporel. Les éléments de la liste sont donc automatiquement classés par ordre chronologique.
Vous pouvez utiliser la référence aux nouvelles données renvoyées par la méthode Push()
pour obtenir la valeur de la clé générée automatiquement de l'enfant ou définir des données pour l'enfant. L'appel de Key
sur une référence Push()
renvoie la valeur de la clé générée automatiquement.
Mettre à jour des champs spécifiques
Pour écrire simultanément dans des enfants spécifiques d'un nœud sans écraser d'autres nœuds enfants, utilisez la méthode UpdateChildrenAsync()
.
Lorsque vous appelez UpdateChildrenAsync()
, vous pouvez mettre à jour les valeurs enfants de niveau inférieur en spécifiant un chemin d'accès pour la clé. Si les données sont stockées à plusieurs endroits pour mieux évoluer, vous pouvez mettre à jour toutes les instances de ces données à l'aide de la distribution des données. Par exemple, un jeu peut avoir une classe LeaderboardEntry
comme celle-ci :
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; } }
Pour créer un LeaderboardEntry et le mettre à jour simultanément dans le flux des scores récents et dans la liste des scores de l'utilisateur, le jeu utilise un code semblable à celui-ci :
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); }
Cet exemple utilise Push()
pour créer une entrée dans le nœud contenant les entrées de tous les utilisateurs à l'adresse /scores/$key
et récupérer simultanément la clé avec Key
. La clé peut ensuite être utilisée pour créer une deuxième entrée dans les scores de l'utilisateur à /user-scores/$userid/$key
.
À l'aide de ces chemins, vous pouvez effectuer des mises à jour simultanées à plusieurs emplacements de l'arborescence JSON avec un seul appel à UpdateChildrenAsync()
, comme dans cet exemple qui crée la nouvelle entrée aux deux emplacements. Les mises à jour simultanées effectuées de cette manière sont atomiques : soit toutes les mises à jour réussissent, soit toutes échouent.
Supprimer des données
Le moyen le plus simple de supprimer des données consiste à appeler RemoveValue()
sur une référence à l'emplacement de ces données.
Vous pouvez également supprimer une valeur en spécifiant null
comme valeur pour une autre opération d'écriture, telle que SetValueAsync()
ou UpdateChildrenAsync()
. Vous pouvez utiliser cette technique avec UpdateChildrenAsync()
pour supprimer plusieurs enfants en un seul appel d'API.
Vous savez quand vos données sont validées.
Pour savoir quand vos données sont validées sur le serveur Firebase Realtime Database, vous pouvez ajouter une continuation. SetValueAsync()
et UpdateChildrenAsync()
renvoient un Task
qui vous permet de savoir quand l'opération est terminée. Si l'appel échoue pour une raison quelconque, la valeur IsFaulted
de Tasks sera définie sur "true", et la propriété Exception
indiquera la raison de l'échec.
Enregistrer des données en tant que transactions
Lorsque vous travaillez avec des données qui pourraient être corrompues par des modifications simultanées, comme des compteurs incrémentaux, vous pouvez utiliser une opération de transaction.
Vous attribuez un Func
à cette opération. Cette mise à jour Func
prend l'état actuel des données comme argument et renvoie le nouvel état souhaité que vous souhaitez écrire. Si un autre client écrit à l'emplacement avant que votre nouvelle valeur ne soit écrite, votre fonction de mise à jour est appelée à nouveau avec la nouvelle valeur actuelle, et l'écriture est réessayée.
Par exemple, dans un jeu, vous pouvez autoriser les utilisateurs à mettre à jour un classement avec les cinq meilleurs scores :
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); }); }
L'utilisation d'une transaction permet d'éviter que le classement soit incorrect si plusieurs utilisateurs enregistrent des scores en même temps ou si le client disposait de données obsolètes. Si la transaction est refusée, le serveur renvoie la valeur actuelle au client, qui exécute à nouveau la transaction avec la valeur mise à jour. Cette opération se répète jusqu'à ce que la transaction soit acceptée ou que trop de tentatives aient été effectuées.
Écrire des données hors connexion
Si un client perd sa connexion réseau, votre application continuera de fonctionner correctement.
Chaque client connecté à une base de données Firebase conserve sa propre version interne des données actives. Lorsque des données sont écrites, elles le sont d'abord dans cette version locale. Le client Firebase synchronise ensuite ces données avec les serveurs de base de données à distance et avec d'autres clients dans la mesure du possible.
Par conséquent, toutes les écritures dans la base de données déclenchent immédiatement des événements locaux, avant que les données ne soient écrites sur le serveur. Cela signifie que votre application reste réactive, quelle que soit la latence ou la connectivité du réseau.
Une fois la connectivité rétablie, votre application reçoit l'ensemble d'événements approprié afin que le client se synchronise avec l'état actuel du serveur, sans avoir à écrire de code personnalisé.