Prima di iniziare
Prima di poter utilizzare Realtime Database, devi:
Registra il tuo progetto Unity e configuralo in modo che utilizzi Firebase.
Se il tuo progetto Unity utilizza già Firebase, è già registrato e configurato per Firebase.
Se non hai un progetto Unity, puoi scaricare un'app di esempio.
Aggiungi l'SDK Firebase Unity (in particolare,
FirebaseDatabase.unitypackage
) al tuo progetto Unity.
Tieni presente che l'aggiunta di Firebase al tuo progetto Unity comporta attività sia nella Firebase console sia nel progetto Unity aperto (ad esempio, scarichi i file di configurazione Firebase dalla console, poi li sposti nel progetto Unity).
Risparmio dati
Esistono cinque metodi per scrivere dati in Firebase Realtime Database:
Metodo | Utilizzi comuni |
---|---|
SetValueAsync() |
Scrivi o sostituisci i dati in un percorso definito, ad esempio
users/<user-id>/<username> . |
SetRawJsonValueAsync() |
Scrivi o sostituisci i dati con JSON non elaborato, ad esempio
users/<user-id>/<username> . |
Push() |
Aggiungere a un elenco di dati. Ogni volta che chiami
Push() , Firebase genera una chiave univoca che può essere utilizzata anche
come identificatore univoco, ad esempio
user-scores/<user-id>/<unique-score-id> . |
UpdateChildrenAsync() |
Aggiorna alcune chiavi per un percorso definito senza sostituire tutti i dati. |
RunTransaction() |
Aggiorna dati complessi che potrebbero essere danneggiati da aggiornamenti simultanei. |
Recuperare un DatabaseReference
Per scrivere i dati nel database, devi disporre di un'istanza di 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; } }
Scrivere, aggiornare o eliminare dati in un riferimento
Operazioni di scrittura di base
Per le operazioni di scrittura di base, puoi utilizzare SetValueAsync()
per salvare i dati in un riferimento specificato, sostituendo tutti i dati esistenti nel percorso. Puoi utilizzare questo
metodo per trasmettere tipi che corrispondono ai tipi JSON disponibili nel seguente modo:
string
long
double
bool
Dictionary<string, Object>
List<Object>
Se utilizzi un oggetto C# digitato, puoi utilizzare JsonUtility.ToJson()
integrato per convertire l'oggetto in JSON non elaborato e chiamare SetRawJsonValueAsync()
.
Ad esempio, potresti avere una classe User con il seguente aspetto:
public class User { public string username; public string email; public User() { } public User(string username, string email) { this.username = username; this.email = email; } }
Puoi aggiungere un utente con SetRawJsonValueAsync()
nel seguente modo:
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'utilizzo di SetValueAsync()
o SetRawJsonValueAsync()
in questo modo sovrascrive i dati
nella posizione specificata, inclusi tutti i nodi secondari. Tuttavia, puoi comunque
aggiornare un bambino senza riscrivere l'intero oggetto. Se vuoi consentire agli utenti
di aggiornare i propri profili, puoi aggiornare il nome utente nel seguente modo:
mDatabaseRef.Child("users").Child(userId).Child("username").SetValueAsync(name);
Aggiungere a un elenco di dati
Utilizza il metodo Push()
per aggiungere dati a un elenco in applicazioni multiutente.
Il metodo Push()
genera una chiave univoca ogni volta che viene aggiunto un nuovo
elemento secondario al riferimento Firebase specificato. Utilizzando queste
chiavi generate automaticamente per ogni nuovo elemento dell'elenco, più client possono
aggiungere figli alla stessa posizione contemporaneamente senza conflitti di scrittura. La
chiave univoca generata da Push()
si basa su un timestamp, quindi gli elementi dell'elenco vengono
ordinati automaticamente in ordine cronologico.
Puoi utilizzare il riferimento ai nuovi dati restituiti dal metodo Push()
per ottenere
il valore della chiave generata automaticamente dell'elemento secondario o impostare i dati per l'elemento secondario. La chiamata
Key
su un riferimento Push()
restituisce il valore della
chiave generata automaticamente.
Aggiornare campi specifici
Per scrivere contemporaneamente a nodi secondari specifici di un nodo senza sovrascrivere altri
nodi secondari, utilizza il metodo UpdateChildrenAsync()
.
Quando chiami UpdateChildrenAsync()
, puoi aggiornare i valori secondari di livello inferiore specificando un percorso per la chiave. Se i dati vengono archiviati in più posizioni per migliorare la scalabilità, puoi aggiornare tutte le istanze di questi dati utilizzando la distribuzione dei dati. Ad esempio, un
gioco potrebbe avere una classe LeaderboardEntry
come questa:
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; } }
Per creare una LeaderboardEntry e aggiornarla contemporaneamente al feed dei punteggi recenti e all'elenco dei punteggi dell'utente, il gioco utilizza un codice simile a questo:
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); }
Questo esempio utilizza Push()
per creare una voce nel nodo contenente le voci per tutti gli utenti all'indirizzo /scores/$key
e recuperare contemporaneamente la chiave con Key
. La chiave può essere utilizzata per creare una seconda voce nei punteggi dell'utente all'indirizzo /user-scores/$userid/$key
.
Utilizzando questi percorsi, puoi eseguire aggiornamenti simultanei a più posizioni nell'albero JSON con una singola chiamata a UpdateChildrenAsync()
, ad esempio come questo esempio crea la nuova voce in entrambe le posizioni. Gli aggiornamenti simultanei eseguiti in questo modo sono atomici: o tutti gli aggiornamenti vanno a buon fine o tutti gli aggiornamenti non vanno a buon fine.
Elimina dati
Il modo più semplice per eliminare i dati è chiamare RemoveValue()
su un riferimento alla
posizione di questi dati.
Puoi anche eliminare specificando null
come valore per un'altra operazione di scrittura
come SetValueAsync()
o UpdateChildrenAsync()
. Puoi utilizzare questa
tecnica con UpdateChildrenAsync()
per eliminare più figli in una singola chiamata
API.
Scopri quando i tuoi dati vengono salvati.
Per sapere quando i dati vengono inviati al server Firebase Realtime Database, puoi
aggiungere una continuazione. Sia SetValueAsync()
che UpdateChildrenAsync()
restituiscono una Task
che ti consente di sapere quando l'operazione è completata. Se la chiamata non va a buon fine per qualsiasi motivo, Tasks IsFaulted
sarà true e la proprietà Exception
indicherà il motivo dell'errore.
Salvare i dati come transazioni
Quando lavori con dati che potrebbero essere danneggiati da modifiche simultanee, come i contatori incrementali, puoi utilizzare un'operazione di transazione.
Assegni un Func
a questa operazione. Questo aggiornamento Func
prende lo stato attuale
dei dati come argomento e restituisce il nuovo stato desiderato che vuoi
scrivere. Se un altro client scrive nella posizione prima che il nuovo valore venga
scritto correttamente, la funzione di aggiornamento viene chiamata di nuovo con il nuovo valore
corrente e la scrittura viene ritentata.
Ad esempio, in un gioco potresti consentire agli utenti di aggiornare una classifica con i cinque punteggi più alti:
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'utilizzo di una transazione impedisce che la classifica sia errata se più utenti registrano punteggi contemporaneamente o se il client dispone di dati obsoleti. Se la transazione viene rifiutata, il server restituisce il valore corrente al client, che esegue nuovamente la transazione con il valore aggiornato. Questa operazione si ripete finché la transazione non viene accettata o non vengono effettuati troppi tentativi.
Scrivere dati offline
Se un client perde la connessione di rete, la tua app continuerà a funzionare correttamente.
Ogni client connesso a un database Firebase mantiene la propria versione interna di tutti i dati attivi. Quando i dati vengono scritti, vengono scritti prima in questa versione locale. Il client Firebase sincronizza quindi i dati con i server di database remoti e con altri client in base al "miglior sforzo".
Di conseguenza, tutte le scritture nel database attivano immediatamente gli eventi locali, prima che i dati vengano scritti sul server. Ciò significa che la tua app rimane reattiva indipendentemente dalla latenza o dalla connettività di rete.
Una volta ripristinata la connettività, la tua app riceve il set appropriato di eventi in modo che il client si sincronizzi con lo stato attuale del server, senza dover scrivere codice personalizzato.