ذخیره داده ها

قبل از شروع

قبل از اینکه بتوانید از Realtime Database استفاده کنید، باید:

  • پروژه Unity خود را ثبت کرده و آن را برای استفاده از Firebase پیکربندی کنید.

    • اگر پروژه Unity شما قبلاً از Firebase استفاده می‌کند، پس از قبل برای Firebase ثبت و پیکربندی شده است.

    • اگر پروژه یونیتی ندارید، می توانید یک برنامه نمونه دانلود کنید.

  • 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 نیاز دارید:

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() برای حذف چندین فرزند در یک تماس API استفاده کنید.

بدانید چه زمانی داده های شما متعهد است.

برای اینکه بدانید چه زمانی داده های شما به سرور 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 آن داده ها را با سرورهای پایگاه داده راه دور و با سایر کلاینت ها بر اساس "بهترین تلاش" همگام سازی می کند.

در نتیجه، همه نوشته‌ها در پایگاه داده، بلافاصله رویدادهای محلی را راه‌اندازی می‌کنند، قبل از اینکه داده‌ای روی سرور نوشته شود. این بدان معناست که برنامه شما بدون توجه به تأخیر شبکه یا اتصال، پاسخگو باقی می ماند.

پس از برقراری مجدد اتصال، برنامه شما مجموعه مناسبی از رویدادها را دریافت می کند تا کلاینت بدون نیاز به نوشتن کد سفارشی با وضعیت سرور فعلی همگام شود.

مراحل بعدی