บันทึกข้อมูล

ก่อนเริ่มต้น

ก่อนที่จะใช้งานได้ Realtime Database คุณต้องทำดังนี้

  • ลงทะเบียนโปรเจ็กต์ Unity และกำหนดค่าให้ใช้ Firebase

    • หากโปรเจ็กต์ Unity ของคุณใช้ Firebase อยู่แล้ว ก็หมายความว่า ลงทะเบียนและกำหนดค่าสำหรับ Firebase แล้ว

    • หากไม่มีโปรเจ็กต์ Unity คุณสามารถดาวน์โหลด ตัวอย่างแอป

  • เพิ่ม Firebase Unity SDK (โดยเฉพาะ FirebaseDatabase.unitypackage) ลงใน โปรเจ็กต์ Unity

โปรดทราบว่าการเพิ่ม Firebase ลงในโปรเจ็กต์ Unity จะเกี่ยวข้องกับงานทั้งใน คอนโซล Firebase และในโปรเจ็กต์ Unity ที่เปิดอยู่ (เช่น คุณดาวน์โหลดไฟล์การกำหนดค่า Firebase จากคอนโซล แล้วย้าย ลงในโปรเจ็กต์ Unity)

กำลังบันทึกข้อมูล

การเขียนข้อมูลไปยังฐานข้อมูลเรียลไทม์ของ Firebase มี 5 วิธีดังนี้

วิธีการ การใช้งานทั่วไป
SetValueAsync() เขียนหรือแทนที่ข้อมูลในเส้นทางที่กำหนด เช่น users/<user-id>/<username>.
SetRawJsonValueAsync() เขียนหรือแทนที่ข้อมูลด้วย Json แบบ Raw เช่น users/<user-id>/<username>.
Push() เพิ่มลงในรายการข้อมูล ทุกครั้งที่คุณโทร Push() โดย Firebase จะสร้างคีย์ที่ไม่ซ้ำกันซึ่งใช้ได้ด้วยเช่นกัน เป็นตัวระบุที่ไม่ซ้ำกัน เช่น user-scores/<user-id>/<unique-score-id>.
UpdateChildrenAsync() อัปเดตคีย์บางรายการสำหรับเส้นทางที่กำหนดโดยไม่ต้องแทนที่ ข้อมูลดังกล่าว
RunTransaction() อัปเดตข้อมูลที่ซับซ้อนที่อาจเสียหายจากการอัปเดตพร้อมกัน

รับ DatabaseReference

ในการเขียนข้อมูลไปยังฐานข้อมูล คุณต้องมีอินสแตนซ์ของ 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;
  }
}

เขียน อัปเดต หรือลบข้อมูลที่ข้อมูลอ้างอิง

การดำเนินการเขียนพื้นฐาน

สำหรับการดำเนินการเขียนพื้นฐาน คุณสามารถใช้ SetValueAsync() เพื่อบันทึกข้อมูลไปยัง ข้อมูลอ้างอิงที่ระบุ โดยแทนที่ข้อมูลที่มีอยู่ในเส้นทางนั้น คุณใช้ ในการส่งประเภทที่สอดคล้องกับประเภท JSON ที่มีอยู่ดังนี้

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

หากใช้ออบเจ็กต์ C# ที่พิมพ์ไว้ คุณจะใช้ JsonUtility.ToJson() ในตัวได้ เพื่อแปลงวัตถุเป็น Json แบบ Raw และเรียกใช้ SetRawJsonValueAsync() เช่น คุณอาจมีคลาส User ที่มีลักษณะดังนี้

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

    public User() {
    }

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

คุณเพิ่มผู้ใช้ที่มี SetRawJsonValueAsync() ได้โดยทำดังนี้

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

การใช้ SetValueAsync() หรือ SetRawJsonValueAsync() ในลักษณะนี้จะเขียนทับข้อมูล ในตำแหน่งที่ระบุ รวมถึงโหนดย่อย อย่างไรก็ตาม คุณยังสามารถ อัปเดตรายการย่อยโดยไม่ต้องเขียนออบเจ็กต์ทั้งหมดใหม่ หากต้องการอนุญาตผู้ใช้ เพื่ออัปเดตโปรไฟล์ของพวกเขา คุณสามารถอัปเดตชื่อผู้ใช้ได้ดังนี้:

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

ต่อท้ายรายการข้อมูล

ใช้เมธอด Push() เพื่อต่อท้ายรายการในแอปพลิเคชันที่มีผู้ใช้หลายคน เมธอด Push() จะสร้างคีย์ที่ไม่ซ้ำกันทุกครั้งที่มีการเรียก ลงในการอ้างอิง Firebase ที่ระบุ ด้วยการใช้สิ่งเหล่านี้ คีย์ที่สร้างขึ้นโดยอัตโนมัติสำหรับองค์ประกอบใหม่แต่ละรายการในรายการ โดยไคลเอ็นต์หลายราย เพิ่มเด็กไปยังตำแหน่งที่ตั้งเดียวกันพร้อมกันโดยไม่มีความขัดแย้งในการเขียน คีย์ที่ไม่ซ้ำกันที่ Push() สร้างขึ้นจะอิงตามการประทับเวลา ดังนั้นรายการจึง จะเรียงตามลำดับเวลาโดยอัตโนมัติ

คุณสามารถใช้การอ้างอิงข้อมูลใหม่ที่แสดงโดยเมธอด Push() เพื่อเรียก ค่าของคีย์ที่สร้างขึ้นโดยอัตโนมัติของบุตรหลานหรือตั้งค่าข้อมูลสำหรับบุตรหลาน การโทร Key ในข้อมูลอ้างอิง Push() แสดงผลค่าของแอตทริบิวต์ ที่สร้างโดยอัตโนมัติ

อัปเดตช่องข้อมูลที่เฉพาะเจาะจง

เพื่อเขียนไปยังโหนดย่อยที่ต้องการพร้อมกันโดยไม่เขียนทับโหนดอื่น โหนดย่อย ให้ใช้เมธอด UpdateChildrenAsync()

เมื่อโทรหา UpdateChildrenAsync() คุณจะอัปเดตค่าย่อยระดับล่างได้โดย โดยระบุเส้นทางของคีย์นี้ หากมีการจัดเก็บข้อมูลในหลายตำแหน่งเพื่อปรับขนาด คุณจะสามารถอัปเดตอินสแตนซ์ทั้งหมดของข้อมูลนั้นได้โดยใช้ การขยายข้อมูล ตัวอย่างเช่น เกมอาจมีคลาส LeaderboardEntry ในลักษณะนี้

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

เพื่อสร้างลีดเดอร์บอร์ดรายการและอัปเดตให้เป็นคะแนนล่าสุดไปพร้อมๆ กัน และรายการคะแนนของผู้ใช้เอง เกมจะใช้โค้ดดังนี้

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

ตัวอย่างนี้ใช้ Push() เพื่อสร้างรายการในโหนดที่มีรายการสำหรับ ผู้ใช้ทั้งหมดที่ /scores/$key และดึงคีย์ไปพร้อมๆ กันด้วย Key จากนั้นสามารถใช้คีย์เพื่อสร้างรายการที่ 2 ในส่วน คะแนนในนาทีที่ /user-scores/$userid/$key

การใช้เส้นทางเหล่านี้จะทำให้คุณสามารถอัปเดตสถานที่หลายแห่งพร้อมกันใน โครงสร้าง JSON ที่มีการเรียกไปยัง UpdateChildrenAsync() ครั้งเดียว เช่น สร้างรายการใหม่ในทั้ง 2 ตำแหน่ง การอัปเดตในเวลาเดียวกันทำให้รายการนี้ ต่างกันตรงที่ว่าการอัปเดตทั้งหมดสำเร็จหรือล้มเหลว

ลบข้อมูล

วิธีที่ง่ายที่สุดในการลบข้อมูลคือการเรียกใช้ RemoveValue() ตามการอ้างอิง ตำแหน่งของข้อมูลนั้น

ก็ลบได้ด้วยการระบุ null เป็นค่าสำหรับการเขียนอื่น เช่น SetValueAsync() หรือ UpdateChildrenAsync() คุณใช้ เทคนิคที่มี UpdateChildrenAsync() ในการลบรายการย่อยหลายรายการใน API เดียว การโทร

รับข้อมูลเมื่อมีการคอมมิตข้อมูลของคุณ

หากต้องการทราบว่าข้อมูลของคุณถูกคอมมิตไปยังเซิร์ฟเวอร์ฐานข้อมูลเรียลไทม์ของ Firebase เมื่อใด คุณจะต้อง เพิ่มข้อความต่อเนื่องได้ ทั้ง SetValueAsync() และ UpdateChildrenAsync() แสดงผล Task ที่จะช่วยให้คุณทราบได้เมื่อการดำเนินการเสร็จสมบูรณ์ หาก การโทรไม่สำเร็จด้วยเหตุผลใดก็ตาม Tasks IsFaulted จะเป็นจริงด้วย พร็อพเพอร์ตี้ Exception ที่ระบุสาเหตุของความล้มเหลว

บันทึกข้อมูลเป็นธุรกรรม

เมื่อทำงานกับข้อมูลที่อาจเสียหายจากการเชื่อมต่อพร้อมกัน เช่น ตัวนับที่เพิ่มขึ้น คุณสามารถใช้ การดำเนินการธุรกรรม คุณกำหนดให้การดำเนินการนี้เป็น Func การอัปเดต Func นี้จะเปลี่ยนสถานะปัจจุบัน ของข้อมูลเป็นอาร์กิวเมนต์ และส่งคืนสถานะใหม่ที่ต้องการ เขียน หากไคลเอ็นต์อื่นเขียนไปยังตำแหน่งนั้นก่อนค่าใหม่ของคุณคือ เขียนสำเร็จแล้ว ฟังก์ชันอัปเดตของคุณจะถูกเรียกอีกครั้งด้วยฟังก์ชัน และพยายามเขียนอีกครั้ง

เช่น ในเกมที่คุณอนุญาตให้ผู้ใช้อัปเดตลีดเดอร์บอร์ด คะแนนสูงสุด 5 อันดับ ได้แก่

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

การใช้ธุรกรรมจะป้องกันไม่ให้ลีดเดอร์บอร์ดไม่ถูกต้องหากมีหลายรายการ ผู้ใช้บันทึกคะแนนในเวลาเดียวกันหรือไคลเอ็นต์มีข้อมูลเก่า หาก ปฏิเสธธุรกรรม เซิร์ฟเวอร์จะส่งคืนมูลค่าปัจจุบันไปยังไคลเอ็นต์ ซึ่งจะเรียกใช้ธุรกรรมอีกครั้งด้วยมูลค่าที่อัปเดต ซึ่งจะเกิดซ้ำจนถึง ยอมรับธุรกรรมหรือพยายามดำเนินการหลายครั้งเกินไป

เขียนข้อมูลแบบออฟไลน์

หากลูกค้าสูญเสียการเชื่อมต่อเครือข่าย แอปจะยังคงทำงานต่อไป อย่างถูกต้อง

ลูกค้าทุกรายที่เชื่อมต่อกับฐานข้อมูล Firebase จะมีเวอร์ชันภายในของตนเอง ของข้อมูลที่ใช้งานอยู่ เมื่อเขียนข้อมูล ระบบจะเขียนลงในเวอร์ชันนี้ในเครื่อง ก่อน จากนั้นไคลเอ็นต์ Firebase จะซิงค์ข้อมูลนั้นกับฐานข้อมูลระยะไกล เซิร์ฟเวอร์และไคลเอ็นต์อื่นๆ อย่าง "สุดความสามารถ" พื้นฐาน

ด้วยเหตุนี้ การเขียนทั้งหมดไปยังฐานข้อมูลจะทริกเกอร์เหตุการณ์ในระบบทันที ข้อมูลใดก็ตามที่เขียนไปยังเซิร์ฟเวอร์ ซึ่งหมายความว่าแอปของคุณจะยัง ตอบสนองตามอุปกรณ์โดยไม่คำนึงถึงเวลาในการตอบสนองหรือการเชื่อมต่อของเครือข่าย

เมื่อเชื่อมต่ออินเทอร์เน็ตอีกครั้งแล้ว แอปจะได้รับชุด เหตุการณ์เพื่อให้ไคลเอ็นต์ซิงค์กับสถานะเซิร์ฟเวอร์ปัจจุบันโดยไม่ต้อง เขียนโค้ดที่กำหนดเอง

ขั้นตอนถัดไป