قبل البدء
قبل أن تتمكّن من استخدام Realtime Database، عليك تنفيذ ما يلي:
سجِّل مشروع Unity الخاص بك وأعدَّه لاستخدام Firebase.
إذا كان مشروع Unity يستخدم Firebase، يعني ذلك أنّه سبق تسجيله وإعداده لاستخدام Firebase.
إذا لم يكن لديك مشروع على Unity، يمكنك تنزيل نموذج تطبيق.
أضِف حزمة تطوير البرامج (SDK) الخاصة بـ Firebase Unity (على وجه التحديد،
FirebaseDatabase.unitypackage) إلى مشروعك على Unity.
يُرجى العِلم أنّ إضافة Firebase إلى مشروع Unity تتضمّن مهامًا في كلّ من وحدة تحكّم Firebase ومشروع Unity المفتوح (على سبيل المثال، يمكنك تنزيل ملفات إعدادات Firebase من وحدة التحكّم، ثم نقلها إلى مشروع Unity).
حفظ البيانات
هناك خمس طرق لكتابة البيانات في Firebase Realtime Database:
| الطريقة | طرق الاستخدام الشائعة |
|---|---|
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 المتاحة على النحو التالي:
stringlongdoubleboolDictionary<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. ويمكن بعد ذلك استخدام المفتاح لإنشاء إدخال ثانٍ في نتائج المستخدم في /user-scores/$userid/$key.
باستخدام هذه المسارات، يمكنك إجراء تعديلات متزامنة على مواقع متعددة في شجرة JSON من خلال استدعاء واحد لـ UpdateChildrenAsync()، مثل كيفية إنشاء هذا المثال للإدخال الجديد في كلا الموقعين. التعديلات المتزامنة التي يتم إجراؤها بهذه الطريقة تكون ذرية: إما أن تنجح جميع التعديلات أو تفشل جميع التعديلات.
حذف البيانات
أبسط طريقة لحذف البيانات هي استدعاء RemoveValue() على مرجع إلى
موقع تلك البيانات.
يمكنك أيضًا حذف البيانات من خلال تحديد null كقيمة لعملية كتابة أخرى، مثل SetValueAsync() أو UpdateChildrenAsync(). يمكنك استخدام هذه الطريقة مع UpdateChildrenAsync() لحذف عدة عناصر فرعية في طلب واحد من واجهة برمجة التطبيقات.
معرفة وقت تنفيذ بياناتك
لمعرفة متى يتم إرسال بياناتك إلى خادم Firebase Realtime Database، يمكنك إضافة استمرارية. تُرجع كل من 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 هذه البيانات مع خوادم قواعد البيانات البعيدة ومع العملاء الآخرين على أساس "بذل قصارى الجهد".
نتيجةً لذلك، تؤدي جميع عمليات الكتابة في قاعدة البيانات إلى تشغيل الأحداث المحلية على الفور، قبل كتابة أي بيانات على الخادم. هذا يعني أن تطبيقك يظل مستجيبًا بغض النظر عن زمن انتقال الشبكة أو الاتصال.
بعد إعادة إمكانية الاتصال، يتلقّى تطبيقك المجموعة المناسبة من الأحداث لكي تتم مزامنة العميل مع حالة الخادم الحالية، بدون الحاجة إلى كتابة أي رمز مخصّص.