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