সিঙ্গল-ক্লিকগুলিকে কীভাবে সঠিকভাবে আলাদা করতে হবে এবং সি # ব্যবহার করে ইউনিটি 3 ডি-তে ডাবল-ক্লিক করুন?


15

আমি এখানে যা বুঝতে এবং শিখতে চেষ্টা করছি এটি একটি খুব প্রাথমিক বিষয়: সি # ব্যবহার করে ইউনিটির 3 প্রধান মাউস বোতামের জন্য একক-ক্লিকগুলি এবং ডাবল-ক্লিকগুলিকে সঠিকভাবে আলাদা করার সর্বাধিক সাধারণ এবং সর্বাধিক পালিশ উপায় কী?

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

আমাকে ব্যাখ্যা করতে দাও. প্রস্তাবিত সমাধানগুলির মধ্যে সর্বদা দুটি পদ্ধতির এবং এর সাথে সম্পর্কিত ত্রুটিগুলির একটি ছিল:

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

রুক্ষ উদাহরণ:

float dclick_threshold = 0.25f;
double timerdclick = 0;

if (Input.GetMouseButtonDown(0) 
{
   if (Time.time - timerdclick) > dclick_threshold)
   {
       Debug.Log("single click");
       //call the SingleClick() function, not shown
   } else {
       Debug.Log("double click");
       //call the DoubleClick() function, not shown
   }
   timerdclick = Time.time;
}
  1. একক-ক্লিকটি সক্রিয় হওয়ার জন্য অপেক্ষার জন্য বিলম্ব নির্ধারণ করুন, যার অর্থ, প্রতিটি ক্লিকে কেবলমাত্র একক ক্লিক ক্রিয়াকলাপ সক্রিয় করুন যদি শেষ ক্লিকটি প্রদত্ত প্রান্তিকের চেয়ে বেশি সময় ব্যয় হয়। তবে এটি স্বচ্ছন্দ ফলাফল দেয়, যেহেতু একক-ক্লিকগুলি সনাক্ত হওয়ার আগে অপেক্ষাটি লক্ষ্য করা সম্ভব। তার চেয়েও খারাপ, এই ধরণের সমাধানটি মেশিনগুলির মধ্যে বিভেদগুলির সাথে ভুগছে, যেহেতু এটি OS অ্যাকাউন্টে ব্যবহারকারীর ডাবল-ক্লিকের গতি সেটিংটি কতটা ধীর বা কত গতিযুক্ত তা বিবেচনায় নেই।

রুক্ষ উদাহরণ:

   float one_click = false;
   float dclick_threshold = 0.25f;
   double timerdclick = 0;

   if (one_click && ((Time.time - timerdclick) > dclick_threshold))
   {
       Debug.Log("single click");
       //call the SingleClick() function, not shown
       one_click = false;
   }

   if (Input.GetMouseButtonDown(0))
   {

       if (!one_click)
       {
           dclick = -1;
           timerdclick = Time.time;
           one_click = true;
       }

       else if (one_click && ((Time.time - timerdclick) < dclick_threshold))
       {
           Debug.Log("double click");
           //call the DoubleClick() function, not shown
           one_click = false;
       }

   }

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


হুম। ডাবল-ক্লিকগুলি সঠিকভাবে সনাক্ত করা হচ্ছে ... আমি কেবল এটি কীভাবে করব তা নিয়েই ভাবতে পারি যা সম্ভবত কোনও কম অপেশাদার নয়।
ড্রাকো

2
আমি মনে করি না আপনি ক্লিকগুলি আরও ভালভাবে সনাক্ত করতে পারবেন - আপনি ব্যবহারকারীর শারীরিক ক্রিয়া ফলাফলের পূর্বাভাস দিতে পারবেন না। আমি বরং আমার জিইউআই এবং মেকানিক্স ডিজাইনের দিকে মনোনিবেশ করব যাতে ট্রিগারযুক্ত ক্রিয়াকলাপগুলি তারা যতটা পারে ঠিক তত লুকিয়ে রাখে। * ঠিক আছে, তাত্ত্বিকভাবে আপনি কিছু এআই বিশ্লেষণের ব্যবহারের আচরণটি বাস্তবায়ন করতে পারেন, তবে ফলাফলগুলি সামঞ্জস্যপূর্ণ হবে না
বিস্মিত

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

উত্তর:


13

Coroutines মজাদার:

using UnityEngine;
using System.Collections;

public class DoubleClickTest : MonoBehaviour 
{
private float doubleClickTimeLimit = 0.25f;

protected void Start()
{
    StartCoroutine(InputListener());
}

// Update is called once per frame
private IEnumerator InputListener() 
{
    while(enabled)
    { //Run as long as this is activ

        if(Input.GetMouseButtonDown(0))
            yield return ClickEvent();

        yield return null;
    }
}

private IEnumerator ClickEvent()
{
    //pause a frame so you don't pick up the same mouse down event.
    yield return new WaitForEndOfFrame();

    float count = 0f;
    while(count < doubleClickTimeLimit)
    {
        if(Input.GetMouseButtonDown(0))
        {
            DoubleClick();
            yield break;
        }
        count += Time.deltaTime;// increment counter by change in time between frames
        yield return null; // wait for the next frame
    }
    SingleClick();
}


private void SingleClick()
{
    Debug.Log("Single Click");
}

private void DoubleClick()
{
    Debug.Log("Double Click");
}

}

স্বতন্ত্র বোতামটি টিপলে এটি সনাক্ত করা যায় না বলে মনে হয়; কেবলমাত্র যখন পর্দা ক্লিক করা হয় বা সাধারণভাবে ডাবল ক্লিক করা হয় (যদিও ওপি এটি অনুরোধ করেনি, সুতরাং এটি এত বেশি জিজ্ঞাসা করা মোটেও ন্যায়সঙ্গত নয়)। কেউ কীভাবে এটি করতে পারে তার কোনও পরামর্শ?
জাভাত্রা

প্রশ্নটিতে প্রস্তাবিত দ্বিতীয় পদ্ধতির চেয়ে এটি কীভাবে আলাদা তা আমি দেখতে পাচ্ছি না।
জন হ্যামিল্টন

5

আমি ইংরেজি পড়তে পারি না। তবে ইউএনআরএক্স আপনাকে সাহায্য করতে সক্ষম হতে পারে।

https://github.com/neuecc/UniRx#introduction

void Start () {

    var clickStream = Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0));
    var bufferStream = clickStream.Buffer (clickStream.Throttle (TimeSpan.FromMilliseconds (250))).Publish ().RefCount ();
    bufferStream.Where (xs => xs.Count == 1).Subscribe (_ => Debug.Log ("single click"));
    bufferStream.Where (xs => xs.Count >= 2).Subscribe (_ => Debug.Log ("double click"));
}

এটি কাজ করে তবে উইন্ডোজে ডাবল ক্লিকগুলি প্রয়োগ করা হয় ঠিক তেমন নয়। আপনি যখন ক্লিক করেন, উদাহরণস্বরূপ, এক নাগাড়ে 6 বার, কেবল একটি ডাবল ক্লিক তৈরি হয়। উইন্ডোজে এটি 3 টি ডাবল ক্লিক হবে। আপনি চেষ্টা করতে পারেন Control Panel → Mouse
ম্যাক্সিম কমলভ

2

উইন্ডোজ ডিফল্ট ডাবল ক্লিকের বিলম্ব 500ms = 0.5 সেকেন্ড।

সাধারণত কোনও গেমের ক্ষেত্রে বিশ্বব্যাপী নয়, ক্লিক করা হচ্ছে এমন নিয়ন্ত্রণে ডাবল ক্লিক পরিচালনা করা অনেক সহজ। যদি আপনি বিশ্বব্যাপী ডাবল ক্লিকগুলি হ্যান্ডেল করার সিদ্ধান্ত নেন তবে 2 টি খুব অনাকাঙ্ক্ষিত পার্শ্ব প্রতিক্রিয়া এড়াতে আপনাকে workarounds প্রয়োগ করতে হবে:

  1. প্রতিটি একক ক্লিক 0.5 সেকেন্ড দেরি করতে পারে।
  2. একটি নিয়ন্ত্রণে একক ক্লিকের পরে দ্রুত অন্য একটি নিয়ন্ত্রণের একটি ক্লিক ক্লিক করে দ্বিতীয় নিয়ন্ত্রণে ডাবল ক্লিক হিসাবে ভুল ব্যাখ্যা করা যেতে পারে।

যদি আপনাকে একটি বিশ্বব্যাপী বাস্তবায়ন ব্যবহার করতে হয় তবে আপনাকে ক্লিকের অবস্থানটিও দেখতে হবে - যদি মাউস খুব বেশি দূরে সরে যায় তবে এটি ডাবল ক্লিক নয়। আপনি যখনই ফোকাস পরিবর্তন করেন তখন আপনি সাধারণত একটি ফোকাস ট্র্যাকার প্রয়োগ করেন যা ডাবল ক্লিক কাউন্টারটিকে পুনরায় সেট করে।

ডাবল-ক্লিকের সময়সীমা অতিক্রান্ত হওয়া পর্যন্ত যদি আপনার অপেক্ষা করা হয় তবে এই প্রশ্নের জন্য, প্রতিটি কন্ট্রোলের জন্য এটি আলাদাভাবে পরিচালনা করা দরকার। আপনার 4 টি আলাদা ইভেন্ট রয়েছে:

  1. কার্সার রাখুন।
  2. একক ক্লিক, যা ডাবল ক্লিক বা নাও হতে পারে।
  3. ডবল ক্লিক করুন.
  4. ডাবল ক্লিকের সময়সীমা, একক ক্লিক ডাবল ক্লিক না হওয়ার জন্য নিশ্চিত হয়েছে।

যখনই সম্ভব, আপনি জিইউআই মিথস্ক্রিয়াগুলি এমনভাবে নকশা করার চেষ্টা করলেন যাতে শেষ ইভেন্টটি ব্যবহার করা হবে না: উইন্ডোজ ফাইল এক্সপ্লোরার তাত্ক্ষণিকভাবে একটি একক ক্লিকে একটি আইটেম নির্বাচন করবে এবং এটি একটি ডাবল ক্লিকে খুলবে, এবং নিশ্চিত সিঙ্গেলটিতে কিছুই করবে না ক্লিক.

অন্য কথায়: আপনি নিয়ন্ত্রণের পছন্দসই আচরণ কী তা নির্ভর করে আপনি প্রস্তাবিত দুটি বিকল্প ব্যবহার করেন।


2

উপরের সমাধানগুলি পুরো স্ক্রিনে করা ক্লিকগুলির জন্য কাজ করে। আপনি যদি পৃথক বোতামে ডাবল-ক্লিকগুলি সনাক্ত করতে চান তবে আমি পেয়েছি যে উপরের উত্তরে এই পরিবর্তনটি ভালভাবে কাজ করছে:

using UnityEngine;
using System.Collections;

public class DoubleClickTest : MonoBehaviour
{
    private float doubleClickTimeLimit = 0.35f;
    bool clickedOnce = false;
    public string singleTapMove;
    public string doubleTapMove;
    float count = 0f;

    public void startClick(){
        StartCoroutine (ClickEvent ());
    }

    public IEnumerator ClickEvent()
    {
        if (!clickedOnce && count < doubleClickTimeLimit) {
            clickedOnce = true;
        } else {
            clickedOnce = false;
            yield break;  //If the button is pressed twice, don't allow the second function call to fully execute.
        }
        yield return new WaitForEndOfFrame();

        while(count < doubleClickTimeLimit)
        {
            if(!clickedOnce)
            {
                DoubleClick();
                count = 0f;
                clickedOnce = false;
                yield break;
            }
            count += Time.deltaTime;// increment counter by change in time between frames
            yield return null; // wait for the next frame
        }
        SingleClick();
        count = 0f;
        clickedOnce = false;
    }
    private void SingleClick()
    {
        Debug.Log("Single Click");
    }

    private void DoubleClick()
    {
        Debug.Log("Double Click");
    }
}

এই স্ক্রিপ্টটি যতটা বোতাম আপনি তার সাথে সংযুক্ত করুন। তারপরে সম্পাদকের অন ক্লিকের বিভাগে (প্রতিটি বোতামের জন্য আপনি এটি সংযুক্ত করেছেন), '+' ক্লিক করুন, গেমের অবজেক্ট হিসাবে নিজেকে বোতামটি যুক্ত করুন, এবং তারপরে ফোন করার জন্য "ডাবলিক্লিকটেষ্ট -> স্টার্টক্লিক () 'নির্বাচন করুন বোতাম টিপলে।


1

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

আমি মনে করি Unক্যের পরিদর্শককে ব্যবহার করার পক্ষে এটি দুর্দান্ত উপায়, কারণ আপনি আপনার গেমের যেকোন বিষয়কে দৃষ্টিভঙ্গি এবং সুরক্ষিতভাবে উল্লেখ করতে পারেন বলে আপনার কোডটি আরও নমনীয়।

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

এরপরে আপনার রেইকাস্ট সক্ষম গেম অবজেক্টে ইভেন্টের ট্রিগার উপাদানটি যুক্ত করুন । একটি UI 'তে উপাদান এর মতো বা একটি পরী, একটি 3D বস্তুর সংঘর্ষ সঙ্গে । এটি ক্লিকের ইভেন্টটি আমাদের স্ক্রিপ্টে পৌঁছে দেবে। যোগ পয়েন্টার ক্লিক করুন ঘটনা টাইপ এবং রিসিভার খেলা বস্তুর হয়েছে সেট ক্লিক করুন কন্ট্রোলার এটা স্ক্রিপ্ট কম্পোনেন্ট এবং পরিশেষে তার নির্বাচন onClick () পদ্ধতি। (এছাড়াও আপনি আপডেটে সমস্ত ক্লিক পেতে স্ক্রিপ্ট পরিবর্তন করতে পারেন)) এবং এই পদক্ষেপটি এড়িয়ে যেতে পারেন)

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

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

এখানে চিত্র বর্ণনা লিখুন

স্ক্রিপ্ট নিজেই প্রথম টাইমে দুটি টাইমার দিয়ে একটি কর্টিন শুরু করে। প্রথমটির সাথে ক্লিক করে প্রথম ক্লিকটাইম এবং কারেন্টটাইম।

সময়সীমাটির মেয়াদ শেষ না হওয়া অবধি এই ফ্রেইট প্রতিটি ফ্রেমের শেষে একবার লুপ করে। ইতিমধ্যে অনক্লিক () পদ্ধতিতে ক্লিকগুলি গণনা অব্যাহত রয়েছে।

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

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using System.Collections;

public class ClickController : MonoBehaviour
{
    public float timeLimit = 0.25f;
    public PointerEventData.InputButton button;

    [System.Serializable]
    public class OnSingleClick : UnityEvent {};
    public OnSingleClick onSingleClick;

    [System.Serializable]
    public class OnDoubleClick : UnityEvent {};
    public OnDoubleClick onDoubleClick;

    private int clickCount;
    private float firstClickTime;
    private float currentTime;

    private ClickController () {
        clickCount = 0;
    }

    public void onClick (BaseEventData data) {

        PointerEventData pointerData = data as PointerEventData;

        if (this.button != pointerData.button) {
            return;
        }

        this.clickCount++;

        if (this.clickCount == 1) {
            firstClickTime = pointerData.clickTime;
            currentTime = firstClickTime;
            StartCoroutine (ClickRoutine ());
        }
    }

    private IEnumerator ClickRoutine () {

        while (clickCount != 0)
        {
            yield return new WaitForEndOfFrame();

            currentTime += Time.deltaTime;

            if (currentTime >= firstClickTime + timeLimit) {
                if (clickCount == 1) {
                    onSingleClick.Invoke ();
                } else {
                    onDoubleClick.Invoke ();
                }
                clickCount = 0;
            }
        }
    }
}

ঠিক আছে, আমার প্রথম পোস্টটি আরও কিছুটা তথ্যপূর্ণ হওয়া উচিত। তাই আমি বিস্তারিত বিবরণ যুক্ত করেছি এবং স্ক্রিপ্টটি কিছুটা পরিমার্জন করেছি। আপনার -1 ভাল লাগলে দয়া করে অপসারণ করুন।
নরব

0

আমি মনে করি ব্যবহারকারীর মন পড়ার কোনও উপায় নেই হয় সে সিঙ্গল বা ডাবল ক্লিক করবে, সর্বোপরি আমাদের ইনপুটটির জন্য অপেক্ষা করতে হবে। যদিও আপনি দ্বিতীয় ক্লিকের জন্য 0.01 সেকেন্ডের (যত কম) অপেক্ষা করতে পারেন। এই বিষয়ে আমি ওয়েটিং বিকল্পের জন্য যেতে চাই।

এবং হ্যাঁ Coroutinesমজাদার ...

একটি বিকল্প

float _threshold = 0.25f;

void Start ()
{
    StartCoroutine ("DetectTouchInput");
}

IEnumerator DetectTouchInput ()
{
    while (true) {
        float duration = 0;
        bool doubleClicked = false;
        if (Input.GetMouseButtonDown (0)) {
            while (duration < _threshold) {
                duration += Time.deltaTime;
                yield return new WaitForSeconds (0.005f);
                if (Input.GetMouseButtonDown (0)) {
                    doubleClicked = true;
                    duration = _threshold;
                    // Double click/tap
                    print ("Double Click detected");
                }
            }
            if (!doubleClicked) {
                // Single click/tap
                print ("Single Click detected");
            }
        }
        yield return null;
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.