তথ্য সংরক্ষণ

শুরু করার আগে

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

  • আপনার ইউনিটি প্রকল্পটি নিবন্ধন করুন এবং এটিকে Firebase ব্যবহারের জন্য কনফিগার করুন।

    • যদি আপনার ইউনিটি প্রজেক্ট ইতিমধ্যেই Firebase ব্যবহার করে, তাহলে এটি ইতিমধ্যেই Firebase-এর জন্য নিবন্ধিত এবং কনফিগার করা আছে।

    • যদি আপনার কোন ইউনিটি প্রজেক্ট না থাকে, তাহলে আপনি একটি নমুনা অ্যাপ ডাউনলোড করতে পারেন।

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

মনে রাখবেন যে আপনার ইউনিটি প্রজেক্টে ফায়ারবেস যোগ করার ক্ষেত্রে Firebase কনসোল এবং আপনার ওপেন ইউনিটি প্রজেক্ট উভয় ক্ষেত্রেই কাজ জড়িত (উদাহরণস্বরূপ, আপনি কনসোল থেকে ফায়ারবেস কনফিগারেশন ফাইল ডাউনলোড করেন, তারপর সেগুলিকে আপনার ইউনিটি প্রজেক্টে স্থানান্তর করেন)।

ডেটা সংরক্ষণ করা হচ্ছে

Firebase Realtime Database ডেটা লেখার জন্য পাঁচটি পদ্ধতি রয়েছে:

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

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

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

অন্য চাইল্ড নোডগুলিকে ওভাররাইট না করে একটি নোডের নির্দিষ্ট চাইল্ড্রেনগুলিতে একই সাথে লেখার জন্য, 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() কল করা।

আপনি 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);
    });
}

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

অফলাইনে ডেটা লিখুন

যদি কোনও ক্লায়েন্ট তার নেটওয়ার্ক সংযোগ হারিয়ে ফেলে, তাহলে আপনার অ্যাপটি সঠিকভাবে কাজ করতে থাকবে।

ফায়ারবেস ডাটাবেসের সাথে সংযুক্ত প্রতিটি ক্লায়েন্ট যেকোনো সক্রিয় ডেটার নিজস্ব অভ্যন্তরীণ সংস্করণ বজায় রাখে। যখন ডেটা লেখা হয়, তখন প্রথমে এটি এই স্থানীয় সংস্করণে লেখা হয়। তারপর ফায়ারবেস ক্লায়েন্ট সেই ডেটাকে "সর্বোত্তম প্রচেষ্টা" ভিত্তিতে দূরবর্তী ডাটাবেস সার্ভার এবং অন্যান্য ক্লায়েন্টদের সাথে সিঙ্ক্রোনাইজ করে।

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

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

পরবর্তী পদক্ষেপ