Was ich hier zu verstehen und zu lernen versuche, ist eine sehr grundlegende Sache: Was ist die allgemeinste und ausgefeilteste Methode, um Einzel- und Doppelklicks für die 3 wichtigsten Maustasten in Unity mit C # richtig zu unterscheiden?
Meine Betonung auf dem Wort richtig ist nicht umsonst. Obwohl ich überrascht war, dass dies auf dieser Website anscheinend noch nie gestellt wurde, habe ich natürlich zahlreiche ähnliche Fragen in den Foren von Unity und auf den Frage-Antwort-Seiten von Unity gesucht und gefunden. Wie es jedoch häufig bei Antworten in diesen Ressourcen der Fall ist, schienen sie alle entweder einfach falsch oder zumindest ein bisschen zu amateurhaft zu sein.
Lassen Sie mich erklären. Die vorgeschlagenen Lösungen hatten immer einen der beiden Ansätze und die entsprechenden Mängel:
- Berechnen Sie bei jedem Klick das Zeit-Delta seit dem letzten Klick. Wenn es kleiner als ein bestimmter Schwellenwert ist, wird ein Doppelklick erkannt. Diese Lösung führt jedoch dazu, dass ein schneller Einzelklick erkannt wird, bevor der Doppelklick erkannt wird, was in den meisten Situationen unerwünscht ist, da dann sowohl Einzelklick- als auch Doppelklickaktionen aktiviert werden.
Grobes Beispiel:
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;
}
- Legen Sie eine Wartezeit für die Aktivierung des Einzelklicks fest. Dies bedeutet, dass bei jedem Klick nur dann Einzelklickaktionen aktiviert werden, wenn die Zeitverzögerung seit dem letzten Klick einen bestimmten Schwellenwert überschreitet. Dies führt jedoch zu schleppenden Ergebnissen, da ein Warten, bevor es möglich ist, das Warten zu bemerken, bevor Einzelklicks erkannt werden. Schlimmer noch, diese Art von Lösung weist maschinenübergreifende Diskrepanzen auf, da nicht berücksichtigt wird, wie langsam oder wie schnell die Doppelklickgeschwindigkeitseinstellung des Benutzers auf Betriebssystemebene ist.
Grobes Beispiel:
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;
}
}
Daher werden meine Fragen wie folgt. Gibt es eine bessere und zuverlässigere Methode zum Erkennen von Doppelklicks in Unity mithilfe von C # als diese Lösungen und eine, mit der die oben genannten Probleme behoben werden können?
Antworten:
Coroutinen machen Spaß:
quelle
Ich kann kein Englisch lesen. Möglicherweise kann UniRx Ihnen jedoch weiterhelfen.
https://github.com/neuecc/UniRx#introduction
quelle
Control Panel → Mouse
.Die Windows-Standardverzögerung für Doppelklicks beträgt 500 ms = 0,5 Sekunden.
Im Allgemeinen ist es in einem Spiel viel einfacher, einen Doppelklick auf das angeklickte Steuerelement auszuführen, als global. Wenn Sie sich entscheiden, Doppelklicks global zu verarbeiten, müssen Sie Problemumgehungen implementieren, um zwei sehr unerwünschte Nebenwirkungen zu vermeiden:
Wenn Sie eine globale Implementierung verwenden müssen, müssen Sie auch die Position des Klicks überprüfen. Wenn die Maus zu weit bewegt wurde, ist dies kein Doppelklick. Normalerweise implementieren Sie einen Fokus-Tracker, der den Doppelklickzähler zurücksetzt, wenn sich der Fokus ändert.
Bei der Frage, ob Sie warten sollen, bis das Doppelklick-Timeout abgelaufen ist, muss dies für jedes Steuerelement unterschiedlich gehandhabt werden. Sie haben 4 verschiedene Ereignisse:
Wann immer möglich, versuchen Sie, die GUI-Interaktionen so zu gestalten, dass das letzte Ereignis nicht verwendet wird: Der Windows-Datei-Explorer wählt ein Element sofort mit einem Klick aus und öffnet es mit einem Doppelklick. Bei einem bestätigten Ereignis wird nichts unternommen klicken.
Mit anderen Worten: Sie verwenden beide von Ihnen vorgeschlagenen Optionen, abhängig vom gewünschten Verhalten des Steuerelements.
quelle
Die obigen Lösungen funktionieren für Klicks auf dem gesamten Bildschirm. Wenn Sie Doppelklicks auf einzelne Schaltflächen erkennen möchten, habe ich festgestellt, dass diese Änderung an der obigen Antwort gut funktioniert:
Hängen Sie dieses Skript an beliebig viele Schaltflächen an. Klicken Sie dann im Abschnitt "On Click" des Editors (für jede Schaltfläche, an die Sie diese anhängen) auf "+", fügen Sie die Schaltfläche als Spielobjekt hinzu und wählen Sie "DoubleClickTest -> startClick ()" als aufzurufende Funktion wenn die Taste gedrückt wird.
quelle
Ich suchte nach einem geeigneten Single-Double-Click-Handler. Ich habe dieses Thema gefunden und einige wirklich gute Ideen gesammelt. Also habe ich mir endlich die folgende Lösung ausgedacht und möchte sie mit Ihnen teilen. Ich hoffe, Sie finden diese Methode hilfreich.
Ich denke, es ist ein großartiger Ansatz, den Inspector von Unity zu verwenden, da Ihr Code auf diese Weise flexibler ist, da Sie jedes Ihrer Spielobjekte visuell und sicher referenzieren können.
Fügen Sie zuerst die Event System- Komponente zu einem Ihrer Spielobjekte hinzu. Dadurch wird auch die Komponente Standalone Input Module hinzugefügt . Dies kümmert sich um die Eingabeereignisse wie Mausklicks und Berührungen. Ich empfehle dies an einem einzelnen Spielobjekt zu tun.
Fügen Sie als Nächstes die Event Trigger- Komponente zu einem Ihrer Raycast-fähigen Spielobjekte hinzu. Wie ein Oberflächenelement oder ein Sprite ein 3D-Objekt mit einem Collider . Dadurch wird das Click-Ereignis an unser Skript übergeben. Fügen Sie den Ereignistyp " Zeigerklick" hinzu, und legen Sie das Empfängerspielobjekt fest, auf dem sich die Skriptkomponente " Click Controller" befindet , und wählen Sie schließlich die Methode " onClick () " aus. (Sie können auch das Skript ändern, um alle Klicks in einem Update () zu erhalten, und diesen Schritt überspringen.)
Das Empfängerspielobjekt, das natürlich dasjenige mit dem Ereignisauslöser sein kann, wird also alles mit den Einzel- oder Doppelklickereignissen tun.
Sie können das Zeitlimit für Doppelklick, die gewünschte Schaltfläche und die benutzerdefinierten Ereignisse für Einzel- und Doppelklick festlegen. Die einzige Einschränkung ist , dass Sie können wählen , nur eine Taste zu einem Zeitpunkt für ein Spiel Objekt .
Das Skript selbst startet bei jedem ersten Klick eine Coroutine mit zwei Timern. Die firstClickTime und die currentTime werden mit der ersten synchronisiert.
Diese Coroutine wiederholt sich einmal am Ende jedes Frames, bis das Zeitlimit abgelaufen ist. Währenddessen zählt die onClick () -Methode die Klicks weiter.
Wenn das Zeitlimit abgelaufen ist, ruft es das Einzel- oder Doppelklick-Ereignis entsprechend dem clickCounter auf. Dann setzt es diesen Zähler auf Null, so dass die Coroutine beendet werden kann und der gesamte Prozess von vorne beginnt.
quelle
Ich denke, es gibt keine Möglichkeit, die Gedanken des Benutzers zu lesen, entweder er klickt einfach oder doppelt, schließlich müssen wir auf die Eingabe warten. Sie können jedoch eine Wartezeit von 0,01 Sekunden (so niedrig wie möglich) für den zweiten Klick festlegen. In dieser Hinsicht würde ich mich für die Wartemöglichkeit entscheiden.
Und JA
Coroutines
macht Spaß ...Eine Alternative
quelle