আমি কীভাবে উপাদান থেকে টু-অবজেক্ট যোগাযোগকে নিরাপদে এবং ক্যাশে-বান্ধব উপাদান স্টোরেজ সহ সমর্থন করতে পারি?


9

আমি এমন একটি গেম তৈরি করছি যা কম্পোনেন্ট-ভিত্তিক গেম অবজেক্ট ব্যবহার করে এবং প্রতিটি উপাদান তার গেম অবজেক্টের সাথে যোগাযোগের জন্য একটি উপায় কার্যকর করতে আমার বেশ কষ্ট হচ্ছে। একবারে সবকিছু ব্যাখ্যা করার পরিবর্তে, আমি প্রাসঙ্গিক নমুনা কোডের প্রতিটি অংশ ব্যাখ্যা করব:

class GameObjectManager {
    public:
        //Updates all the game objects
        void update(Time dt);

        //Sends a message to all game objects
        void sendMessage(Message m);

    private:
        //Vector of all the game objects
        std::vector<GameObject> gameObjects;

        //vectors of the different types of components
        std::vector<InputComponent> input;
        std::vector<PhysicsComponent> ai;
        ...
        std::vector<RenderComponent> render;
}

GameObjectManagerসব খেলা বস্তু এবং তাদের উপাদান ঝুলিতে। এটি গেমের বিষয়গুলি আপডেট করার জন্যও দায়ী। এটি নির্দিষ্ট ক্রমে উপাদান ভেক্টরগুলি আপডেট করে এটি করে। আমি অ্যারেগুলির পরিবর্তে ভেক্টর ব্যবহার করি যাতে একবারে উপস্থিত গেম অবজেক্টগুলির সংখ্যার কার্যত কোনও সীমা থাকে না।

class GameObject {
    public:
        //Sends a message to the components in this game object
        void sendMessage(Message m);

    private:
        //id to keep track of components in the manager
        const int id;

        //Pointers to components in the game object manager
        std::vector<Component*> components;
}

GameObjectবর্গ কি জানেন তার উপাদান এবং তাদের বার্তা পাঠাতে পারেন।

class Component {
    public:
        //Receives messages and acts accordingly
        virtual void handleMessage(Message m) = 0;

        virtual void update(Time dt) = 0;

    protected:
        //Calls GameObject's sendMessage
        void sendMessageToObject(Message m);

        //Calls GameObjectManager's sendMessage
        void sendMessageToWorld(Message m);
}

Componentবর্গ বিশুদ্ধ ভার্চুয়াল তাই উপাদান বিভিন্ন ধরনের ক্লাস কিভাবে বার্তা ও আপডেট হ্যান্ডেল করতে বাস্তবায়ন পারে। এটি বার্তা প্রেরণ করতেও সক্ষম।

এখন সমস্যা উপর দেখা দেয় দুটো কারণে কিভাবে উপাদান কল করতে পারেন sendMessageইন ফাংশান GameObjectএবং GameObjectManager। আমি দুটি সম্ভাব্য সমাধান নিয়ে এসেছি:

  1. এর Componentএকটি পয়েন্টার দিন GameObject

তবে, যেহেতু গেমের অবজেক্টগুলি ভেক্টরে রয়েছে তাই পয়েন্টারগুলি দ্রুত অবৈধ হয়ে যেতে পারে (একই সাথে ভেক্টরটি সম্পর্কেও বলা যেতে পারে GameObject, তবে আশা করা যায় যে এই সমস্যার সমাধানটিও এটি সমাধান করতে পারে)। আমি গেমের জিনিসগুলিকে একটি অ্যারেতে রাখতে পারি, তবে তারপরে আমাকে আকারের জন্য একটি স্বেচ্ছাসেবী সংখ্যায় পাস করতে হবে, যা সহজেই অকারণে উচ্চ এবং বর্জ্য স্মৃতি হতে পারে।

  1. Componentএকটি পয়েন্টার দিন GameObjectManager

তবে আমি চাই না যে উপাদানগুলি পরিচালকের আপডেট ফাংশনটিতে কল করতে সক্ষম হোক। আমি এই প্রকল্পে কাজ করা একমাত্র ব্যক্তি, তবে আমি সম্ভাব্য বিপজ্জনক কোড লেখার অভ্যাস পেতে চাই না।

আমার কোডটি নিরাপদ এবং ক্যাশে বন্ধুত্বপূর্ণ রাখার সময় আমি কীভাবে এই সমস্যার সমাধান করতে পারি?

উত্তর:


6

আপনার যোগাযোগের মডেলটি দুর্দান্ত বলে মনে হচ্ছে এবং কেবলমাত্র আপনি যদি সেই পয়েন্টারগুলি নিরাপদে সংরক্ষণ করতে পারেন তবে বিকল্পটি ঠিকঠাক কাজ করবে। উপাদান স্টোরেজের জন্য একটি আলাদা ডেটা কাঠামো বাছাই করে আপনি এই সমস্যাটি সমাধান করতে পারেন।

std::vector<T>ছিল প্রথম যুক্তিসঙ্গত পছন্দ। তবে ধারকটির পুনরাবৃত্তকারী অবৈধ আচরণ একটি সমস্যা। আপনি যা চান তা হ'ল একটি ডেটা স্ট্রাকচার যা দ্রুতগতিতে পুনরাবৃত্ত হওয়ার জন্য ক্যাশে-সুসংহত এবং আইটেমগুলি সন্নিবেশ করানো বা সরিয়ে দেওয়ার সময় এটি পুনরুক্তি স্থিরতাও সংরক্ষণ করে।

আপনি যেমন একটি ডেটা কাঠামো তৈরি করতে পারেন। এটি পৃষ্ঠাগুলির একটি লিঙ্কযুক্ত তালিকা নিয়ে গঠিত । প্রতিটি পৃষ্ঠার একটি স্থির ক্ষমতা রয়েছে এবং এর সমস্ত আইটেমকে একটি অ্যারেতে ধারণ করে। সেই অ্যারেতে থাকা কতগুলি আইটেম সক্রিয় রয়েছে তা নির্দেশ করতে একটি গণনা ব্যবহৃত হয়। একটি পৃষ্ঠা একটি বিনামূল্যে তালিকা (সাফ এন্ট্রির পুনঃব্যবহারের অনুমতি) এবং একটি Skip তালিকা (আপনি ছেড়ে যাওয়ার অনুমতি আছে উপর সাফ এন্ট্রি যখন iterating।

অন্য কথায়, ধারণার মতো কিছু:

struct Page {
   int count;
   int capacity;           // Optional if every page is a fixed size.
   T * m_storage;
   bool * m_skip;          // Skip list; can be bit-compressed.
   std::stack<int> m_free; // Can be replaced with a specialized stack.

   Page * next;
   Page * prior;           // Optional, allows reverse iteration
};

আমি অকল্পনীয়ভাবে এই ডেটা স্ট্রাকচারকে একটি বই বলি (কারণ এটি পৃষ্ঠাগুলির সংগ্রহ যা আপনি পুনরাবৃত্তি করেন), তবে কাঠামোটির বিভিন্ন নাম রয়েছে।

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

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

এটি নিখুঁত নয়; ব্যবহারের প্যাটার্নের সাহায্যে ক্যাশে সুসংহততা নষ্ট করা সম্ভব যা কার্যকরভাবে ধারকটিতে র্যান্ডম দাগগুলি থেকে কার্যকরভাবে মুছে ফেলা এবং তারপরে সন্নিবেশকারীদের ব্যাকফিল আইটেমগুলি উপস্থিত হওয়ার আগে সেই ধারকটির উপরে পুনরাবৃত্তি করা জড়িত। আপনি যদি সেই পরিস্থিতিতে প্রায়শই থাকেন তবে আপনি একবারে মেমরির সম্ভাব্য-বৃহত অঞ্চলগুলি এড়িয়ে যাবেন। তবে অনুশীলনে আমি মনে করি যে এই ধারকটি আপনার দৃশ্যের জন্য যুক্তিসঙ্গত পছন্দ।

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


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

5

'ক্যাশে ফ্রেন্ডলি' হওয়া বড় গেমগুলির একটি ব্যস্ততা । এটি আমার কাছে অকালে অপ্টিমাইজেশন বলে মনে হচ্ছে।


'ক্যাশে ফ্রেন্ডলি' না হয়ে এটি সমাধানের একটি উপায় হ'ল স্ট্যাকের পরিবর্তে গাদাতে আপনার অবজেক্ট তৈরি করা: আপনার বস্তুর জন্য ব্যবহার newএবং (স্মার্ট) পয়েন্টার। এইভাবে, আপনি আপনার অবজেক্টগুলিকে রেফারেন্স করতে সক্ষম হবেন এবং তাদের রেফারেন্স বাতিল করা হবে না।

আরও ক্যাশে বান্ধব সমাধানের জন্য আপনি নিজেরাই অবজেক্টগুলির ডি / বরাদ্দ পরিচালনা করতে পারবেন এবং এই বিষয়গুলিতে হ্যান্ডলগুলি ব্যবহার করতে পারেন।

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

আপনার উপাদানটি যেমন প্রয়োজন, আপনি মেমম্যানকে এই বস্তুটি অ্যাক্সেস করতে বলবেন যা এটি আনন্দের সাথে করবে। তবে এর রেফারেন্স রাখবেন না কারণ ....

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

পাঠ্যপুস্তক বলছে যে আপনার স্মৃতি পরিচালনা করার এই পদ্ধতিতে কমপক্ষে 2 টি সুবিধা রয়েছে:

  1. কম ক্যাশে মিস করে কারণ বস্তুগুলি মেমরির ক্ষেত্রে একে অপরের নিকটে থাকে
  2. এটি ওএসে মেমরি ডি / এলোকেশন কলগুলির সংখ্যা হ্রাস করে যা কিছু সময় নেয় বলে মনে করা হয় ।

মনে রাখবেন যে আপনি কীভাবে মেমম্যান ব্যবহার করেন এবং কীভাবে আপনি অভ্যন্তরীণভাবে মেমরিটি সংগঠিত করবেন আপনি কীভাবে আপনার উপাদানগুলি ব্যবহার করবেন তার উপর নির্ভরশীল । আপনি যদি তাদের ধরণের উপর ভিত্তি করে তাদের মাধ্যমে পুনরাবৃত্তি করেন তবে আপনি উপাদানগুলি টাইপ অনুসারে রাখতে চান, যদি আপনি তাদের গেম অবজেক্টের উপর ভিত্তি করে পুনরাবৃত্তি করেন তবে আপনাকে অবশ্যই এটির কাছাকাছি থাকার একটি উপায় খুঁজে বের করতে হবে sure অন্য এর উপর ভিত্তি করে, ইত্যাদি ...

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