Ir para o console

Salvar dados

Antes de começar

Antes de usar o Realtime Database, você precisa:

  • registrar seu projeto do Unity e configurá-lo para usar o Firebase.

    • Se o projeto do Unity já usa o Firebase, ele já está registrado e configurado para essa plataforma.

    • Se você não tiver um projeto do Unity, poderá fazer o download de um aplicativo de amostra.

  • Adicionar o SDK do Firebase para Unity (especificamente, FirebaseDatabase.unitypackage) ao seu projeto do Unity.

Adicionar o Firebase ao seu projeto do Unity envolve tarefas no Console do Firebase e no projeto do Unity aberto (por exemplo, fazer o download dos arquivos de configuração do Firebase no Console e movê-los para o projeto do Unity).

Salvar dados

Há cinco métodos para escrever dados no Firebase Realtime Database:

Método Usos comuns
SetValueAsync() Escreva ou substitua dados em um caminho definido, como users/<user-id>/<username>.
SetRawJsonValueAsync() Escreva ou substitua dados com JSON bruto, como users/<user-id>/<username>.
Push() Adicione a uma lista de dados. Toda vez que você chama Push(), o Firebase gera uma chave exclusiva que também pode ser usada como um identificador exclusivo como, por exemplo, user-scores/<user-id>/<unique-score-id>.
UpdateChildrenAsync() Atualize algumas das chaves de um caminho definido sem substituir todos os dados.
RunTransaction() Atualize dados complexos que possam ser corrompidos por atualizações simultâneas.

Receber um DatabaseReference

Para gravar dados no Database, você precisa de uma instância de DatabaseReference:

using Firebase;
using Firebase.Database;
using Firebase.Unity.Editor;

public class MyScript: MonoBehaviour {
  void Start() {
    // Set up the Editor before calling into the realtime database.
    FirebaseApp.DefaultInstance.SetEditorDatabaseUrl("https://YOUR-FIREBASE-APP.firebaseio.com/");

    // Get the root reference location of the database.
    DatabaseReference reference = FirebaseDatabase.DefaultInstance.RootReference;
  }
}

Gravar, atualizar ou excluir dados em uma referência

Operações básicas de gravação

Em operações básicas de gravação, use SetValueAsync() para salvar dados em uma referência específica e substitua os dados existentes no caminho. Você pode usar este método para transmitir tipos que correspondem aos tipos de JSON disponíveis abaixo:

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

Se você usar um objeto do tipo C#, poderá utilizar o JsonUtility.ToJson() integrado para converter o objeto em JSON bruto e chamar SetRawJsonValueAsync(). Por exemplo, é possível que você tenha uma classe de usuário como a descrita a seguir:

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

    public User() {
    }

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

Você pode adicionar um usuário com SetRawJsonValueAsync() da seguinte forma:

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);
}

O uso de SetValueAsync() ou SetRawJsonValueAsync() desta maneira substitui os dados no local especificado, incluindo os nodes filhos. No entanto, ainda é possível atualizar um node filho sem reescrever todo o objeto. Para permitir que os usuários atualizem os próprios perfis, atualize o nome de usuário deles desta forma:

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

Anexar a uma lista de dados

Use o método Push() para anexar dados a uma lista em aplicativos de vários usuários. O método Push() gera uma chave exclusiva sempre que um novo node filho for adicionado a uma referência específica do Firebase. Ao usar essas chaves geradas automaticamente para cada novo elemento da lista, vários clientes podem adicionar filhos no mesmo local simultaneamente sem criar conflitos de gravação. A chave exclusiva gerada por Push() é baseada em um timestamp. Portanto, os itens da lista são organizados automaticamente em ordem cronológica.

Use a referência aos novos dados retornados pelo método Push() para receber o valor da chave filha gerada automaticamente ou para definir os dados da chave filha. Chamar a Key em uma referência Push() retorna o valor da chave gerada automaticamente.

Atualizar campos específicos

Para gravar filhos específicos de um node simultaneamente sem substituir outros nodes filhos, use o método UpdateChildrenAsync().

Ao chamar UpdateChildrenAsync(), atualize valores de filhos de nível inferior especificando um caminho para a chave. Se os dados estiverem armazenados em vários locais para aprimorar a escalabilidade, atualize todas as instâncias usando a distribuição de dados. Por exemplo, um jogo pode ter uma classe LeaderboardEntry como esta:

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&ltstring, Object&gt ToDictionary() {
        Dictionary&ltstring, Object&gt result = new Dictionary&ltstring, Object&gt();
        result["uid"] = uid;
        result["score"] = score;

        return result;
    }
}

Para criar uma LeaderboardEntry e atualizá-la simultaneamente no feed de pontuação recente e na lista de pontuação do usuário, o jogo usa o seguinte código:

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&ltstring, Object&gt entryValues = entry.ToDictionary();

    Dictionary&ltstring, Object&gt childUpdates = new Dictionary&ltstring, Object&gt();
    childUpdates["/scores/" + key] = entryValues;
    childUpdates["/user-scores/" + userId + "/" + key] = entryValues;

    mDatabase.UpdateChildrenAsync(childUpdates);
}

Este exemplo usa Push() para criar uma entrada no node que contém entradas para todos os usuários em /scores/$key e para recuperar simultaneamente a chave com Key. Desta forma, a chave pode ser usada para criar uma segunda entrada nas pontuações do usuário em /user-scores/$userid/$key.

Com esses caminhos, você faz atualizações simultâneas em vários locais da árvore JSON com uma única chamada ao UpdateChildrenAsync() e cria a nova entrada nos dois locais. Atualizações simultâneas realizadas dessa maneira são atômicas: ou todas funcionam ou todas falham.

Excluir dados

A maneira mais simples de excluí-los é chamar RemoveValue() em uma referência ao local dos dados.

Você também pode fazer a exclusão ao especificar null como o valor de outra operação de gravação, como SetValueAsync() ou UpdateChildrenAsync(). Use essa técnica com UpdateChildrenAsync() para excluir vários filhos de uma única chamada de API.

Como saber se os seus dados foram confirmados

Para saber se os seus dados foram confirmados no servidor do Firebase Realtime Database, você pode adicionar uma continuação. SetValueAsync() e UpdateChildrenAsync() retornam uma Task que permite que você saiba quando a operação foi concluída. Se, por qualquer motivo, a chamada falhar, as Tarefas IsFaulted serão verdadeiras e a propriedade Exception indicará a causa da falha.

Salvar dados como transações

Ao trabalhar com dados que podem ser corrompidos por modificações simultâneas, como contadores incrementais, use uma operação de transação. Dê a essa operação a função Func. A função de atualização Func usa o estado atual dos dados como um argumento e retorna o novo estado de acordo com as preferências de gravação. Se outro cliente fizer uma gravação no local antes que o seu novo valor seja gravado, sua função de atualização será chamada novamente com o novo valor atual e a gravação será repetida.

Por exemplo, você pode permitir que os usuários atualizem uma tabela de classificação em um jogo com as cinco pontuações mais altas:

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

    leaderBoardRef.RunTransaction(mutableData =&gt {
      List&ltobject&gt leaders = mutableData.Value as List&ltobject>

      if (leaders == null) {
        leaders = new List&ltobject&gt();
      } else if (mutableData.ChildrenCount &gt= MaxScores) {
        long minScore = long.MaxValue;
        object minVal = null;
        foreach (var child in leaders) {
          if (!(child is Dictionary&ltstring, object&gt)) continue;
          long childScore = (long)
                      ((Dictionary&ltstring, object&gt)child)["score"];
          if (childScore &lt minScore) {
            minScore = childScore;
            minVal = child;
          }
        }
        if (minScore &gt 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&ltstring, object&gt newScoreMap =
                       new Dictionary&ltstring, object&gt();
      newScoreMap["score"] = score;
      newScoreMap["email"] = email;
      leaders.Add(newScoreMap);
      mutableData.Value = leaders;
      return TransactionResult.Success(mutableData);
    });
}

Usar uma transação evita que a tabela de classificação fique incorreta caso vários usuários gravem resultados ao mesmo tempo ou o cliente tenha dados desatualizados. Se a transação for rejeitada, o servidor retornará o valor atual ao cliente, que executará a transação novamente com o valor atualizado. Isso se repetirá até que a transação seja aceita ou até que muitas tentativas sejam realizadas.

Gravar dados off-line

Se um cliente perder a conexão de rede, o app continuará funcionando.

Todos os clientes conectados a um banco de dados do Firebase mantêm a própria versão interna de dados ativos. A gravação deles ocorre primeiro nessa versão local. Depois, o cliente do Firebase sincroniza esses dados com os servidores remotos e com outros clientes de acordo com o modelo “melhor esforço".

Consequentemente, todas as gravações no banco de dados acionam eventos locais, antes de qualquer dado ser gravado no servidor, e o app continua responsivo, independentemente da conectividade ou da latência da rede.

Para que a conectividade seja restabelecida, seu app recebe o conjunto apropriado de eventos, e o cliente faz a sincronização com o estado atual do servidor, sem precisar de um código personalizado.

Próximas etapas