Horreurs de OnPointerDown contre OnBeginDrag dans Unity3D
Je suis préoccupé par la différence entre OnPointerDown
contre OnBeginDrag
dans un seul mouvement de doigt de code.
(Dans la dernière Unité paradigme de l'aide d'un physique raycaster: donc, finalement, l'Unité sera correctement ignorer le contact sur la couche d'INTERFACE utilisateur.
Donc à partir de 2015 ce que vous devez faire est ceci:
- Oublier la merde traditionnel
Input
ouTouches
système qui sont de la merde et même Unité admettre sont tout à fait inutile de la merde depuis qu'ils ne fonctionnent pas - Ajouter un vide objet de jeu avec une BoxCollider2D, probablement plus grande que l'écran. Faire la couche de "Dessiner" (paramètres physiques, il interagit avec rien)
- Simplement ajouter à l'appareil photo, 2D ou en 3D, la physique raycaster. masque d'événement de votre "Tirage" de la couche.
Faire un script comme ci-dessous et de le mettre sur "dessiner".
(Pointe - n'oubliez pas d'ajouter simplement un EventSystem
à la scène. Bizarrement, l'Unité ne pas faire cela automatiquement pour vous dans certaines situations, mais l'Unité ne le faire automatiquement pour vous dans d'autres situations, il est donc ennuyeux si vous oubliez!)
Mais voici le problème.
Il y a obtenu d'être certains subtile différence entre l'utilisation de OnPointerDown
contre OnBeginDrag
(et correspondant à la fin des appels). (Vous pouvez juste changer l'action dans l'exemple de code suivant.)
Naturellement l'Unité n'offre pas de conseils sur ce; le code suivant magnifiquement rejette errants attrape et aussi parfaitement ignore votre couche d'INTERFACE utilisateur (grâce à l'Unité! lors de la dernière!) mais je suis complètement perplexe à propos de la différence entre les deux approches (commencer à glisser V commencer à toucher) et je ne peut pas de toute façon de trouver la logique de la différence entre les deux dans les tests unitaires.
Quelle est la réponse?
/*
general movement of something by a finger.
*/
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class FingerMove:MonoBehaviour,
IPointerDownHandler,
IBeginDragHandler,
IDragHandler,
IPointerUpHandler,
IEndDragHandler
{
public Transform moveThis;
private Camera theCam;
private FourLimits thingLimits;
private Vector3 prevPointWorldSpace;
private Vector3 thisPointWorldSpace;
private Vector3 realWorldTravel;
public void Awake()
{
theCam = Camera.main or whatever;
}
public void OnMarkersReady() //(would be EVENT DRIVEN for liveness)
{
thingLimits = Grid.liveMarkers. your motion limits
}
private int drawFinger;
private bool drawFingerAlreadyDown;
public void OnPointerDown (PointerEventData data)
{
Debug.Log(" P DOWN " +data.pointerId.ToString() );
}
public void OnBeginDrag (PointerEventData data)
{
Debug.Log(" BEGIN DRAG " +data.pointerId.ToString() );
if (drawFingerAlreadyDown == true)
{
Debug.Log(" IGNORE THAT DOWN! " +data.pointerId.ToString() );
return;
}
drawFinger = data.pointerId;
drawFingerAlreadyDown=true;
prevPointWorldSpace = theCam.ScreenToWorldPoint( data.position );
}
public void OnDrag (PointerEventData data)
{
Debug.Log(" ON DRAG " +data.pointerId.ToString() );
if (drawFingerAlreadyDown == false)
{
Debug.Log(" IGNORE THAT PHANTOM! " +data.pointerId.ToString() );
}
if ( drawFinger != data.pointerId )
{
Debug.Log(" IGNORE THAT DRAG! " +data.pointerId.ToString() );
return;
}
thisPointWorldSpace = theCam.ScreenToWorldPoint( data.position );
realWorldTravel = thisPointWorldSpace - prevPointWorldSpace;
_processRealWorldtravel();
prevPointWorldSpace = thisPointWorldSpace;
}
public void OnEndDrag (PointerEventData data)
{
Debug.Log(" END DRAG " +data.pointerId.ToString() );
if ( drawFinger != data.pointerId )
{
Debug.Log(" IGNORE THAT UP! " +data.pointerId.ToString() );
return;
}
drawFingerAlreadyDown = false;
}
public void OnPointerUp (PointerEventData data)
{
Debug.Log(" P UP " +data.pointerId.ToString() );
}
private void _processRealWorldtravel()
{
if ( Grid. your pause concept .Paused ) return;
//potential new position...
Vector3 pot = moveThis.position + realWorldTravel;
//almost always, squeeze to a limits box...
//(whether the live screen size, or some other box)
if (pot.x < thingLimits.left) pot.x = thingLimits.left;
if (pot.y > thingLimits.top) pot.y = thingLimits.top;
if (pot.x > thingLimits.right) pot.x = thingLimits.right;
if (pot.y < thingLimits.bottom) pot.y = thingLimits.bottom;
//kinematic ... moveThis.position = pot;
//or
//if pushing around physics bodies ... rigidbody.MovePosition(pot);
}
}
Et voici une chose à portée de main. Enregistrer en tapant avec la même chose pour les scènes en 3D, en utilisant le peu connu mais exquis
pointerCurrentRaycast
voici comment... notez l'excellente
data.pointerCurrentRaycast.worldPosition
appel de courtoisie à l'Unité.
public class FingerDrag .. for 3D scenes:MonoBehaviour,
IPointerDownHandler,
IDragHandler,
IPointerUpHandler
{
public Transform moveMe;
private Vector3 prevPointWorldSpace;
private Vector3 thisPointWorldSpace;
private Vector3 realWorldTravel;
private int drawFinger;
private bool drawFingerAlreadyDown;
public void OnPointerDown (PointerEventData data)
{
if (drawFingerAlreadyDown == true)
return;
drawFinger = data.pointerId;
drawFingerAlreadyDown=true;
prevPointWorldSpace = data.pointerCurrentRaycast.worldPosition;
//in this example we'll put it under finger control...
moveMe.GetComponent<Rigidbody>().isKinematic = false;
}
public void OnDrag (PointerEventData data)
{
if (drawFingerAlreadyDown == false)
return;
if ( drawFinger != data.pointerId )
return;
thisPointWorldSpace = data.pointerCurrentRaycast.worldPosition;
realWorldTravel = thisPointWorldSpace - prevPointWorldSpace;
_processRealWorldtravel();
prevPointWorldSpace = thisPointWorldSpace;
}
public void OnPointerUp (PointerEventData data)
{
if ( drawFinger != data.pointerId )
return;
drawFingerAlreadyDown = false;
moveMe.GetComponent<Rigidbody>().isKinematic = false;
moveMe = null;
}
private void _processRealWorldtravel()
{
Vector3 pot = moveMe.position;
pot.x += realWorldTravel.x;
pot.y += realWorldTravel.y;
moveMe.position = pot;
}
}
J'ai copié le script dans un projet de test, l'Unité 5.2.1. quand j'ai cliqué sur le Box2D il a enregistré l'OnPointerDown trucs, quand j'ai commencé à glisser connecté OnBeginDrag choses. Donc, si vous cliquez et maintenez-mais ne pas bouger, que OnPointerDown est appelé, OnBeginDrag ne le fait pas.
Salut Prog & Nikster. Oui, je comprends la différence en tant que telle, que Nika explique ... je suppose que je veux savoir à utiliser ... en fait, dans le monde réel qui est le chemin à parcourir?
je l'ai mis dans un exemple de la super-pratique pointerCurrentRaycast pour la scène 3D utiliser. Enregistrer en tapant
OriginalL'auteur Fattie | 2016-03-16
Vous devez vous connecter pour publier un commentaire.
Je veux commencer par dire que
Input
etTouches
ne sont pas de merde.Ils sont toujours utiles et ont été le meilleur moyen de vérifier latouch
sur les appareils mobiles avantOnPointerDown
etOnBeginDrag
est venu le long.OnMouseDown()
vous pouvez appeler de merde parce qu'il n'était pas optimisé pour le mobile. Pour un débutant qui vient de commencé à savoir l'Unité,Input
etTouches
sont leurs options.Quant à votre question,
OnPointerDown
etOnBeginDrag
sont PAS l'-même. Bien que ils ont presque la même chose, mais ils ont été mis en œuvre pour effectuer de différentes manières. Ci-dessous, je vais décrire la plupart de ces:OnPointerDown
:Appelé lorsqu'il existe presse/contact sur l'écran (quand il y a un clic ou le doigt appuyé sur l'écran tactile)
OnPointerUp
:Appelé lorsque la touche/touche est relâchée (lors d'un clic est libéré ou le doigt est retiré de l'écran tactile)
OnBeginDrag
:Appelé une fois avant de glisser est démarré(lorsque le doigt/la souris est déplacé pour la première temps tout en bas)
OnDrag
:À plusieurs reprises, appelé lorsque l'utilisateur est en le faisant glisser sur l'écran (lorsque le doigt/souris se déplace sur l'écran tactile)
OnEndDrag
:Appelé lors de glisser arrête lorsque le doigt/la souris est pas plus se déplaçant sur l'écran tactile).
OnPointerDown
contreOnBeginDrag
etOnEndDrag
OnPointerUp
sera PAS être appelé siOnPointerDown
n'a pas été appelé.OnEndDrag
sera PAS être appelé siOnBeginDrag
n'a pas été appelé. C'est comme l'accolades en C++,C#, vous ouvrir il {"et vous près il}'.LA DIFFÉRENCE:
OnPointerDown sera appelé une fois et immédiatement lorsque doigt/la souris est sur l'écran tactile. Rien d'autre ne se passera jusqu'à il y a un mouvement de la souris ou le doigt se déplace sur l'écran, puis
OnBeginDrag
sera appelé une fois suivie par OnDrag.Elles sont faites pour faire des avancées telles que personnalisé de l'INTERFACE utilisateur avec des contrôles qui n'est pas inclus dans l'Unité.
QUAND UTILISER CHACUN D'EUX:
1. Lorsque vous devez mettre en œuvre un simple, cliquez sur le bouton, par exemple, en Haut,en Bas, Tirer sur le Bouton de l'écran, vous seulement besoin
OnPointerDown
pour détecter le contact. Cela devrait fonctionner pour Sprite Images.2. Lorsque vous devez mettre en œuvre une coutume interrupteur à bascule et vous voulez qu'il soit réaliste de sorte que le joueur peut faire glisser vers la gauche/droite ou haut/bas pour bascule, alors vous devez
OnPointerDown
,OnBeginDrag
,OnDrag
,OnEndDrag
,OnPointerUp
. Vous devez écrire votre code dans cet ordre d'avoir un lisse Sprite/Texture de transition sur l'écran. Certains interrupteurs à bascule sont faites pour être à cliqué et il bascule. Certaines personnes préfèrent le faire paraître réaliste, en faisant en sorte que vous avez à glisser pour bascule.3. Aussi quand vous voulez mettre en œuvre Génériques réutilisables fenêtre pop-up qui est déplaçable, vous devez également utiliser ces 5 fonctions (
OnPointerDown
,OnBeginDrag
,OnDrag
,OnEndDrag
,OnPointerUp
).D'abord détecter quand il y a un clic(
OnPointerDown
), assurez-vous que le Sprite cliqué est le droit que vous souhaitez déplacer. Attendre pour le joueur de se déplacer(OnBeginDrag
) leur doigt/souris. Une fois qu'ils commencent à glisser, peut-être que vous pouvez appeler une coroutine fonction avecwhile
boucle qui va commencer à déplacer le Sprite et à l'intérieur que la coroutine, vous pouvez lisse le mouvement de l'image-objet avecTime.deltaTime
ou de toute autre méthode préférée.Depuis
OnBeginDrag
est appelée une fois, c'est un bon endroit pour commencer la coroutine.En tant que joueur de continuer à faire glisser le Sprite,
OnDrag
sera appelé à plusieurs reprises. Utiliser leOnDrag
fonction permettant d'obtenir la position actuelle de l'outil de recherche et de mise à jour qu'à uneVector3
que la coroutine est déjà en cours d'exécution sur l'utilisation de mise à jour la position du Sprite. Lorsque le joueur s'arrête déplaçant son doigt de la souris sur l'écran,OnEndDrag
est appelé et vous pouvezboolean
variable et de dire la coroutine à arrêter mise à jour la position du Sprite. Puis, lorsque le joueur communiqués de leur doigt(OnPointerUp
) vous pouvez ensuite arrêter la coroutine avec le StopCoroutine fonction.En raison de
OnBeginDrag
nous nous sommes en mesure de commencer à coroutine une fois glisser commencé lors de l'attente pour glisser à la fin. Il ne serait pas faire sens à commencer que coroutine dansOnPointerDown
parce que cela signifie que chaque fois que le joueur touche l'écran, une coroutine serait commencé.Sans
OnBeginDrag
, nous devons utiliserboolean
variable pour faire de la coroutine commencer qu'une fois dans laOnDrag
d'une fonction qui est appelée à chaque fois, sinon il serait coroutine courir partout et inattendu mouvement de l'image-objet se produire.4. Lorsque vous souhaitez afin de déterminer combien de temps le joueur a déménagé avec leur doigt. Exemple de ceci est le célèbre jeu appelé Fruit Ninja. Permet simplement de dire que vous souhaitez afin de déterminer où le joueur glisser sur l'écran.
D'abord, attendre jusqu'à
OnPointerDown
est appelé, attendre à nouveau jusqu'à ceOnBeginDrag
est appelé, alors vous pouvez obtenir la actuel position du doigt à l'intérieurOnBeginDrag
fonction carOnBeginDrag
est appelé avant que le doigt commence à se déplacer. Après le doigt,OnEndDrag
est appelé. Ensuite, vous pouvez obtenir la position actuelle du doigt encore une fois. Vous pouvez utiliser ces deux positions vérifier dans quelle mesure le doigt déplacé par soustrayant.Si vous décidez d'utiliser
OnPointerDown
comme le lieu pour obtenir le première position du doigt, vous obtiendrez un mal résultat, parce que si le joueur frottis droit, puis attend et balaye de gauche puis attend encore et balayez vers le haut sans relâcher le doigt après chaque balayage, la seule bonne résultat que vous avez est la première utilisation(de balayage à droite). Le gauche et la jusqu' glissement ont invalide valeurs, parce que la première valeur que vous avez obtenu lors de l'OnPointerDown
était appelé est la valeur que vous encore à l'aide. C'est parce que le joueur ne jamais retiré son doigt de l'écran de sorte donc,OnPointerDown
est jamais appelé nouveau et le premier ancien ancienne valeur est toujours là.Mais lorsque vous utilisez
OnBeginDrag
au lieu deOnPointerDown
, ce problème sera allé parce que lorsque le doigt arrête de bouger,OnEndDrag
est appelé et quand il commence à se déplacer à nouveauOnBeginDrag
est appelé une fois de plus l'origine de la première position être écrasé avec le nouveau.J'ai réalisé que ma question était un peu rêveuse, j'ai donc fermé! le point soulevé ici par @Programmeur ... "OnEndDrag ne sera PAS appelé si OnBeginDrag n'a pas été appelé. Ses comme les accolades..." etc., semble être la critique de perspicacité dans cette assurance de la qualité. Merci à tous !
Pas de problème Joe. Heureux que j'ai été capable de les aider.
mec @programmeur comment êtes-vous. J'ai pensé, quelle est la MEILLEURE FAÇON, ces derniers temps, si vous voulez tout simplement pour détecter une touche (par exemple, balayez) n'importe où sur l'écran? C'est incroyable de voir quelque chose de si de base est tellement vague dans l'Unité. Quel est votre avis?
Ce que je veux dire, j'ai l'habitude d'ajouter un vide collider (juste une boîte plate) en vertu de la caméra (c'est à dire qui se déplace autour de la caméra), pour détecter les touches sur l'écran de l'appareil. Je veux dire dans un jeu en 3D où la caméra est en mouvement. Il semble peu élégante.
OriginalL'auteur Programmer
La différence est que
OnBeginDrag
n'est pas appelée jusqu'à ce que le tactile/souris a déplacé une certaine distance minimum, faites glisser le seuil. Vous pouvez définir le glisser seuil sur le Système d'Événements de composant.Ce qui est nécessaire quand vous avez une hiérarchie d'objets avec différentes façons de traiter l'entrée, en particulier scrollviews. Imaginez que vous avez un scrollview avec une pile verticale de cellules, chacune avec un bouton. Lorsque la touche démarre pour la première fois sur l'un des boutons, nous ne savons pas si l'utilisateur en appuyant sur un bouton ou en faisant glisser le scrollview. Il n'est pas jusqu'à ce que la touche entraîne pour le glisser seuil que nous savons qu'il est un boulet et pas d'un robinet.
OriginalL'auteur Matt Rix