ก่อนเริ่มต้น
คุณต้องดำเนินการต่อไปนี้ก่อนจึงจะใช้ 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 ดิบ เช่น
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 ดิบและเรียกใช้ SetRawJsonValueAsync()
ได้
เช่น คุณอาจมีคลาสผู้ใช้ที่มีลักษณะดังนี้
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; } }
หากต้องการสร้าง LeaderboardEntry และอัปเดตพร้อมกันเป็นฟีดคะแนนล่าสุด และรายการคะแนนของผู้ใช้เอง เกมจะใช้โค้ดดังนี้
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 => { 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 จะซิงโครไนซ์ข้อมูลดังกล่าวกับเซิร์ฟเวอร์ฐานข้อมูลระยะไกล และกับไคลเอ็นต์อื่นๆ โดยพยายามอย่างเต็มที่
ด้วยเหตุนี้ การเขียนทั้งหมดไปยังฐานข้อมูลจึงทําให้เกิดเหตุการณ์ในเครื่องทันที ก่อนที่จะมีการเขียนข้อมูลใดๆ ไปยังเซิร์ฟเวอร์ ซึ่งหมายความว่าแอปจะยังคงตอบสนองได้ไม่ว่าเครือข่ายจะมีเวลาในการตอบสนองหรือการเชื่อมต่อเป็นอย่างไร
เมื่อมีการเชื่อมต่ออีกครั้ง แอปจะได้รับชุดเหตุการณ์ที่เหมาะสมเพื่อให้ไคลเอ็นต์ซิงค์กับสถานะเซิร์ฟเวอร์ปัจจุบันโดยไม่ต้องเขียนโค้ดที่กำหนดเอง