Les smartphones sont de plus en plus performants et apportent dans notre poche beaucoup de choses qui étaient jusqu’à il y a quelques années seulement, réservées aux PC de bureau. Parmi cette liste de choses, nous avons bien évidemment les jeux vidéo. Ces bijoux de technologie ont un point fort que les PC n’ont pas (pour la majorité) : un écran tactile. Et on ne dirait pas comme ça, mais ça ouvre pas mal de portes en matière de gameplay mobile. Si on regardait comment ça marche avec Unity ?
Cet article est compatible avec Unity 5.3. Si vous utilisez une version différente d’Unity, il est possible que certaines choses ne fonctionnent plus de la même manière.
Le Tap, cousin du clic
La gestion du touch est aussi simple que la gestion d’un clic de souris. La gestion du touch peut être très simple, mais on peut aller très loin et c’est là que ça se complique… c’est aussi là que ça devient intéressant évidemment ! Mais avant d’aller plus loin, parlons des gestures ou gestes en français. C’est le nom que l’on donne aux différents mouvements réalisés sur un écran tactile pour effectuer une action. Depuis le temps, certains mouvements se sont imposés pour certaines actions, tout comme le clic droit sert à ouvrir les menus contextuels. En voici quelques uns par exemple :

Nous avons donc un premier niveau d’utilisation qui consiste à détecter le simple Tap. Le Tap, c’est le fait d’appuyer sur l’écran comme si vous cliquiez à la souris. Et je vous le donne en mille… dans ce cas là, le fonctionnement est exactement le même. Et quand je dis que c’est le même, ce code fonctionne sur PC et sur mobile :
private void Update() { if (Input.GetMouseButtonDown(0)) { var ms = GetComponent(typeof(MeshRenderer)) as MeshRenderer; ms.material.color = new Color(Random.value, Random.value, Random.value, 1.0f); } }
Le fait que « GetMouseButtonDown » fonctionne pour mobile est un peu déroutant, mais c’est un raccourcis qui est plus qu’utile . Créez un script avec ça dedans et attachez le à un cube visible par la caméra principale. Faites un build Android et testez par vous même. Incroyable hein ? 🙂
Les gestures
La gestion du Tap est transparente et entre nous, c’est souvent largement suffisant pour faire un jeu mobile. Mais parfois, on veut profiter un peu plus des possibilités offertes par l’écran tactile et utiliser des gestures avancées comprenant un mouvement. Pour ce qui est de la détection de ces mouvements, ça se complique un peu. En effet, Unity ne propose pas de système de détection des mouvements. C’est donc à vous de le créer en mettant en place la logique.
Détecter un Flick / Swipe
Aller on se met au boulot. Comment est-ce qu’on va détecter que le joueur fait un Swipe ? Tout d’abord il faut bien comprendre une chose. Si sur PC il n’y a qu’une souris, sur mobile… vous pouvez utiliser plusieurs doigts ! Il faut donc gérer chacun des points de contact indépendamment. Selon vos besoins, il vous faudra donc gérer le cas où l’utilisateur appuie et / ou fait des mouvements avec plusieurs doigts en même temps. Pour ne pas trop compliquer la chose, je vais restreindre l’utilisation à un seul touch simultané. Ensuite, contrairement à la souris, les touchs ont ce qu’on appelle une Phase. Une Phase correspond à l’état actuel du touch. Il peut prendre différentes valeurs :
- Began : Le touch vient tout juste d’être détecté
- Moved : le point de touch a bougé depuis la dernière boucle d’Update
- Stationary : le point n’a pas bougé depuis la dernière boucle d’Update
- Ended : le point de touch a disparu (l’utilisateur a relevé le doigt)
- Canceled : le point de touch a été annulé par le système
C’est donc via tous ces états différents que nous allons pouvoir détecter notre mouvement. Si on veut détecter un Swipe, voilà la marche à suivre pour chaque Phase :
- Began : enregistrement du point de départ du touch
- Ended : enregistrement du point de fin du touch
En C#, qu’est-ce que ça donne ?
private Vector2 _startPosition; private Vector2 _endPosition; private void Update() { if (Input.touchCount == 0) { var touch = Input.touches[0]; switch (touch.phase) { case TouchPhase.Began: // Stockage du point de départ _startPosition = touch.position; break; case TouchPhase.Ended: // Stockage du point de fin _endPosition = touch.position; break; } } }
Maintenant qu’on a les informations qui nous intéressent, on peut procéder à leur analyse et décider si la distance parcourue est suffisante. En effet, il ne faudrait pas que le joueur déclenche le Swipe alors qu’il voulait faire un Tap !
private float _swipeDistanceThreshold = 50; private float _swipeThreshold = 50; private void AnalyzeGesture(Vector2 start, Vector2 end) { // Distance if(Vector2.Distance(start, end) > _swipeDistanceThreshold) { // Le mouvement est suffisamment ample } }
Deux nouvelles variables font leur apparition : _swipeDistanceThreshold (le seuil de détection du Swipe) et _swipeThreshold (seuil de détection vertical / horizontal). En dessous de cette valeurs de distance parcourue, le mouvement ne sera pas reconnu. C’est un point important comme vu plus haut. Le seuil dépend de ce que vous voulez détecter, mais une valeur entre 50 et 100 est un bon point de départ. Maintenant que le mouvement est suffisamment ample, allons encore plus loin et détections quel Swipe on va faire. Vers le haut ? Vers le bas ? A gauche ? A droite ? Pour savoir dans quelle direction est le mouvement, il suffit de comparer les positions de départ et de fin :
// De gauche à droite ou de droite à gauche ? var leftToRight = start.x < end.x; // De bas en haut ou de haut en bas ? var bottomToUp = start.x _swipeThreshold; // C'est un swipe vertical ? var verticalSwipe = Mathf.Abs(start.y - end.y) > _swipeThreshold;
Concernant le référentiel de ces valeurs, le point 0 est en bas à gauche. X est l’axe horizontal et Y l’axe vertical. Et ce, quelle que soit l’orientation du téléphone. Il est sympa Unity quand même hein ?
Ce qui nous amène à la répartition des différentes directions de Swipe :
if (horizontalSwipe) { if(leftToRight) { SwipeLeft(); } else { SwipeRight(); } } else if(verticalSwipe) { if (bottomToUp) { SwipeUp(); } else { SwipeDown(); } }
Ca commence à vous plaire ? Maintenant vous n’avez plus qu’à créer les méthodes SwipeDIRECTION et gérer le comportement associé. Aller, je vous donne un exemple, avec notre cube qui change de couleur :
private void SwipeLeft() { SetCubeColor(Color.green); } private void SwipeRight() { SetCubeColor(Color.blue); } private void SwipeUp() { SetCubeColor(Color.yellow); } private void SwipeDown() { SetCubeColor(Color.red); } private void SetCubeColor(Color color) { var ms = GetComponent(typeof(MeshRenderer)) as MeshRenderer; ms.material.color = color; }
Et voilà le travail, vous avez maintenant un gestionnaire de Swipe. Simple, mais efficace.
Crédits photo : Luis Llerena