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