Menyimpan Data

Sebelum memulai

Sebelum dapat menggunakan Realtime Database, Anda perlu:

  • Mendaftarkan project Unity Anda dan mengonfigurasikannya untuk menggunakan Firebase.

    • Jika project Unity Anda telah menggunakan Firebase, berarti project tersebut telah terdaftar dan dikonfigurasi untuk Firebase.

    • Jika belum memiliki project Unity, Anda dapat mendownload aplikasi contoh.

  • Menambahkan Firebase Unity SDK (khususnya, FirebaseDatabase.unitypackage) ke project Unity Anda.

Perlu diperhatikan bahwa menambahkan Firebase ke project Unity Anda melibatkan tugas di Firebase console dan di project Unity yang terbuka (misalnya, Anda mendownload file konfigurasi Firebase dari konsol, lalu memindahkannya ke project Unity).

Menyimpan Data

Ada lima metode untuk menulis data ke Firebase Realtime Database:

Metode Penggunaan umum
SetValueAsync() Menulis atau mengganti data ke jalur yang ditetapkan, seperti users/<user-id>/<username>.
SetRawJsonValueAsync() Menulis atau mengganti data dengan JSON mentah, seperti users/<user-id>/<username>.
Push() Menambahkan ke daftar data. Setiap kali Anda memanggil Push(), Firebase akan menghasilkan kunci unik yang juga dapat digunakan sebagai ID unik, seperti user-scores/<user-id>/<unique-score-id>.
UpdateChildrenAsync() Mengupdate beberapa kunci untuk jalur yang ditetapkan tanpa mengganti semua data.
RunTransaction() Mengupdate data kompleks yang bisa rusak karena update serentak.

Mendapatkan DatabaseReference

Untuk menulis data ke Database, Anda perlu instance 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;
  }
}

Menulis, mengupdate, atau menghapus data pada referensi

Operasi tulis dasar

Untuk operasi tulis dasar, Anda dapat menggunakan SetValueAsync() untuk menyimpan data ke referensi yang ditentukan, sehingga menggantikan data yang ada di jalur tersebut. Anda dapat menggunakan metode ini untuk meneruskan jenis yang sesuai dengan jenis JSON yang tersedia sebagai berikut:

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

Jika Anda menggunakan objek C# yang diketik, Anda dapat menggunakan JsonUtility.ToJson() bawaan untuk mengonversi objek menjadi JSON mentah dan memanggil SetRawJsonValueAsync(). Misalnya, Anda mungkin memiliki class User yang terlihat sebagai berikut:

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

    public User() {
    }

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

Anda dapat menambahkan pengguna dengan SetRawJsonValueAsync() seperti berikut:

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

Penggunaan SetValueAsync() atau SetRawJsonValueAsync() seperti ini akan menimpa data di lokasi yang ditentukan, termasuk semua node turunan. Namun, Anda masih dapat mengupdate turunan tanpa menulis ulang seluruh objek. Jika ingin mengizinkan pengguna untuk mengupdate profil mereka, Anda dapat mengupdate nama pengguna seperti berikut:

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

Menambahkan ke daftar data

Gunakan metode Push() untuk menambahkan data ke daftar dalam aplikasi multipengguna. Metode Push() menghasilkan kunci unik setiap kali turunan baru ditambahkan ke referensi Firebase tertentu. Dengan kunci yang dihasilkan secara otomatis untuk setiap elemen baru dalam daftar, beberapa klien dapat menambahkan turunan ke lokasi yang sama secara bersamaan tanpa mengalami konflik penulisan. Kunci unik yang dihasilkan oleh Push() didasarkan pada stempel waktu, sehingga item daftar otomatis diurutkan secara kronologis.

Anda dapat menggunakan referensi ke data baru yang ditampilkan oleh metode Push() untuk mendapatkan nilai kunci turunan yang dihasilkan otomatis atau menetapkan data untuk turunan. Memanggil Key pada referensi Push() akan menampilkan nilai kunci yang dihasilkan secara otomatis.

Mengupdate kolom tertentu

Untuk menulis secara simultan ke turunan tertentu sebuah node tanpa menimpa node turunan yang lain, gunakan metode UpdateChildrenAsync().

Saat memanggil UpdateChildrenAsync(), Anda dapat memperbarui nilai turunan di level yang lebih rendah dengan menentukan jalur untuk kunci. Jika data disimpan dalam beberapa lokasi agar dapat melakukan penskalaan yang lebih baik, Anda dapat mengupdate semua instance data tersebut menggunakan fan-out data. Misalnya, suatu game mungkin memiliki class LeaderboardEntry seperti ini:

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

Untuk membuat LeaderboardEntry dan sekaligus mengupdatenya ke feed skor terbaru dan daftar skor milik pengguna, game menggunakan kode seperti ini:

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

Contoh ini menggunakan Push() guna membuat entri dalam node yang berisi entri untuk semua pengguna di /scores/$key, dan sekaligus mengambil kunci dengan Key. Selanjutnya, kunci tersebut dapat digunakan untuk membuat entri kedua di skor pengguna pada /user-scores/$userid/$key.

Dengan menggunakan jalur tersebut, Anda dapat menjalankan update simultan ke beberapa lokasi di hierarki JSON dengan sekali panggilan ke UpdateChildrenAsync(), seperti yang digunakan pada contoh ini untuk membuat entri baru di kedua lokasi. Update bersamaan menjadikan proses ini berjalan menyeluruh: entah semua update berhasil atau semua update gagal.

Menghapus data

Cara termudah untuk menghapus data adalah dengan memanggil RemoveValue() pada referensi ke lokasi data tersebut.

Penghapusan juga dapat dilakukan dengan menentukan null sebagai nilai untuk operasi tulis lainnya, seperti SetValueAsync() atau UpdateChildrenAsync(). Teknik ini dapat digunakan dengan UpdateChildrenAsync() untuk menghapus beberapa turunan dengan sebuah panggilan API.

Mengetahui kapan data Anda disimpan.

Untuk mengetahui kapan data Anda disimpan ke server Firebase Realtime Database, Anda bisa menambahkan sebuah kelanjutan. SetValueAsync() dan UpdateChildrenAsync() menghasilkan Task yang memungkinkan Anda untuk mengetahui kapan operasi selesai. Jika panggilan tidak berhasil karena alasan apa pun, Tugas IsFaulted akan menghasilkan nilai benar (true) dengan properti Exception yang menunjukkan mengapa kegagalan terjadi.

Menyimpan data sebagai transaksi

Ketika bekerja dengan data yang bisa rusak karena perubahan serentak, seperti penghitung tambahan, Anda dapat menggunakan operasi transaksi. Anda memberi operasi ini Func. Update Func ini mengambil status data saat ini sebagai argumen dan menampilkan status baru yang ingin Anda tuliskan. Jika ada klien lain yang melakukan penulisan ke lokasi sebelum nilai baru Anda berhasil ditulis, fungsi update Anda akan dipanggil lagi dengan nilai baru saat ini, lalu proses tulis akan dicoba ulang.

Misalnya, dalam game Anda dapat mengizinkan pengguna untuk mengupdate papan peringkat dengan lima nilai tertinggi:

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

Penggunaan transaksi dapat mencegah kesalahan papan peringkat jika beberapa pengguna mencatat skor secara bersamaan atau jika klien memiliki data yang sudah usang. Jika transaksi ditolak, server akan menampilkan nilai saat ini ke klien yang akan menjalankan lagi transaksi tersebut dengan nilai yang diupdate. Proses ini akan berulang hingga transaksi diterima atau ada terlalu banyak percobaan yang dilakukan.

Menulis data offline

Jika koneksi jaringan klien terputus, aplikasi Anda akan tetap berfungsi dengan baik.

Setiap klien yang terhubung ke database Firebase menyimpan versi internalnya sendiri untuk setiap data aktif. Ketika ditulis, data akan dituliskan ke versi lokal ini terlebih dahulu. Selanjutnya, klien Firebase menyinkronkan data tersebut dengan server remote database, dan dengan klien lain berdasarkan "upaya terbaik".

Akibatnya, semua operasi tulis ke database akan langsung memicu peristiwa lokal, sebelum ada data yang dituliskan ke server. Ini berarti aplikasi Anda akan tetap responsif, apa pun kondisi konektivitas atau latensi jaringannya.

Setelah konektivitas pulih, aplikasi Anda akan menerima kumpulan peristiwa yang tepat, sehingga klien sinkron dengan kondisi server saat ini, tanpa perlu menulis kode khusus apa pun.

Langkah Berikutnya