ก่อนจะเริ่ม
ก่อนที่คุณจะสามารถใช้ ฐานข้อมูลเรียลไทม์ คุณต้อง:
ลงทะเบียนโครงการ Unity ของคุณและกำหนดค่าให้ใช้ Firebase
หากโปรเจ็กต์ Unity ของคุณใช้ Firebase อยู่แล้ว แสดงว่าได้ลงทะเบียนและกำหนดค่าสำหรับ Firebase แล้ว
หากคุณไม่มีโปรเจ็กต์ Unity คุณสามารถดาวน์โหลด แอปตัวอย่าง ได้
เพิ่ม Firebase Unity SDK (โดยเฉพาะ
FirebaseDatabase.unitypackage
) ให้กับโปรเจ็กต์ Unity ของคุณ
โปรดทราบว่าการเพิ่ม Firebase ให้กับโปรเจ็กต์ Unity ของคุณเกี่ยวข้องกับงานทั้งใน คอนโซล Firebase และในโครงการ Unity แบบเปิดของคุณ (เช่น คุณดาวน์โหลดไฟล์กำหนดค่า Firebase จากคอนโซล จากนั้นย้ายไปยังโปรเจ็กต์ Unity ของคุณ)
บันทึกข้อมูล
มีห้าวิธีในการเขียนข้อมูลไปยังฐานข้อมูลเรียลไทม์ของ Firebase:
วิธี | การใช้งานทั่วไป |
---|---|
SetValueAsync() | เขียนหรือแทนที่ข้อมูลไปยังเส้นทางที่กำหนด เช่น users/<user-id>/<username> |
SetRawJsonValueAsync() | เขียนหรือแทนที่ข้อมูลด้วย Raw Json เช่น users/<user-id>/<username> |
Push() | เพิ่มในรายการข้อมูล ทุกครั้งที่คุณเรียกใช้ Push() Firebase จะสร้างคีย์เฉพาะที่สามารถใช้เป็นตัวระบุที่ไม่ซ้ำกันได้ เช่น user-scores/<user-id>/<unique-score-id> |
UpdateChildrenAsync() | อัปเดตคีย์บางคีย์สำหรับพาธที่กำหนดโดยไม่ต้องแทนที่ข้อมูลทั้งหมด |
RunTransaction() | อัปเดตข้อมูลที่ซับซ้อนที่อาจเสียหายจากการอัพเดทพร้อมกัน |
รับฐานข้อมูลอ้างอิง
ในการเขียนข้อมูลไปยังฐานข้อมูล คุณต้องมีอินสแตนซ์ของ 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()
คุณสามารถอัปเดตค่าลูกระดับล่างได้โดยการระบุเส้นทางสำหรับคีย์ หากข้อมูลถูกจัดเก็บไว้ในหลายตำแหน่งเพื่อให้ปรับขนาดได้ดีขึ้น คุณสามารถอัปเดตอินสแตนซ์ทั้งหมดของข้อมูลนั้นได้โดยใช้ data fan-out ตัวอย่างเช่น เกมอาจมีคลาส 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
คีย์สามารถใช้เพื่อสร้างรายการที่สองในคะแนนของผู้ใช้ที่ /user-scores/$userid/$key
เมื่อใช้พาธเหล่านี้ คุณสามารถทำการอัปเดตหลายตำแหน่งพร้อมกันในแผนผัง JSON ได้ด้วยการเรียก UpdateChildrenAsync()
เพียงครั้งเดียว เช่น ตัวอย่างนี้สร้างรายการใหม่ในทั้งสองตำแหน่ง การอัปเดตพร้อมกันในลักษณะนี้เป็นแบบปรมาณู: การอัปเดตทั้งหมดสำเร็จหรือการอัปเดตทั้งหมดล้มเหลว
ลบข้อมูล
วิธีที่ง่ายที่สุดในการลบข้อมูลคือการเรียก RemoveValue()
โดยอ้างอิงถึงตำแหน่งของข้อมูลนั้น
คุณยังสามารถลบโดยระบุ null
เป็นค่าสำหรับการดำเนินการเขียนอื่น เช่น SetValueAsync()
หรือ UpdateChildrenAsync()
คุณสามารถใช้เทคนิคนี้กับ UpdateChildrenAsync()
เพื่อลบชายน์หลายคนในการเรียก API ครั้งเดียว
รู้ว่าข้อมูลของคุณมีความมุ่งมั่นเมื่อใด
หากต้องการทราบว่าข้อมูลของคุณถูกส่งไปยังเซิร์ฟเวอร์ฐานข้อมูลเรียลไทม์ของ Firebase เมื่อใด คุณสามารถเพิ่มความต่อเนื่องได้ ทั้ง SetValueAsync()
และ UpdateChildrenAsync()
ส่งคืน Task
ที่ให้คุณทราบเมื่อการดำเนินการเสร็จสิ้น หากการโทรไม่สำเร็จด้วยเหตุผลใดก็ตาม Tasks IsFaulted
จะเป็นจริงด้วยคุณสมบัติ Exception
ซึ่งบ่งชี้ว่าเหตุใดจึงเกิดความล้มเหลว
บันทึกข้อมูลเป็นธุรกรรม
เมื่อทำงานกับข้อมูลที่อาจเสียหายจากการแก้ไขพร้อมกัน เช่น ตัวนับที่เพิ่มขึ้น คุณสามารถใช้ การดำเนินการธุรกรรม คุณให้การดำเนินการนี้เป็น Func
การอัปเดต Func
นี้ใช้สถานะปัจจุบันของข้อมูลเป็นอาร์กิวเมนต์ และส่งกลับสถานะใหม่ที่คุณต้องการจะเขียน ถ้าไคลเอนต์อื่นเขียนไปยังตำแหน่งก่อนที่ค่าใหม่ของคุณจะเขียนได้สำเร็จ ฟังก์ชันอัพเดตของคุณจะถูกเรียกอีกครั้งด้วยค่าปัจจุบันใหม่และลองเขียนใหม่
ตัวอย่างเช่น ในเกม คุณสามารถอนุญาตให้ผู้ใช้อัปเดตกระดานผู้นำด้วยคะแนนสูงสุดห้าคะแนน:
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 จะซิงโครไนซ์ข้อมูลนั้นกับเซิร์ฟเวอร์ฐานข้อมูลระยะไกลและกับไคลเอนต์อื่น ๆ ด้วย "ความพยายามอย่างดีที่สุด"
ด้วยเหตุนี้ การเขียนทั้งหมดไปยังฐานข้อมูลจะทริกเกอร์เหตุการณ์ในเครื่องทันที ก่อนที่ข้อมูลใดๆ จะถูกเขียนไปยังเซิร์ฟเวอร์ ซึ่งหมายความว่าแอปของคุณยังคงตอบสนองโดยไม่คำนึงถึงเวลาแฝงของเครือข่ายหรือการเชื่อมต่อ
เมื่อการเชื่อมต่อถูกสร้างขึ้นใหม่ แอปของคุณจะได้รับชุดเหตุการณ์ที่เหมาะสม เพื่อให้ไคลเอ็นต์ซิงค์กับสถานะเซิร์ฟเวอร์ปัจจุบัน โดยไม่ต้องเขียนโค้ดที่กำหนดเองใดๆ