Usuari/a: -- Sortir --

Nav Mesh Tutorial

Aprende a crear búsquedas de rutas de IA con los componentes de Unity NavMesh.

FASE 1: BASICS

NUEVO PROYECTO DE UNITY EN 3D (UNITY 2018.4).

ASSETS QUE VAMOS A USAR

De la carpeta Assets necessitamos:

  • Exemple01 Basics
  • NavMeshComponents
  • Exemple01 Basics.unity
  • Arrastramos a Unity estos Assets.

    Doble-Click a Exemple01 Basics.unity.

    DEFINIR LA SUPERFICIE POR DONDE PODREMOS MOVERNOS

  • En Jerarquia creamos un empty object, cambiamos el nombre a Nav Mesh y le hacemos reset al Transform.
  • Movemos el Nav Mesh arriba del todo y vamos Add Component > Nav Mesh Surface.
  • Vamos a Nav Mesh Surface y simplemente damos click a Bake y se creara la superficie donde podremos movernos.
  • Si os fijais bien el Nav Mesh considera a nuestro player como un obstaculo vamos a arreglarlo.
  • Seleccionamos el Player i vamos a Layer.
  • Le damos a add layer, creamos un layer de nombre Player y lo assignamos al Player.
  • Volvemos a Nav Mesh > Nav Mesh Surface y donde pone Included Layers quitamos la que pone Player para acabar solo hay que darle otra vez a Bake.
  • El Nav Mesh ya no considera al Player como un obstaculo.
  • Navigation

  • En Nav Mesh > Nav Mesh Surface tenemos la opcion Agent Type, si hacemos click sobre Humanoid nos saldra la Open Agent Setting hacemos click aquí.
  • Nos saldra la ventana Navigation des de la que podremos modificar el NavMesh.
  • Muros

  • Los muros no deberian ser una superficie por la que puedas moverte vamos a cambiar el Nav Mesh para que tampoco tenga en cuenta los muros.
  • Vamos a Jerarquia seleccionamos Level > Walls > Add Component > Nav Mesh Modifier.
  • Seleccionamos la opcion Override Area i nos saldra la opcion Area Type, aquí cambiamos Walkable por Not Walkable.
  • Resultado si le damos a Bake veremos como la superficie de los muros ya no estan en azul.
  • Moviendo al Jugador

  • Añadimos la componente Nav Mesh Agent al Player.
  • Creamos el Script que controlara al Player le podemos decir PlayerController, tambe podem crear una carpeta un guardar tots els Scripts y le damos doble-click.
  • Per començar eliminem Start() y en Update() miraremos cuando el jugador pulse el boton izquierdo del raton fent servir la classe Input y la funcio GetMousseButtonDown(0).
  • Queremos disparar un rayo a la posicion donde este el raton para necessitamos saber la posicion actual del raton. Input.moussePosition es la posicion actual del raton en la pantalla.
  • Necessitamos una funcion para convertir la posicion en un rayo que dispararemos. La Camara de Unity tiene la funcion que necessitamos por eso vamos arriba del Update y creamos una referencia a la Camara:
  • Ahora podemos usar la función ScreenPointToRay() la traemos de la siguiente manera:
  • Guardamos toda la linea un una variable de tipo Ray.
  • Queremos una variable que guarde informacion sobre la posicion donde dispararemos. Para eso vamos a utilizar una variable RaycastHit.
  • Para disparar el rayo usaremos Physics.raycast(ray “nuestro rayo”, out hit donde guaramos la informacion:
  • Creamos una sentencia if y usamos el Physics.Raycast como condición. Dentro del if es donde ira el codigo para mover el agente:
  • IMPORTANTE: Siempre que trabajemos con Nav Mesh tenemos que utilizar UnityEngine.AI. Tambien podemos eliminar System.Collections no los vamos a utilizar:
  • Para mover el Agente necessitamos una referencia al NavMeshAgent en el script:
  • Ahora en el if donde vamos a mover el agente usaremos la funcion SetDestination():
  • Vamos a Unity

  • Si vamos a PlayerController ahora hay dos variables Cam y Agent. A Cam le arrastramos MainCamera. A Agent le arrastramos el NavMeshAgent. Ya podemos darle Play y si hacemos click en un punto del mapa el Player deberia buscar la ruta mas rapida hacia ese punto.
  • Podemos cambiar la velocidad de movimiento, de giro, la acceleracion y el stop:
  • FASE 2: MAKING IT DYNAMIC

    ASSETS QUE NECESSITAMOS

  • Arrastramos a unity los siguientes objetos: la carpeta Example2 – Obstacle y Example2 – Obstacle.unity.
  • Vamos a Assets Abrimos el Example2 – Obstacle.unity.
  • Vamos a Jerarquia > Nav Mesh y en el inspector le damos a Bake.
  • Vamos al Player y le añadimos el script PlayerController hay que dejarlo igual que antes.
  • OBSTACULOS

  • Vamos a Jerarquia, creamos un cubo (Click Derecho > 3D Object > Cube) y hacemos reset al transform.
  • Cambiamos la Position Y del Cubo a 1 y lo escalamos X=2 Y=1 Z=2.
  • En la Carpeta Example02 tenemos preparados unos materiales, cogemos el que se llama Obstacle y lo ponemos al cubo. Cambia el nombre del Cubo a Obstaculo.
  • Ahora el Nav Mesh ignora nuestro obstaculo el siguiente paso sera hacer que nuestro Nav Mesh se actualize durante la partida.
  • NAV MESH OBSTACLE

  • Vamos al Obstacle y le añadiremos la componente NavMeshObstacle.
  • Hay 2 formas de crear obstaculos: La primera consiste en utilizar el Obstacle Avoidance del NavMeshAgent que hemos puesto al Player.
  • La otra manera es utilizando el Carve de la componente Nav Mesh Obstacle.
  • La diferencia entre las dos maneras es que el segundo afecta al Nav Mesh y el primero no. Estos metodos son eficientes cuando tenemos pocos objetos.
  • Nivel Autogenerado

  • Vamos ha hacer que el Nivel pueda generarse solo durante la partida. Para ello necessitamos La Carpeta Example03 – Runtime y el .unity de mismo nombre.
  • Abrimos el Example03 – Runtime y veremos que solo tiene el ground, Nav Mesh y un LevelGenerator.
  • Si le damos a play el LevelGenerator creara un nivel aleatorio.
  • Esta imagen es solo un ejemplo el nivel sera aleatorio.
  • Vamos ha hacer que el Nav Mesh se genere cada vez que le damos a play. Abrimos el script LevelGenerator y veremos que hay una funcion que se encarga de generar aleatoriamente el nivel.

    Necessitamos actualizar el Nav Mesh cada vez que generamos el nivel para ello en el Start() debajo de la funcion GenerateLevel() es donde lo haremos.

  • Primero using UnityEngine.AI, Segundo una variable que hara referencia a nuestro Nav Mesh.
  • Ahora vamos al Start() y solo tenemos que hacer esto:
  • Volvemos a Unity si vamos al script LevelGenerator en Surface vamos a ponerle el objeto Nav Mesh. Ademas vamos a Nav Mesh y le damos a Bake.
  • FASE 3: Animacion de Personaje y Conectar dos Nav Mesh

    Para empezar vamos a necessitar Example04 – Links y Example04 – Links.unity los arrastramos a Assets.

  • Abrimos Example04 – Links.unity.
  • En el Player le volvemos a Assignar el PlayerController y le ponemos la camera y el Nav Mesh Agent.
  • Vamos a Nav Mesh y hacemos click en Bake se creara el Nav Mesh en las dos superficies pero estan separadas en el siguiente paso vamos a crear un link para conectar-las.
  • Conectar dos Nav Mesh

  • Creamos un empty Object, reset al transform y lo llamamos Link.
  • A Link le añadiremos la componente NavMeshLink y veremos como se crea un dibujo de 2 flechas que apuntan en direcciones opuestas.
  • Rotamos el objeto para que apunte a las dos superficies y lo subimos hasta que aparezcan los circulos al final de cada flecha.
  • Eso seria todo ahora si le damos play el player deberia poder cruzar al otro lado y al reves siempre pasara por donde esten los dos circulos.
  • Como extra si vamos a Nav Mesh Link en Unity podremos ver la opcion Width o Anchura. Si ponemos la Anchura del mismo tamaño que el espacio que separa los bloques entonces el player buscara la distancia mas cercana para cruzar al otro lado.
  • Conectar dos Nav Mesh distintos

    En el paso anterior creamos un link que conectaba dos bloques separados pero esos usaban el mismo Nav Mesh tambien se pueden conectar dos Nav Mesh diferentes.

  • Duplicamos el Nav Mesh y los llamamos Nav Mesh 01 y Nav Mesh 02.
  • Vamos a Ground01 y vamos a añadir 2 nuevos layers Ground01 y Ground02.
  • Assignamos el layer a su respectivo objeto.
  • Si vamos a NavMesh01 a Included layers quitaremos el layer Ground02 y Bake. El mateix a NavMesh02 pero al reves treurem Ground01 y Bake.
  • Esto ya esta el link deberia funcionar y el player podra moverse entre bloques.
  • Modificar al Player, darle cuerpo, animaciones... En este paso vamos a cambiar el cilindro por una figura Humanoide

  • Antes de nada vamos a necessitar la carpeta Example05 – LowMan y el .unity de mismo nombre (todo incluido en el ExamplesNavMesh.zip). Cuando lo tengamos abrimos la escena.
  • Antes de continuar vamos a: En el Player le volvemos a Assignar el PlayerController y le ponemos la camera y el Nav Mesh Agent.
  • Vamos a Nav Mesh y le damos a Bake para generar el Nav Mesh. Cambiemos la velocidad del player a 6.
  • Seleccionamos el player y quitaremos estos componentes: Cylinder, Mesh Renderer Capsule Collider.
  • En la carpeta Example05 – Lowman vamos a buscar el modelo del player que se encuentra aquí y lo arrastramos al Player:
  • Quitamos la componente Animator por ahora. Vamos a Player y en Nav Mesh Agent le pondremos el Base Offset a 0 y ya podemos ponerlo al suelo.
  • Si no teneis el transform de LowBody a 0 haced un reset.
  • Lo escalamos a 1.2 y le ponemos un material de la carpeta.
  • Animaciones del player

  • Buscamos el script ThirdPersonCharacter y lo arrastramos al Player.
  • En el Capsule Collider cambiamos la altura a 2 y la Y a 1. En Nav Mesh Agent vamos a poner la velocidad a 1.
  • En la componente Animator podemos ver que falta assigar un Controller y un avatar.
  • En la carpeta LowMan si hacemos click sobre Animation ahi tenemos el Controller solo tenemos que arrastrarlo al Animator.
  • Lo mismo con Avatar:
  • Las animaciones ya estan preparadas ahora queda usar el script ThirdPersonCharacter.
  • Vamos a abrir el script PlayerController y aquí necessitamos hacer una referencia al script ThirdPersonCharacter. Antes de nada tenemos que poner la siguiente linea de codigo “using UnityStandardAssets.Character.ThirdPerson”.
  • Creamos una variable publica ThirdPersonCharacter la llamamos character.
  • En el Start() (si no esta lo cread-lo) aquí vamos a hacer que el agent no actualize su rotación con la siguiente linea:
  • En el Update() vamos a usar la funcion character.Move() esta funcion necesita un Vector 3 que define donde queremos movernos y si el personaje tiene que agacharse o saltar.
  • Cuando el Player llega a su destino queremo que para para eso vamos a usar un if:
  • Si ahora guardamos y vamos a Unity En PlayerController tenemos el ThirdPersonCharacter.
  • Ya esta si ahora le damos a Play y nos movemos veremos las animaciones del Player.