samedi 23 juin 2018

[Unity3D][Défi50jours] Jour 5 - Déplacement sur une grille et suivi de la caméra

Journal de bord de Macmist, défi 50 jours Unity, jour 5


Aujourd'hui, ou plutôt hier soir, je me suis attaqué au déplacement d'objet sur le terrain. Il fallait que l'objet puisse suivre la souris lorsqu'elle se déplace à l'écran, mais aussi qu'il reste à des positions fixes sur une grille. Ca a été plutôt laborieux et j'ai du faire appel à toutes les ressources de l'internet, mais j'y suis finalement parvenu.

Au début, j'ai créé un script qui faisait apparaitre un cube, et j'ai essayé de lui donner comme position la position de la souris. Le problème que cela a posé est que la souris n'a pas de position en 3D, mais seulement sur le plan (x, y), dans Unity cela revient à la largeur et la hauteur. La profondeur est omise.

L'espace dans Unity

L'objet suivait donc la souris, mais se déplaçait du coup latéralement et en hauteur uniquement. Or il fallait qu'il puisse se déplacer sur les axes x et z. Il me fallut donc chercher une autre solution.

Je me suis souvenu alors d'une notion apprise durant ma formation et qui aurait pu être utile. Quelques recherches plus tard, j'ai découvert que Unity permettait de la mettre en place de manière très simple. Cette méthode est celle du Raycasting, ou lancé de rayons en français. C'est une technique qui est énormément utilisée dans le jeu vidéo pour résoudre une grande variété de problématiques, et c'est pourquoi il est naturel que Unity fournisse des fonctions déjà toute faites pour la mettre en place.

Si vous lisez ceci et ne savez pas ce qu'est le Raycasting, laissez moi vous l'expliquer brièvement. Il s'agit d'une technique de géométrie visant a déterminer le point ou l'objet le plus proche dans une direction donnée. Son principe est très simple, on "lance" un rayon (en fait une droite), à partir d'un point donné et dans une direction précise. On peut donner à se rayon une longueur maximale ou le considérer comme infini. Puis, si le rayon est arrêté par quelque chose (une surface, un objet...), on arrête le lancé et récupère la position de ce point d'intersection. Les cas d'application sont nombreux, par exemple détecter le point d'impact d'une balle de revolver lancée à toute vitesse, ou encore définir le champ de vision d'un personnage. En effet, comme on s'arrête à la première intersection, si intersection il y a, l'objet est forcément visible depuis le point d'origine du lancé.
Si l'on décidait de ne pas s'arrêter à la première intersection, mais plutôt de faire "rebondir" le rayon et le suivre ainsi dans toute ses intersections, on parlerait alors de RayTracing. C'est une autre technique, plus gourmande, mais aussi très utilisée, notamment pour calculer les ombres et les reflets de lumière avec un haut degré de réalisme.

Schéma explicatif


Ray casting en action


Image rendue par RayTracing



Après toutes ces explications comprenez sans doute comment le Raycasting pouvait être intéressant ici. Pour arriver à faire suivre la souris par l'objet, j'ai mis en place la technique suivante: lancer un rayon depuis la caméra en direction de la souris. Si il y a un point d'impact sur le terrain, déplacer l'objet à cet endroit. Et ça a marché comme sur des roulettes.
A ce moment là, l'objet suivait la souris comme je le voulais, mais je n'étais pas au bout de mes peines, car deux problèmes restaient à être résolu. Premièrement, l'objet était à moitié rentré dans le terrain, et secondement, l'objet ne devait pas pouvoir se déplacer n'importe comment, mais plutôt suivre la grille (c'est à dire avoir des positions à chiffres ronds, (1.4, 12.4, 0.789) n'est pas une position acceptable, il nous faudrait (1, 12, 1)).
Ces deux problèmes ont finalement été plutôt simples à résoudre. Pour le premier il suffit de placer l'objet de manière à ce que son point le plus bas soit pile au niveau du point le plus haut du sol. On sait où se trouve le sol, il est au point d'impact. Celui ci étant à une hauteur y, et notre objet faisant une hauteur y2, il suffit de placer l'objet à une hauteur y + y2 / 2, puisque généralement dans Unity le centre de gravité d'un objet est situé en son point central.
Pour le second problème, il suffisait d'arrondir les coordonnées x et z au nombre entier le plus proche pour pouvoir coller à la grille.


Exemple de l'objet bien positionné



Après tout ça, il me restait une ultime chose à faire afin de pouvoir clore la session et m'endormir sereinement: faire bouger la caméra en fonction de la souris.
Au moins, cette partie était très peu technique, et j'ai pu la mettre en place en très peu de temps. Pour faire simple, il suffisait d'établir une marge autour des bords de l'écran, en nombre de pixels, à partir de laquelle faire bouger la caméra si la souris entrait à l'intérieur





Voilà, ma tâche était accomplie. Et quelle satisfaction de voir tout prendre forme. Je vais maintenant pouvoir me retirer dans mes quartiers afin de prendre un repos bien mérité. A demain très cher journal.

Aucun commentaire:

Enregistrer un commentaire