ডেটা সেভ করা

শুরু করার আগে

Realtime Database ব্যবহার করার আগে, আপনাকে যা করতে হবে:

  • আপনার Unity প্রোজেক্ট রেজিস্টার করুন এবং Firebase ব্যবহার করার জন্য এটি কনফিগার করুন।

    • আপনার Unity প্রোজেক্টে আগে থেকেই Firebase ব্যবহার করা হলে, সেটি আগে থেকেই Firebase-এর জন্য রেজিস্টার ও কনফিগার করা আছে।

    • আপনার কোনও Unity প্রোজেক্ট না থাকলে, আপনি একটি স্যাম্পেল অ্যাপ ডাউনলোড করতে পারবেন।

  • আপনার Unity প্রোজেক্টে Firebase Unity SDK (বিশেষ করে, FirebaseDatabase.unitypackage) যোগ করুন।

মনে রাখবেন, আপনার Unity প্রোজেক্টে Firebase যোগ করার জন্য 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# অবজেক্ট ব্যবহার করলে, অবজেক্টকে র Json-এ কনভার্ট করতে এবং SetRawJsonValueAsync() কল করতে, আপনি বিল্ট-ইন JsonUtility.ToJson() ব্যবহার করতে পারবেন। যেমন, আপনার কাছে এমন একটি 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() পদ্ধতি ব্যবহার করুন। নির্দিষ্ট Firebase রেফারেন্সে নতুন চাইল্ড যোগ করা হলে, Push() পদ্ধতিটি প্রতিবার একটি অনন্য কী তৈরি করে। তালিকার প্রতিটি নতুন এলিমেন্টের জন্য এই অটোমেটিক জেনারেট করা কী ব্যবহার করে, একাধিক ক্লায়েন্ট একই সময়ে একই লোকেশনে চিল্ড্রেন যোগ করতে পারে, এতে রাইট কনফ্লিক্ট হয় না। Push()-এর মাধ্যমে তৈরি করা অনন্য কী টাইমস্ট্যাম্পের উপর ভিত্তি করে তৈরি করা হয়, তাই তালিকার আইটেমগুলি অটোমেটিক কালানুক্রমিকভাবে সাজানো হয়।

আপনি Push() পদ্ধতি দ্বারা রিটার্ন করা নতুন ডেটার রেফারেন্স ব্যবহার করে চাইল্ডের অটোমেটিক জেনারেট করা কী-এর ভ্যালু পেতে বা চাইল্ডের জন্য ডেটা সেট করতে পারেন। Push() রেফারেন্সে Key কল করলে অটোমেটিক জেনারেট হওয়া কী-এর ভ্যালু রিটার্ন করে।

নির্দিষ্ট ফিল্ড আপডেট করুন

অন্য চাইল্ড নোড ওভাররাইট না করে নোডের নির্দিষ্ট চাইল্ডে একই সাথে লিখতে, 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-এ ব্যবহারকারীর স্কোরে দ্বিতীয় এন্ট্রি তৈরি করতে 'কী' ব্যবহার করা যেতে পারে।

এইসব পাথ ব্যবহার করে, আপনি UpdateChildrenAsync()-এ একটি কল করে JSON ট্রির একাধিক লোকেশনে একসাথে আপডেট করতে পারবেন, যেমন এই উদাহরণে দুটি লোকেশনেই নতুন এন্ট্রি তৈরি করা হয়েছে। এইভাবে করা যুগপৎ আপডেটগুলি অ্যাটমিক: হয় সব আপডেট সফল হয় অথবা সব আপডেট ব্যর্থ হয়।

ডেটা মুছে দিন

ডেটা মুছে ফেলার সবচেয়ে সহজ উপায় হল, সেই ডেটার লোকেশনের রেফারেন্সে RemoveValue() কল করা।

এছাড়াও, আপনি SetValueAsync() বা UpdateChildrenAsync()-এর মতো অন্য কোনও রাইট অপারেশনের জন্য null-কে ভ্যালু হিসেবে নির্দিষ্ট করে মুছে দিতে পারেন। আপনি এই পদ্ধতি 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 ক্লায়েন্ট তখন রিমোট ডেটাবেস সার্ভার এবং অন্যান্য ক্লায়েন্টের সাথে "সর্বোচ্চ চেষ্টা"র ভিত্তিতে সেই ডেটা সিঙ্ক করে।

এর ফলে, ডেটাবেসে লেখা সমস্ত ডেটা সার্ভারে লেখার আগেই অবিলম্বে স্থানীয় ইভেন্ট ট্রিগার করে। এর অর্থ হল, নেটওয়ার্ক লেটেন্সি বা কানেক্টিভিটি যাই হোক না কেন, আপনার অ্যাপ রেসপন্সিভ থাকে।

কানেক্টিভিটি আবার চালু হয়ে গেলে, আপনার অ্যাপ উপযুক্ত সেট অফ ইভেন্ট পায় যাতে ক্লায়েন্ট বর্তমান সার্ভার স্ট্যাটাসের সাথে সিঙ্ক করে, কোনও কাস্টম কোড না লিখেই।

পরবর্তী ধাপ