তথ্য সংরক্ষণ

আপনি শুরু করার আগে

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

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

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

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

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

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

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

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

পদ্ধতি সাধারণ ব্যবহার
SetValueAsync() একটি সংজ্ঞায়িত পথে ডেটা লিখুন বা প্রতিস্থাপন করুন, যেমন users/<user-id>/<username>
SetRawJsonValueAsync() raw Json দিয়ে ডেটা লিখুন বা প্রতিস্থাপন করুন, যেমন users/<user-id>/<username>
Push() ডেটার তালিকায় যোগ করুন। যতবার আপনি Push() কল করেন, ফায়ারবেস একটি অনন্য কী তৈরি করে যা একটি অনন্য শনাক্তকারী হিসাবেও ব্যবহার করা যেতে পারে, যেমন 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() কল করতে পারেন। উদাহরণস্বরূপ, আপনার একটি ব্যবহারকারীর শ্রেণী থাকতে পারে যা দেখতে নিম্নরূপ:

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

একটি লিডারবোর্ড এন্ট্রি তৈরি করতে এবং একই সাথে সাম্প্রতিক স্কোর ফিড এবং ব্যবহারকারীর নিজস্ব স্কোর তালিকাতে আপডেট করতে, গেমটি এইরকম কোড ব্যবহার করে:

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 ফেরত দেয় যা আপনাকে অপারেশন সম্পূর্ণ হলে জানতে দেয়। যদি কোনো কারণে কল ব্যর্থ হয়, তাহলে ব্যর্থতা কেন ঘটেছে তা নির্দেশ করে Exception বৈশিষ্ট্যের সাথে টাস্ক IsFaulted হবে।

লেনদেন হিসাবে ডেটা সংরক্ষণ করুন

ক্রমবর্ধমান কাউন্টারগুলির মতো সমসাময়িক পরিবর্তন দ্বারা দূষিত হতে পারে এমন ডেটা নিয়ে কাজ করার সময়, আপনি একটি লেনদেন অপারেশন ব্যবহার করতে পারেন। আপনি এই অপারেশনটিকে একটি 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);
    });
}

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

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

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

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

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

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

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