To, co próbuję zrozumieć i nauczyć się tutaj, jest bardzo podstawową rzeczą: jaki jest najbardziej ogólny i najbardziej dopracowany sposób prawidłowego rozróżnienia pojedynczych kliknięć i podwójnych kliknięć dla 3 głównych przycisków myszy w Unity przy użyciu C #?
Mój nacisk na to słowo właściwie nie jest na darmo. Chociaż byłem zaskoczony, że wydaje się, że nigdy wcześniej nie zadawano tego na tej stronie, oczywiście przeszukałem i znalazłem wiele podobnych pytań na forach Unity i na własnych stronach z odpowiedziami. Jednak, jak to często bywa z odpowiedziami zamieszczonymi w tych zasobach, wszystkie wydawały się albo błędne, albo przynajmniej nieco amatorskie.
Pozwól mi wyjaśnić. Proponowane rozwiązania zawsze miały jedno z dwóch podejść i odpowiadające im wady:
- za każdym razem, gdy nastąpi kliknięcie, obliczyć różnicę czasu od ostatniego kliknięcia, a jeśli byłby on mniejszy niż określony próg, wykryte zostanie podwójne kliknięcie. Jednak to rozwiązanie powoduje wykrycie szybkiego pojedynczego kliknięcia przed wykryciem podwójnego kliknięcia, co jest niepożądane w większości sytuacji, ponieważ wtedy aktywuje zarówno pojedyncze, jak i podwójne kliknięcie.
Szorstki przykład:
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;
}
- ustaw opóźnienie oczekiwania na aktywację pojedynczego kliknięcia, co oznacza, że przy każdym kliknięciu aktywuj akcje pojedynczego kliknięcia tylko wtedy, gdy opóźnienie od ostatniego kliknięcia przekracza określony próg. Daje to jednak powolne wyniki, ponieważ oczekiwanie przed zauważeniem oczekiwania przed wykryciem pojedynczych kliknięć. Co gorsza, w tego rodzaju rozwiązaniu występują rozbieżności między komputerami, ponieważ nie bierze ono pod uwagę szybkości i szybkości ustawienia podwójnego kliknięcia przez użytkownika na poziomie systemu operacyjnego.
Szorstki przykład:
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;
}
}
Dlatego moje pytania stają się następujące. Czy istnieje bardziej dopracowany i niezawodny sposób wykrywania podwójnych kliknięć w Unity przy użyciu C #, inny niż te rozwiązania, i taki, który radzi sobie z wyżej wymienionymi problemami?
Odpowiedzi:
Coroutines są fajne:
źródło
Nie umiem czytać po angielsku. Ale UniRx może ci pomóc.
https://github.com/neuecc/UniRx#introduction
źródło
Control Panel → Mouse
.Domyślne opóźnienie podwójnego kliknięcia w systemie Windows wynosi 500 ms = 0,5 sekundy.
Zasadniczo w grze znacznie łatwiej jest obsługiwać podwójne kliknięcie kontrolki, która jest klikana, nie globalnie. Jeśli zdecydujesz się obsługiwać podwójne kliknięcia na całym świecie, musisz wdrożyć obejścia, aby uniknąć 2 bardzo niepożądanych efektów ubocznych:
Jeśli musisz użyć globalnej implementacji, musisz także spojrzeć na lokalizację kliknięcia - jeśli mysz przesunie się za daleko, nie będzie to podwójne kliknięcie. Zwykle zaimplementowałbyś moduł śledzenia fokusu, który resetuje licznik podwójnych kliknięć za każdym razem, gdy zmienia się fokus.
Na pytanie, czy należy poczekać, aż upłynie limit czasu podwójnego kliknięcia, należy to rozpatrzyć inaczej dla każdej kontroli. Masz 4 różne wydarzenia:
O ile to możliwe, próbujesz zaprojektować interakcje interfejsu GUI w taki sposób, aby ostatnie zdarzenie nie było używane: Eksplorator plików systemu Windows natychmiast wybierze element za pomocą jednego kliknięcia i otworzy go za pomocą podwójnego kliknięcia i nie zrobi nic na potwierdzonym pojedynczym Kliknij.
Innymi słowy: korzystasz z obu zasugerowanych opcji, w zależności od pożądanego zachowania kontrolki.
źródło
Powyższe rozwiązania działają w przypadku kliknięć wykonanych na całym ekranie. Jeśli chcesz wykryć podwójne kliknięcie poszczególnych przycisków, zauważyłem, że modyfikacja powyższej odpowiedzi działa dobrze:
Dołącz ten skrypt do dowolnej liczby przycisków. Następnie w sekcji Edytora po kliknięciu (dla każdego przycisku, do którego go dołączasz), kliknij „+”, dodaj przycisk do siebie jako obiekt gry, a następnie wybierz „DoubleClickTest -> startClick ()” jako funkcję do wywołania po naciśnięciu przycisku.
źródło
Szukałem odpowiedniego modułu obsługi pojedynczego kliknięcia. Znalazłem ten temat i zebrałem kilka naprawdę dobrych pomysłów. W końcu wymyśliłem następujące rozwiązanie i chcę się z tobą podzielić. Mam nadzieję, że uznasz tę metodę za pomocną.
Myślę, że to świetne podejście do korzystania z inspektora Unity, ponieważ w ten sposób twój kod jest bardziej elastyczny, ponieważ możesz wizualnie i bezpiecznie odwoływać się do dowolnego obiektu gry.
Najpierw dodaj komponent System zdarzeń do dowolnego obiektu gry. Spowoduje to również dodanie modułu autonomicznego modułu wejściowego . To zajmie się wejściowymi zdarzeniami, takimi jak kliknięcia i dotknięcia myszy. Polecam to zrobić na pojedynczym obiekcie gry.
Następnie dodaj składnik Event Trigger do dowolnego obiektu gry obsługującego funkcję raycast . Podobnie jak element interfejsu użytkownika lub duszek, obiekt 3D ze zderzaczem . Spowoduje to dostarczenie zdarzenia kliknięcia do naszego skryptu. Dodaj typ zdarzenia Pointer Click i ustaw obiekt gry odbiornika, który ma składnik skryptu Click Controller , a następnie wybierz jego onClick () metodę . (Możesz także zmienić skrypt, aby otrzymywać wszystkie kliknięcia w Aktualizacji () i pomijać ten krok.)
Tak więc obiekt gry odbiornika, którym oczywiście może być wyzwalacz zdarzenia, zrobi wszystko ze zdarzeniami pojedynczego lub podwójnego kliknięcia.
Możesz ustawić limit czasu podwójnego kliknięcia, żądany przycisk oraz zdarzenia niestandardowe dla pojedynczego i podwójnego kliknięcia. Jedynym ograniczeniem jest to, że możesz wybrać tylko jeden przycisk na raz dla jednego obiektu gry .
Sam skrypt uruchamia coroutine przy każdym pierwszym kliknięciu za pomocą dwóch timerów. FirstClickTime i currentTime w synchronizacji z pierwszym.
Ta coroutine zapętla się na końcu każdej klatki, aż do upływu terminu. Tymczasem metoda onClick () kontynuuje liczenie kliknięć.
Po upływie terminu wywołuje zdarzenie jedno- lub dwukrotne kliknięcie zgodnie z parametrem clickCounter. Następnie ustawia ten licznik na zero, dzięki czemu coroutine może się skończyć, a cały proces rozpoczyna się od początku.
źródło
Myślę, że nie ma sposobu, aby odczytać zdanie użytkownika, albo kliknie jeden lub dwa razy, w końcu musimy czekać na dane wejściowe. Chociaż możesz ustawić oczekiwanie na 0,01 sekundy (maksymalnie o tyle) na drugie kliknięcie. W związku z tym wybrałbym opcję oczekiwania.
I tak
Coroutines
są fajne ...Alternatywa
źródło