Premiers pas avec Unity3D : Navigation (I)


Dans ce TP nous explorerons un mécanisme de base de la navigation qui semble donner une certaine "intelligence" aux "non players" : ils se déplacent en évitant automatiquement les obstacles. Notons au passage que ce mécanisme s'applique aussi aux mobiles manipulés par le joueur et facilite la tâche des déplacements.

L'objectif du TP est de modéliser un "agent" se deplaçant automatiquement vers une destination (donnée à la souris) en empruntant le plus court chemin à travers un environnement couvert d'obstacles. Le résultat peut ressembler au jeu ci-contre : MoveAgent (the Game)

De nombreuses vidéos présentent les NavMesh :
La vidéo de  Brackeys est claire et précise (11 min) mais concerne la version 2017 de Unity, elle explique comment exclure certaines zones à l'aide de NavMesh Modifier,
La vidéo suivante est plus récente (2018) traite des mêmes sujets mais aussi un peu plus longue (15min) : Sykoo.

Quelques ressources sont mises à disposition dans le fichier suivant qu'il faudra dezipper : ressources_TP2.zip. Textures et scripts C# peuvent être directement copiés sous Unity en faisant un Drag & Drop dans les ASSETS (fenêtre en bas au centre).

Open a door. <
    Navigation (I) : introduction au NavMesh >
L'interface de Unity.


Principe

Le problème posé est le suivant :
Déplacer un mobile automatiquement d'un point de départ quelconque à un point de Destination tout en évitant les obstacles et en choississant le chemin le plus court.

La résolution de problème ne nécessite pas d'IA (Intelligence Artificielle) mais relève de l'Algorithmique Géométrique (Computational Geometry). Il est traité en 3 étapes :
  1. Le premier algorithme remplace le mobile par un point de référence et calcule la zone bleu clair (accessible au point de référence) en dilatant les obstacles (de la taille du mobile). C'est la somme de Minkowski (vidéo), 
  2. La décomposition de la zone bleue (polygone) permet de construire un graphe dans lequel on recherche le plus court chemin (entre départ et destination),
  3. Enfin le moteur physique permet d'animer le mobile suivant le chemin calculé.

Les obstacles et la surface de déplacement

Dans la scene, nous allons définir une hierarchie "terrain" composée d'un plan et d'obstacles auquel nous allons associer un espace de navigation : le "NavMesh".

Construisez un Empty GameObject nommé "terrain" qui contient la surface  de déplacement "Plane" et des obstacles que l'on a appelé "wall_x".
Ajoutez un MeshRenderer au "terrain" car le composant est nécessaire pour le calcul de l'espace accessible.

Activez la fenêtre Navigation (à droite sur la figure ci-contre) à l'aide du menu :
 Windows / Navigation
Sélectionnez le Mesh Renderer de "terrain" (dont fils sont automatiquement selectionnés) puis activez la Navigation Static et fixez la Navigation Area à  Walkable.

Espace accessible

Nous allons calculer l'espace accessible (par un agent) sur le "terrain".

Pour définir les caractéristiques de l'agent (son encombrement entre autre) passer sur de l'onglet Object à l'onglet Bake (en haut à droite). Et pour lancer le calcul cliquez en bas à droite sur la touche Bake.

Une zone s'affiche en bleu : c'est le polygone correspondant à la surface accessible par un agent dont les caractériques par défaut sont :
  
Agent Radius =0.5
Agent Height = 2
Max Slope = 45° 
Step Height = 0.4

Modifiez les valeurs de ces paramètres (entre autre le Radius) et observez l'évolution de la zone bleue. Notez que le "movingAgent" n'est pas un obstacle (ce n'est pas un élément de terrain).

Déplacement de l'agent

L'agent se déplace par le plus court chemin à une certaine vitesse jusqu'à une destination à définir. Il reste sur l'espace accessible (en bleu). Il faut lui donner une destination (à l'aide d'un script en C# par exemple) et des caractéristiques de déplacement : vitesse, accélération... C'est le role du composant NavMesh Agent.

Ajoutez un composant NavMesh Agent au "movingAgent". Avant de tester il faut définir la destination. Pour ce faire nous utiliserons le script C# "MoveToTarget.cs" que nous ajouterons aux composants de l'agent  (ressources_TP2.zip). Analysez le script et devinez son résultat.

Passez en mode Game et tester l'ensemble.
Modifiez les valeurs des paramètres du NavMesh Agent pour obtenir une dynamique acceptable.

Plusieurs agents en mouvement


Multiplier le nombre d'agents permet d'avoir des dynamiques intéressantes et de comprendre certains paramètres de navigation.

Dupliquez 2 fois simplement le "moving Agent" et réglez la Stopping Distance des NavMeshAgent.
Changez les vitesses de déplacement des agents, un plus rapide, un plus lent...

Passez en mode Game et tester l'ensemble.

Réflexion et prospection 
Changez les rayons des agents dans l'Inspector  (Composant : Transform / Scale). Discutez du résultat (en mode Game)

 

Ajouter des portes

L'ajout de porte -si elles peuvent s'ouvrir- ne change pas l'espace de navigation mais ajoute de la dynamique au jeu...

Reprennez les portes du TP 1 (part II) et placez les dans le labyrinthe. Elles doivent être dans un niveau différent (ou hors de la hierarchie "terrain") pour ne pas être considérées comme des obstacles.

Certaines portes peuvent être verrouilées...
part II

Modifiez la destination


Les agents doivent atteindre une destination fixée en début de partie : le drapeau.

Dupliquez et adaptez le script C# : MoveToTarget.cs

Multipliez les drapeaux et modifiez les règles : chaque agent doit atteindre le drapeau qui est la plus proche de lui.



part II

Un début de jeu


Les agents collectent des trésors ; doivent atteindre des destinations fixées par la position des trésors. Une fois collecté le trésors disparait et l'agent se dirige sur un autre trésors.

Un agent représente le joueur (en rouge) il suit la souris et doit collecter les trésors AVANT les agents (en vert). Il posède une clef qui permet de vérouiller les portes.

D'autres agents essayent d'atteindre le joueur pour le tuer.
part II