অবজেক্টটি যাই হোক না কেন তার ভিত্তিতে প্রসঙ্গ মেনুগুলি কীভাবে ডিজাইন করবেন?


21

আমি "রাইট ক্লিক অপশন" আচরণের জন্য একটি সমাধান খুঁজছি।

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

বিভিন্ন পরিস্থিতিতে উদাহরণের জন্য রাইট ক্লিক করুন :

ইনভেন্টরি: হেলমেট অপশন দেখায় (সজ্জিত, ব্যবহার, ড্রপ, বর্ণনা)

ব্যাংক: হেলমেট অপশন দেখায় (1 নিন, এক্স নিন, সমস্ত নিন, বিবরণ)

মেঝে: হেলমেট অপশন দেখায় (নিন, এখানে চলুন, বর্ণনা)

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

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

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

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

আমি সি # এবং ইউনিটি 3 ডি ব্যবহার করছি তবে প্রদত্ত যে কোনও উদাহরণের সাথে সেগুলির সাথে সম্পর্কিত হতে হবে না কারণ আমি প্রকৃত কোডের বিপরীতে একটি প্যাটার্ন পরে আছি।

যে কোনও সহায়তা অনেক প্রশংসাযোগ্য এবং যদি আমি আমার প্রশ্নে বা কাঙ্ক্ষিত ফলাফলগুলিতে পরিষ্কার না হয়ে থাকি তবে দয়া করে একটি মন্তব্য পোস্ট করুন এবং আমি এটি ASAP এ ঝোঁক দেব।

আমি এখন পর্যন্ত যা চেষ্টা করেছি তা এখানে:

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

"সজ্জিত" ব্যতীত আপনার কমান্ডের তালিকাটি দেখে মনে হচ্ছে এগুলি সমস্ত জেনেরিক এবং আইটেমটি যা তা বিবেচনা না করে প্রয়োগ করুন - নিন, ছাড়ুন, বিবরণ দিন, এখানে যান, ইত্যাদি
ashes999

যদি কোনও আইটেমটি ব্যবসা-বাণিজ্যযোগ্য না হয় তবে "ড্রপ" এর পরিবর্তে এটি "ধ্বংস" করতে পারে
মাইক হান্ট

পুরোপুরি স্পষ্ট বলতে, অনেক গেম একটি ডিএসএল ব্যবহার করে এটি সমাধান করে - গেমের সাথে নির্দিষ্ট একটি কাস্টম স্ক্রিপ্টিং ভাষা।
কর্সিকা

1
রুনস্কেপের পরে আপনার গেমটি মডেলিংয়ের জন্য +1। আমি সেই খেলাটি পছন্দ করি।
জেনাডিক্স

উত্তর:


23

সফ্টওয়্যার বিকাশের সমস্ত কিছুর মতো, কোনও আদর্শ সমাধান নেই। কেবলমাত্র সেই সমাধান যা আপনার এবং আপনার প্রকল্পের জন্য আদর্শ। আপনি ব্যবহার করতে পারেন এখানে কিছু।

বিকল্প 1: পদ্ধতিগত মডেল

প্রাচীন অপ্রচলিত পুরোনো স্কুল পদ্ধতি।

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

বিকল্প 2: অবজেক্ট ওরিয়েন্টেড মডেল

এটি ওওপি-বাই-বুক সমাধানের আরও বেশি যা উত্তরাধিকার এবং বহুবৈচিত্র্যের উপর ভিত্তি করে।

একটি বেস ক্লাসের আছে Itemঅন্যান্য আইটেম পছন্দ যেখান থেকে EdibleItem, EquipableItemইত্যাদি উত্তরাধিকারী। বেস বর্গ একটি সর্বজনীন পদ্ধতি থাকা উচিত GetContextMenuEntriesForBank, GetContextMenuEntriesForFloorইত্যাদি যা একটি তালিকা আসতে ContextMenuEntry। প্রতিটি উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণি এই আইটেম ধরণের জন্য উপযুক্ত প্রসঙ্গ মেনু এন্ট্রিগুলি ফিরিয়ে আনতে এই পদ্ধতিগুলি ওভাররাইড করবে। এটি কোনও ডিফল্ট এন্ট্রিগুলি পেতে যে কোনও আইটেম ধরণের জন্য প্রযোজ্য তা বেস শ্রেণীর একই পদ্ধতিতে কল করতে পারে। এটি ContextMenuEntryএমন একটি পদ্ধতি সহ একটি শ্রেণি হবে Performযা এটি তৈরি করে আইটেম থেকে প্রাসঙ্গিক পদ্ধতিটিকে কল করে (এটির জন্য আপনি কোনও প্রতিনিধি ব্যবহার করতে পারেন )।

এক্সএমএল ফাইল থেকে ডেটা পড়ার সময় এই প্যাটার্নটি প্রয়োগের ক্ষেত্রে আপনার সমস্যা সম্পর্কিত: প্রথমে প্রতিটি আইটেমের প্রকার নির্ধারণ করতে এক্সএমএল নোড পরীক্ষা করুন, তারপরে উপযুক্ত উপ-শ্রেণীর উদাহরণ তৈরি করতে প্রতিটি ধরণের জন্য বিশেষায়িত কোড ব্যবহার করুন।

বিকল্প 3: উপাদান-ভিত্তিক মডেল

এই প্যাটার্নটি উত্তরাধিকারের পরিবর্তে রচনা ব্যবহার করে এবং বাকী ityক্য কীভাবে কাজ করে তার কাছাকাছি। আপনি কীভাবে আপনার গেমটি গঠন করেন তার উপর নির্ভর করে এটির জন্য ইউনিটি উপাদান উপাদানটি ব্যবহার করা সম্ভব / উপকারী হতে পারে ... না, আপনার মাইলেজটি ভিন্ন হতে পারে।

শ্রেণী প্রত্যেকটি বস্তুর Itemমত উপাদানের একটি তালিকা হবে Equipable, Edible, Sellable, Drinkable, ইত্যাদি একটি আইটেম এক বা প্রতিটি উপাদানের কেউই থাকতে পারে (উদাহরণস্বরূপ, একটি শিরস্ত্রাণ চকলেট দিয়ে তৈরি উভয় হবে Equipableএবং Edible, এবং যখন এটা একটি চক্রান্ত-সমালোচনামূলক নয় কোয়েস্ট আইটেম Sellable)। প্রোগ্রামিং যুক্তি যা উপাদানটির সাথে নির্দিষ্ট তা সেই উপাদানটিতে প্রয়োগ করা হয়। যখন ব্যবহারকারী কোনও আইটেমে রাইট ক্লিক করে, আইটেমের উপাদানগুলি পুনরাবৃত্তি হয় এবং উপস্থিত প্রতিটি উপাদানগুলির জন্য প্রসঙ্গ-মেনু এন্ট্রি যুক্ত করা হয়। যখন ব্যবহারকারী এই এন্ট্রিগুলির মধ্যে একটি নির্বাচন করে, সেই উপাদানটি যা এতে প্রবেশ করে বিকল্পটি প্রক্রিয়া করে।

প্রতিটি উপাদানগুলির জন্য একটি সাব-নোড থাকার মাধ্যমে আপনি এটি আপনার এক্সএমএল-ফাইলটিতে উপস্থাপন করতে পারেন। উদাহরণ:

   <item>
      <name>Chocolate Helmet</name>
      <sprite>helmet-chocolate.png</sprite>
      <description>Protects you from enemies and from starving</description>
      <edible>
          <taste>sweet</taste>
          <calories>2560</calories>
      </edible>
      <equipable>
          <slot>head</slot>
          <def>20</def>
      </equipable>
      <sellable>
          <value>120</value>
      </sellable>
   </item>

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

@ মাইকহান্ট-এর উপাদানগুলির তালিকা মডেলটি অবশ্যই আপনার তদন্ত করা উচিত, যেহেতু এটি কোনও ফাইল থেকে আইটেম সংজ্ঞা লোড করার সাথে দুর্দান্তভাবে কাজ করে।
ব্যবহারকারী 253751

আমার প্রাথমিক প্রচেষ্টা যেমনটি ছিল ঠিক তেমনই আমি প্রথমে চেষ্টা করবো তবেই ইমিবিস। ধন্যবাদ :)
মাইক হান্ট

পুরানো উত্তর, তবে "তালিকাভুক্ত উপাদানগুলি" মডেলটি কীভাবে প্রয়োগ করতে হবে তার কোনও দলিল আছে?
জেফ

@ জেফ যদি আপনি আপনার খেলায় এই প্যাটার্নটি প্রয়োগ করতে চান এবং কীভাবে কোনও প্রশ্ন চান তবে দয়া করে একটি নতুন প্রশ্ন পোস্ট করুন।
ফিলিপ

9

সুতরাং, মাইক হান্ট, আপনার প্রশ্নটি আমাকে আগ্রহী, আমি একটি সম্পূর্ণ সমাধান বাস্তবায়নের সিদ্ধান্ত নিয়েছি। তিন ঘন্টা বিভিন্ন জিনিস চেষ্টা করার পরে, আমি এই ধাপে ধাপে সমাধানটি দিয়ে শেষ করেছি:

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

সামগ্রী প্যানেল তৈরি করা হচ্ছে

(এই প্যানেলটি আমাদের প্রসঙ্গ-মেনু বোতামগুলির জন্য ধারক হবে)

  • নতুন তৈরী করা UI Panel
  • anchorনীচে-বামে সেট করুন
  • width300 এ সেট করুন (আপনার ইচ্ছামতো)
  • একটি প্যানেলে একটি নতুন উপাদান যুক্ত করুন Vertical Layout Groupএবং Child Alignmentউপরের-কেন্দ্রে Child Force Expandপ্রস্থে (উচ্চতা নয়) সেট করুন
  • একটি প্যানেলে একটি নতুন উপাদান যুক্ত করুন Content Size Fitterএবং Vertical Fitন্যূনতম আকারে সেট করুন
  • এটি প্রিফাব হিসাবে সংরক্ষণ করুন

(এই মুহুর্তে আমাদের প্যানেলটি একটি লাইনে সঙ্কুচিত হবে It's এটি সাধারণ This

নমুনা বোতাম তৈরি করা হচ্ছে

(এই বোতামটি প্রসঙ্গ-মেনু আইটেমগুলি দেখানোর জন্য তাত্ক্ষণিকভাবে এবং কাস্টমাইজ করা হবে)

  • নতুন ইউআই বোতাম তৈরি করুন
  • anchorউপরের-বামে সেট করুন
  • একটি বাটন একটি নতুন উপাদান যোগ করুন Layout Element, সেট Min Heightথেকে 30, Preferred Height30 থেকে
  • এটি প্রিফাব হিসাবে সংরক্ষণ করুন

ContextMenu.cs স্ক্রিপ্ট তৈরি করা হচ্ছে

(এই স্ক্রিপ্টের একটি পদ্ধতি রয়েছে যা প্রসঙ্গ মেনু তৈরি করে এবং দেখায়)

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[System.Serializable]
public class ContextMenuItem
{
    // this class - just a box to some data

    public string text;             // text to display on button
    public Button button;           // sample button prefab
    public Action<Image> action;    // delegate to method that needs to be executed when button is clicked

    public ContextMenuItem(string text, Button button, Action<Image> action)
    {
        this.text = text;
        this.button = button;
        this.action = action;
    }
}

public class ContextMenu : MonoBehaviour
{
    public Image contentPanel;              // content panel prefab
    public Canvas canvas;                   // link to main canvas, where will be Context Menu

    private static ContextMenu instance;    // some kind of singleton here

    public static ContextMenu Instance
    {
        get
        {
            if(instance == null)
            {
                instance = FindObjectOfType(typeof(ContextMenu)) as ContextMenu;
                if(instance == null)
                {
                    instance = new ContextMenu();
                }
            }
            return instance;
        }
    }

    public void CreateContextMenu(List<ContextMenuItem> items, Vector2 position)
    {
        // here we are creating and displaying Context Menu

        Image panel = Instantiate(contentPanel, new Vector3(position.x, position.y, 0), Quaternion.identity) as Image;
        panel.transform.SetParent(canvas.transform);
        panel.transform.SetAsLastSibling();
        panel.rectTransform.anchoredPosition = position;

        foreach(var item in items)
        {
            ContextMenuItem tempReference = item;
            Button button = Instantiate(item.button) as Button;
            Text buttonText = button.GetComponentInChildren(typeof(Text)) as Text;
            buttonText.text = item.text;
            button.onClick.AddListener(delegate { tempReference.action(panel); });
            button.transform.SetParent(panel.transform);
        }
    }
}
  • এই স্ক্রিপ্টটি একটি ক্যানভাসে সংযুক্ত করুন এবং ক্ষেত্রগুলি বসান। টেনে এনে এন-ড্রপ ContentPanelসংশ্লিষ্ট স্লটে prefab এবং স্লট টেনে আনুন ক্যানভাস নিজেই Canvas

আইটেমকন্ট্রোলার.এস স্ক্রিপ্ট তৈরি করা হচ্ছে

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ItemController : MonoBehaviour
{
    public Button sampleButton;                         // sample button prefab
    private List<ContextMenuItem> contextMenuItems;     // list of items in menu

    void Awake()
    {
        // Here we are creating and populating our future Context Menu.
        // I do it in Awake once, but as you can see, 
        // it can be edited at runtime anywhere and anytime.

        contextMenuItems = new List<ContextMenuItem>();
        Action<Image> equip = new Action<Image>(EquipAction);
        Action<Image> use = new Action<Image>(UseAction);
        Action<Image> drop = new Action<Image>(DropAction);

        contextMenuItems.Add(new ContextMenuItem("Equip", sampleButton, equip));
        contextMenuItems.Add(new ContextMenuItem("Use", sampleButton, use));
        contextMenuItems.Add(new ContextMenuItem("Drop", sampleButton, drop));
    }

    void OnMouseOver()
    {
        if(Input.GetMouseButtonDown(1))
        {
            Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
            ContextMenu.Instance.CreateContextMenu(contextMenuItems, new Vector2(pos.x, pos.y));
        }

    }

    void EquipAction(Image contextPanel)
    {
        Debug.Log("Equipped");
        Destroy(contextPanel.gameObject);
    }

    void UseAction(Image contextPanel)
    {
        Debug.Log("Used");
        Destroy(contextPanel.gameObject);
    }

    void DropAction(Image contextPanel)
    {
        Debug.Log("Dropped");
        Destroy(contextPanel.gameObject);
    }
}
  • দৃশ্যে নমুনা অবজেক্ট তৈরি করুন (অর্থাত্ Cube), এটি ক্যামেরায় দৃশ্যমান হতে দিন এবং এটির সাথে এই স্ক্রিপ্টটি সংযুক্ত করুন। sampleButtonসংশ্লিষ্ট স্লটে প্রিফাব টেনে আনুন ।

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

সম্ভাব্য উন্নতি:

  • আরও জেনেরিক!
  • আরও ভাল মেমরি পরিচালনা (নোংরা লিঙ্কগুলি, প্যানেলটি ধ্বংস করছে না, অক্ষম করছে)
  • কিছু অভিনব জিনিস

নমুনা প্রকল্প (ইউনিট পার্সোনাল 5.2.0, ভিজ্যুয়ালস্টুডিও প্লাগিন): https://drive.google.com/file/d/0B7iGjyVbWvFwUnRQRVVaOGdDc2M/view?usp=sharing


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

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