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

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

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

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

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

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

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

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

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

การเขียนข้อมูลไปยัง Firebase Realtime Database มี 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&ltstring, Object&gt ToDictionary() {
        Dictionary&ltstring, Object&gt result = new Dictionary&ltstring, Object&gt();
        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 Realtime Database คุณต้องทำดังนี้ เพิ่มข้อความต่อเนื่องได้ ทั้ง SetValueAsync() และ UpdateChildrenAsync() แสดงผล Task ที่จะช่วยให้คุณทราบได้เมื่อการดำเนินการเสร็จสมบูรณ์ หาก การโทรไม่สำเร็จด้วยเหตุผลใดก็ตาม Tasks IsFaulted จะเป็นจริงด้วย พร็อพเพอร์ตี้ Exception ที่ระบุสาเหตุของความล้มเหลว

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

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

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

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

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

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

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

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

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

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

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