রিসোর্স ম্যানেজার ক্লাস ডিজাইন করা


17

আমি সিদ্ধান্ত নিয়েছি যে আমি আমার শখের গেম ইঞ্জিনের জন্য একটি কেন্দ্রীয় রিসোর্স ম্যানেজার / রিসোর্সক্যাস ক্লাস লিখতে চাই, তবে ক্যাচিং স্কিম ডিজাইন করতে সমস্যা হচ্ছে।

ধারণাটি হ'ল রিসোর্স ম্যানেজারের সমস্ত গেমের সংস্থানগুলি একত্রিত করে ব্যবহৃত মোট মেমোরির জন্য একটি নরম লক্ষ্য রয়েছে। অন্যান্য শ্রেণিগুলি রিসোর্স অবজেক্ট তৈরি করবে, যা একটি লোড করা অবস্থায় থাকবে এবং সেগুলি রিসোর্স ম্যানেজারে প্রেরণ করবে। রিসোর্স ম্যানেজার তারপরে সিদ্ধান্ত নেয় যে প্রদত্ত সংস্থানগুলি কখন লোড / আনলোড করবেন, নরম সীমাটি মাথায় রেখে।

যখন অন্য শ্রেণীর দ্বারা কোনও সংস্থান প্রয়োজন হয় তখন এর জন্য রিসোর্স ম্যানেজারের কাছে একটি অনুরোধ প্রেরণ করা হয় (স্ট্রিং আইডি বা কোনও অনন্য সনাক্তকারী ব্যবহার করে)। যদি রিসোর্সটি লোড করা হয়, তবে রিসোর্সের একটি পঠনযোগ্য রেফারেন্স কলিং ফাংশনটিতে পৌঁছে দেওয়া হবে (একটি রেফারেন্সযুক্ত গণনা দুর্বল_সেপ্টারে মোড়ানো)। যদি সংস্থানটি লোড না করা হয়, তবে ম্যানেজারটি পরবর্তী সুযোগে (সাধারণত ফ্রেম আঁকার শেষে) বস্তুটি লোড হওয়ার জন্য চিহ্নিত করবে।

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

প্রথম ব্যবহারের আগে ভাল লোড করার জন্য সংস্থানগুলি চিহ্নিত করাও সম্ভব। আমি যে ক্লাসগুলি ব্যবহার করছি তার একটি স্কেচ এখানে দেওয়া হল:

typedef unsigned int ResourceId;

// Resource is an abstract data type.
class Resource
{
   Resource();
   virtual ~Resource();

   virtual bool load() = 0;
   virtual bool unload() = 0;
   virtual size_t getSize() = 0; // Used in determining how much memory is 
                                 // being used.
   bool isLoaded();
   bool isMarkedForUnloading();
   bool isMarkedForReload();
   void reference();
   void dereference();
};

// This template class works as a weak_ptr, takes as a parameter a sub-class
// of Resource. Note it only hands give a const reference to the Resource, as
// it is read only.
template <class T>
class ResourceGuard
{
   public:
     ResourceGuard(T *_resource): resource(_resource)
     {
        resource->reference();
     }

     virtual ~ResourceGuard() { resource->dereference();}
     const T* operator*() const { return (resource); }
   };

class ResourceManager
{
   // Assume constructor / destructor stuff
   public:
      // Returns true if resource loaded successfully, or was already loaded.
      bool loadResource(ResourceId uid);

      // Returns true if the resource could be reloaded,(if it is being read
      // it can't be reloaded until later).
      bool reloadResource(ResourceId uid)

      // Returns true if the resource could be unloaded,(if it is being read
      // it can't be unloaded until later)
      bool unloadResource(ResourceId uid);

      // Add a resource, with it's named identifier.
      ResourceId addResource(const char * name,Resource *resource);

      // Get the uid of a resource. Returns 0 if it doesn't exist.
      ResourceId getResourceId(const char * name);

      // This is the call most likely to be used when a level is running, 
      // load/reload/unload might get called during level transitions.
      template <class T>
      ResourceGuard<T> &getResource(ResourceId resourceId)
      {
         // Calls a private method, pretend it exits
         T *temp = dynamic_cast<T*> (_getResource(resourceId));
         assert(temp != NULL);
         return (ResourceGuard<T>(temp));
      }

      // Generally, this will automatically load/unload data, and is called
      // once per frame. It's also where the caching scheme comes into play.
      void update();

};

সমস্যাটি হ'ল, মোট ডেটা ব্যবহারকে নরম সীমাবদ্ধতার আশেপাশে / ঘোরাতে রাখতে ম্যানেজারকে কোন বিষয়গুলি আনলোড করতে হবে তা নির্ধারণের একটি স্মার্ট উপায় থাকতে হবে।

আমি কিছুটা অগ্রাধিকার ব্যবস্থা ব্যবহার করার কথা ভাবছি (যেমন অস্থায়ী অগ্রাধিকার, ঘন ঘন ব্যবহৃত অগ্রাধিকার, স্থায়ী অগ্রাধিকার), সর্বশেষ মূল্যবোধের সময় এবং সংস্থানটির আকারের সাথে মিলিয়ে কখন এটি অপসারণ করা হবে তা নির্ধারণ করতে। তবে আমি ব্যবহার করার জন্য কোনও শালীন স্কিম, বা তাদের দ্রুত পরিচালনা করার জন্য সঠিক ডেটা-স্ট্রাকচারের কথা ভাবতে পারি না।

যে কেউ এর মতো একটি সিস্টেম বাস্তবায়ন করেছে তারা কীভাবে কাজ করে তার একটি ওভারভিউ দিতে পারে? আমি কি অনুপস্থিত একটি স্পষ্ট ডিজাইন প্যাটার্ন আছে? আমি কি খুব জটিল করে তুলেছি? আদর্শভাবে আমার একটি দক্ষ, এবং সিস্টেমের অপব্যবহার করা শক্ত প্রয়োজন। কোন ধারনা?


4
সুস্পষ্ট প্রশ্নটি হল "আপনার বাস্তবায়নের জন্য নির্ধারিত বৈশিষ্ট্যগুলি কী দরকার"। আপনি যদি কোনও পিসিতে কাজ করে থাকেন তবে উদাহরণস্বরূপ মেমরির সফট ক্যাপ সেট করা অতিমাত্রায় is যদি আপনার গেমটি স্তরগুলিতে বিভক্ত হয়ে যায় এবং আপনি কী স্তরে কী কী সম্পদ ব্যবহার করতে চলেছেন তা নির্ধারণ করতে পারেন, কেবল শুরুতে সমস্ত কিছু লোড করুন এবং গেমপ্লে চলাকালীন মোটামুটি লোডিং / আনলোডিং এড়ানো উচিত।
টেট্র্যাড

উত্তর:


8

আমি নিশ্চিত নই যে এটি আপনার প্রশ্নের 100% এর সাথে সম্পর্কিত কিনা তবে কয়েকটি পরামর্শের টিপস নিম্নলিখিত:

  1. আপনার সংস্থানগুলিকে একটি হ্যান্ডেলে মোড়ানো rap আপনার সংস্থানগুলি দুটি ভাগে বিভক্ত করা উচিত: তাদের বিবরণ (সাধারণত এক্সএমএলে থাকে) এবং আসল ডেটা। ইঞ্জিনটির গেমের শুরুতে সমস্ত সংস্থান বিবরণ লোড করা উচিত এবং তাদের জন্য সমস্ত হ্যান্ডেল তৈরি করা উচিত। যখন কোনও উপাদান কোনও সংস্থার অনুরোধ করে হ্যান্ডেলটি ফিরে আসে। এইভাবে ফাংশনগুলি স্বাভাবিক হিসাবে এগিয়ে যেতে পারে (তারা এখনও আকারের জন্য অনুরোধ করতে পারে ইত্যাদি ..)। এখন যদি আপনি এখনও সংস্থানটি লোড না করেন? এমন একটি 'নাল রিসোর্স' তৈরি করুন যা এমন কোনও সংস্থান প্রতিস্থাপনের জন্য ব্যবহৃত হয় যা আঁকানোর চেষ্টা করা হয়েছে তবে এখনও লোড হয়নি।

আরও একটি গুচ্ছ আছে। আমি সম্প্রতি এই বইটি পড়েছি " গেম ইঞ্জিন ডিজাইন এবং বাস্তবায়ন " এবং এটির একটি খুব সুন্দর বিভাগ রয়েছে যেখানে এটি যায় এবং একটি সংস্থান ম্যানেজার শ্রেণির নকশা তৈরি করে।

রিসোর্সহ্যান্ডল এবং মেমরি বাজেটের কার্যকারিতা ছাড়াই এখানে বইটি সুপারিশ করেছে:

typedef enum
{
    RESOURCE_NULL = 0,
    RESOURCE_GRAPHIC = 1,
    RESOURCE_MOVIE = 2,
    RESOURCE_AUDIO = 3,
    RESOURCE_TEXT =4,
}RESOURCE_TYPE;


class Resource : public EngineObject
{
public:
    Resource() : _resourceID(0), _scope(0), _type(RESOURCE_NULL) {}
    virtual ~Resource() {}
    virtual void Load() = 0;
    virtual void Unload()= 0;

    void SetResourceID(UINT ID) { _resourceID = ID; }
    UINT GetResourceID() const { return _resourceID; }

    void SetFilename(std::string filename) { _filename = filename; }
    std::string GetFilename() const { return _filename; }

    void SetResourceType(RESOURCE_TYPE type) { _type = type; }
    RESOURCE_TYPE GetResourceType() const { return _type; }

    void SetResourceScope(UINT scope) { _scope = scope; }
    UINT GetResourceScope() const { return _scope; }

    bool IsLoaded() const { return _loaded; }
    void SetLoaded(bool value) { _loaded = value; }

protected:
    UINT _resourceID;
    UINT _scope;
    std::string _filename;
    RESOURCE_TYPE _type;
    bool _loaded;
private:
};

class ResourceManager : public Singleton<ResourceManager>, public EngineObject
{
public:
    ResourceManager() : _currentScope(0), _resourceCount(0) {};
    virtual ~ResourceManager();
    static ResourceManager& GetInstance() { return *_instance; }

    Resource * FindResourceByID(UINT ID);
    void Clear();
    bool LoadFromXMLFile(std::string filename);
    void SetCurrentScope(UINT scope);
    const UINT GetResourceCount() const { return _resourceCount; }
protected:
    UINT _currentScope;
    UINT _resourceCount; //Total number of resources unloaded and loaded
    std::map<UINT, std::list<Resource*> > _resources; //Map of form <scope, resource list>

private:
};

লক্ষ্য করুন যে সেটস্কোপ কার্যকারিতা একটি দৃশ্য-স্তরযুক্ত ইঞ্জিন ডিজাইনকে বোঝায় যেখানে স্কোপিলভেল দৃশ্যে # বোঝায়। একবার কোনও দৃশ্য প্রবেশ / প্রস্থান করার পরে, সেই সুযোগ অনুসারে সমস্ত সংস্থানগুলি লোড হয়ে যায় এবং কোনও বিশ্বব্যাপী সুযোগে লোড হয় না।


আমি সত্যিই নুল অবজেক্ট ধারণা, এবং স্কোপ রাখার ধারণা পছন্দ করি। আমি কেবল 'গেম ইঞ্জিন ডিজাইন এবং বাস্তবায়ন' এর অনুলিপিটির জন্য আমার স্কুল লাইব্রেরি শিকারের মধ্য দিয়ে এসেছি, তবে কোনও ভাগ্য নেই। বইটি কীভাবে মেমরির বাজেট পরিচালনা করবে তা বিশদে চলে যায়?
ডারসি রায়নার

এটি কয়েকটি সাধারণ মেমরি পরিচালনা প্রকল্পের বিবরণ দেয়। শেষ পর্যন্ত এমনকি একটি মৌলিকটি সাধারণ ম্যালোকের চেয়ে অনেক ভাল হওয়া উচিত যেহেতু এটি সমস্ত কিছুর জন্য সর্বোত্তম চেষ্টা করে।
শেথেরন

আমি একেবারে অনুরূপ একটি নকশা বাছাই শেষ।
ডারসি রেনার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.