Casi cualquier juego requiere inteligencia artificial (IA) que interactúa con el usuario, la mayoría de las veces en forma de una fuerza hostil para el jugador. En algunos casos, la IA debería ayudar al jugador, en otros debería combatirlo, pero todos los personajes controlados por la computadora tienen algunas similitudes. Dependiendo de los requisitos del proyecto, la IA puede usar comportamientos simples o complejos. Dichos requisitos pueden ser diplomacia con otro jugador o un simple vagar por la plataforma. Sea como fuere, es necesario asegurarse de que la IA haga su trabajo de manera eficiente.
En este proyecto, demostraré una inteligencia artificial muy simple. Supongamos que creamos un juego en el que un jugador debe colarse cerca del cuartel general enemigo. Cuando un jugador es notado por una cámara de seguridad, los enemigos se crean cerca y por un corto período de tiempo persiguen al jugador. Eso es lo que estamos implementando en el proyecto en el nivel más simple. Al finalizar el proyecto, recibirás un objeto de jugador controlado, un círculo utilizado como cámara del enemigo y un objeto del enemigo que perseguirá al jugador cuando el objeto de la cámara informa sobre su presencia.
Preparación
Primero necesitamos crear un proyecto 3D. Haga clic en el botón
Nuevo en la parte superior de la ventana después de iniciar Unity, como se muestra en la Figura 1.
Figura 1: crear un nuevo proyectoAsigne un nombre a su proyecto de
IA y asegúrese de que sea un proyecto 3D. Después de elegir un lugar en la computadora para almacenar el proyecto, haga clic en el botón
Crear proyecto en la parte inferior, que se muestra en la Figura 2.
Figura 2: pantalla de configuración del proyectoDespués de crear el proyecto, lo primero que debemos hacer es configurar las carpetas en la ventana
Activos para organizar nuestro trabajo. Haga clic derecho en la ventana
Activos y seleccione
Crear → Carpeta para crear una nueva carpeta. Nombre esta carpeta
Materiales . Luego cree una segunda carpeta y asígnele el nombre
Scripts . La Figura 3 muestra cómo debería verse.
Figura 3: crear una nueva carpetaDespués de todo esto, la ventana
Activos debería verse como la que se muestra en la Figura 4.
Figura 4: Ventana de activos .Luego, cree un piso sobre el cual se colocarán todos los objetos. En la ventana
Jerarquía , seleccione
Crear → Objeto 3D → Plano para crear un objeto plano que se utilizará como piso.
Figura 5: Creación de un objeto plano.Nombre este objeto
Floor y cambie su valor de
Escala X a 7, y el valor de
Escala Z a 3. Después de eso, la ventana del
Inspector con el objeto
Floor seleccionado debería verse como se muestra en la Figura 6.
Figura 6: Configuración de las propiedades del objeto Floor .Ahora necesitamos crear un nuevo material para
Floor para distinguirlo del resto de los objetos que se colocarán en la escena. En la carpeta
Materiales de la ventana
Activos , cree un nuevo material haciendo clic derecho en la ventana
Activos y seleccionando
Crear → Material .
Figura 7: crear nuevo materialCuando termine, nombre el material
Piso .
Figura 8: Material del piso .En la parte superior de la ventana del
Inspector con
Piso seleccionado, seleccione un selector de color.
Figura 9: elegir un selector de color.
Por supuesto, puede elegir cualquier color para el piso, pero en este ejemplo elegí rojo-marrón, como se muestra en la Figura 10.
Figura 10: selector de color.
Seleccione el objeto
Piso en la ventana
Jerarquía , y en el componente
Representador de malla , seleccione la flecha pequeña junto a
Materiales .
Figura 11: Preparación para un cambio de material.Arrastre el material del
piso desde la ventana
Activos al campo
Elemento 0 del componente
Renderizador de malla en la ventana
Inspector .
Figura 12: Definición del material del piso como el material del objeto del piso .Habiendo terminado con el objeto
Floor , necesitamos crear alrededor del área de la pared para que el jugador no pueda caerse del borde. Regrese a
Crear → Objeto 3D → Plano para crear un nuevo plano. Llamamos a este plano
Muro y lo configuramos con las mismas dimensiones que
Piso , es decir,
Escala X con un valor de 7 y
Escala Z con un valor de 3. Luego crea tres muros más, selecciona un objeto y presiona Ctrl + D tres veces. Después de eso, coloca los muros alrededor género de acuerdo con los datos de la tabla.
Titulo
| Posición X
| Posición Y
| Posición z
| Rotación x
| Rotación z
|
Pared
| -35
| 21
| 0 0
| 0 0
| -90
|
Pared (1) | -1
| 11
| -15
| 90
| 0 0
|
Pared (2)
| -1
| 11
| 13,5
| -90
| 0 0
|
Pared (3)
| 34
| 21
| 0 0
| 0 0
| 90 |
Tabla 1: Posiciones y rotaciones de todos los objetos de
Muro .
Una vez completado todo esto, debe cambiar la posición de la cámara para que mire el piso desde arriba. Seleccione el objeto de la
cámara principal y establezca la
posición Y en 30, la
posición Z en 0 y la
rotación X en 80.
Figura 13: configuración del objeto de la cámara.La escena está preparada, por lo que es hora de crear el personaje del jugador. En la ventana
Jerarquía , haga clic en
Crear → Objeto 3D → Esfera para crear un objeto de esfera. Denomine este objeto
Player y luego haga clic en el botón
Agregar componente en la parte inferior de la ventana del
Inspector .
Figura 14: agregar un nuevo componente.Ahora encuentra el
cuerpo rígido . Después de eso, seleccione el componente
Rigidbody de la lista y agregue el
Rigidbody al objeto
Player .
Figura 15: agregar un componente Rigidbody .A continuación, debe asignar una etiqueta al jugador, que luego nos será útil en el código. Haga clic en el menú desplegable
Etiqueta en la esquina superior izquierda de la ventana del
Inspector y seleccione la etiqueta
Reproductor .
Figura 16: Definición de una nueva etiqueta.Necesitamos establecer la posición del jugador para que no esté debajo del objeto
Floor . En el ejemplo, coloqué al jugador en la esquina superior izquierda con una
posición X igual a 26, una
posición Y igual a 1 y una
posición Z igual a -9.
Figura 17: colocación del jugador.Para que nuestro código futuro funcione correctamente, por supuesto, debemos adjuntarlo al objeto. Regrese a la ventana
Jerarquía y esta vez seleccione
Crear → Objeto 3D → Cubo . Llame a este cubo
Guard , agregue el componente
Rigidbody y el componente
NavMesh Agent utilizando el botón
Agregar componente en la ventana del
Inspector . Luego, colóquelo en algún lugar en la esquina superior izquierda de la escena. Después de eso, la ventana del
Inspector del objeto
Guardia se verá así:
Figura 18: Objeto protector en la ventana del Inspector .Y este objeto debe ubicarse así:
Figura 19: Colocación del objeto Guard .Finalmente, necesitamos un objeto usado como el "ojo" del objeto
Guardia , que notificará a la
Guardia que el jugador lo está tocando. Por última vez, vaya a la ventana
Jerarquía y seleccione
Crear → Objeto 3D → Esfera para crear otro objeto de esfera. Nombre este objeto
Looker . Esta vez no necesitamos agregarle ningún otro componente. Sin embargo, cambiaremos el tamaño del objeto. Después de elegir
Looker , cambie las siguientes variables del componente
Transformar en la ventana del
Inspector .
- Escala X a las 9.
- Escala Y a 0.5.
- Escala Z a las 9.
Después de eso, coloque el
Looker de manera que esté ubicado en la parte superior media del piso, como se muestra en la Figura 20.
Figura 20: Ubicación del Looker.Es el momento adecuado para darle a
Looker un material único para que pueda ver que vale la pena evitarlo. En la carpeta
Materiales de la ventana
Activos , haga clic con el botón derecho y cree un nuevo material.
Nómbralo Looker y dale un color rojo brillante. Después de eso, designe este material como el material del objeto
Looker para cambiar su color. Después de eso, la escena debería verse así:
Figura 21: Objeto de aspecto con material nuevo.Lo único que nos queda es crear una malla de navegación para la
Guardia , sobre la cual pueda moverse. Hay un menú
Ventana en la parte superior del editor de Unity. Elija
Ventana → Navegación para abrir la ventana de
Navegación que se muestra en la Figura 22.
Figura 22: Ventana de navegación .Seleccione el objeto
Piso en la
Jerarquía y luego, en la ventana
Navegación , seleccione la casilla de verificación
Estática de navegación .
Figura 23: Navegación estática .Luego, seleccione la opción
Hornear en la parte superior de la ventana.
Figura 24: Cambie al menú Hornear .Se abre el menú
Bake , en el que puede cambiar las propiedades de la malla de navegación que vamos a crear. En nuestro ejemplo, nada necesita ser cambiado. Simplemente haga clic en el botón
Hornear en la
esquina inferior derecha.
Figura 25: creación de una nueva malla de navegación.En este punto, Unity le pedirá que guarde la escena. Guárdelo, después de lo cual se creará una malla de navegación. Ahora la escena se verá así:
Figura 26: La escena actual con la malla de navegación agregada.Ahora todo en Unity está configurado, por lo que es hora de crear los scripts necesarios para que el proyecto funcione. En la ventana
Activos , haga clic con el botón derecho y seleccione
Crear → Script de C # . Nombra este script
Player . Repita esta operación dos veces más, creando scripts con los nombres
Guard y
Looker .
Figura 27: crear un nuevo script.Después de eso, la carpeta
Scripts en la ventana
Activos se verá así:
Figura 28: Carpeta de secuencias de comandos .Primero, comenzaremos a escribir el código del script
Player . Haga doble clic en la secuencia de comandos del
reproductor en la ventana
Activos para abrir Visual Studio y comenzar a crear el código.
Código
El script del
jugador es bastante simple, todo lo que hace es dejar que el usuario mueva el objeto bola. Bajo la declaración de clase, necesitamos obtener un enlace al componente
Rigidbody que creamos previamente en el proyecto.
private Rigidbody rb;
Justo después de eso, en la función
Inicio ,
ordenamos a Unity que establezca el componente
Rigidbody actual del objeto
Player en
rb .
rb = GetComponent<Rigidbody>();
Después de eso, el script del
jugador se verá así:
Figura 29: Script del jugador en este momento.Ahora que se asigna el valor
rb , debemos dejar que el objeto
Player se mueva cuando presionamos las teclas de flecha. Para mover el objeto, usaremos física, aplicando fuerza al objeto cuando el usuario presione las teclas de flecha. Para hacer esto, simplemente agregue el siguiente código a la función
Actualizar :
if (Input.GetKey(KeyCode.UpArrow)) rb.AddForce(Vector3.forward * 20); if (Input.GetKey(KeyCode.DownArrow)) rb.AddForce(Vector3.back * 20); if (Input.GetKey(KeyCode.LeftArrow)) rb.AddForce(Vector3.left * 20); if (Input.GetKey(KeyCode.RightArrow)) rb.AddForce(Vector3.right * 20);
Con esto hemos completado el script del
jugador . El guión terminado se verá así:
Figura 30: el script del jugador terminado.Guarda tu trabajo y vuelve a Unity. Esta vez, seleccione la secuencia de comandos
Guardia en la ventana
Activos . Para que el código de
Guard funcione, debe agregar la construcción de uso en la parte superior del script.
using UnityEngine.AI;
A continuación, declare las siguientes variables inmediatamente después de la declaración de clase.
public GameObject player; private NavMeshAgent navmesh;
El objeto
Player se usa como el valor de la variable
jugador del objeto
Guard . Será útil más tarde cuando le ordenemos al objeto
Guardia que persiga al jugador. Luego se
declara que la variable
navmesh recibe el componente
NavMeshAgent del objeto. Lo usaremos más tarde cuando el
Guardia comience a perseguir al jugador después de que se entere de que el jugador está tocando el objeto
Looker . En la función
Inicio , debemos establecer el valor de la variable
navmesh en el componente
NavMesh Agent del objeto:
navmesh = GetComponent<NavMeshAgent>();
Luego, en la función
Actualizar , agregamos una sola línea de código:
navmesh.destination = player.transform.position;
Esta línea establece el destino para el objeto
Guard . En nuestro caso, tomará la posición actual del objeto
Player y se moverá a este punto. Después de la operación, el objeto perseguirá constantemente al jugador. La pregunta es, ¿cómo se realiza el proceso de respuesta? No se codificará en el script
Guard , sino en el script
Looker . Antes de pasar a la secuencia de comandos Looker, mire la Figura 31 para verificar su código de secuencia de comandos
Guard .
Figura 31: el guión de Guardia terminado.Inside
Looker, nuevamente necesitamos declarar las siguientes variables:
public GameObject guard; private float reset = 5; private bool movingDown;
Después de eso, comentamos la función de
Inicio , que no necesitamos en este script. Pasemos a la función
Actualizar y agreguemos el siguiente código:
if (movingDown == false) transform.position -= new Vector3(0, 0, 0.1f); else transform.position += new Vector3(0, 0, 0.1f); if (transform.position.z > 10) movingDown = false; else if (transform.position.z < -10) movingDown = true; reset -= Time.deltaTime; if (reset < 0) { guard.GetComponent<Guard>().enabled = false; GetComponent<SphereCollider>().enabled = true; }
Aquí es donde tienen lugar las principales acciones del proyecto, así que analicemos el código. En primer lugar, dependiendo del valor de la variable booleana
movingDown , el objeto al que se adjunta este script se moverá hacia arriba o hacia abajo. Tan pronto como llegue a cierto punto, cambiará de dirección. A continuación,
Looker reducirá el valor de reinicio en función del tiempo real. Tan pronto como el temporizador sea menor que cero, tomará el guión de
Guard del objeto
Guard y lo desactivará, después de lo cual el objeto
Guard comenzará a moverse a la última posición conocida del jugador hasta este momento, y luego se detendrá.
Looker también vuelve a encender su colisionador para que todo el proceso pueda comenzar de nuevo. Ahora nuestro script se ve así:
Figura 32: Script de Looker .Hablando de colisionadores: es hora de crear un código de conflicto que restablezca el temporizador
Looker e incluya el script
Guard . En la función
Actualizar , cree el siguiente código:
private void OnCollisionEnter(Collision collision) { if (collision.gameObject.tag == "Player") { guard.GetComponent<Guard>().enabled = true; reset = 5; GetComponent<SphereCollider>().enabled = false; } }
OnCollisionEnter Unity lo reconoce automáticamente como un código de colisión y, por lo tanto, lo ejecuta cuando se produce una colisión con otro objeto. En nuestro caso, primero verifica si el objeto en colisión tiene una etiqueta
Player . Si no, ignora el resto del código. De lo contrario, activa la secuencia de comandos
Guard , establece el temporizador de
reinicio en 5 (es decir, cinco segundos) y desactiva su colisionador para que el jugador pueda moverse a través del objeto y no quedar atrapado accidentalmente en el objeto
Looker . La función se muestra en la Figura 33.
Figura 33: Código de colisión para Looker.
¡Eso es todo, el código del proyecto está listo! Puedes hacer un par de cosas más antes de terminar el proyecto. Guarde todo el trabajo y regrese a Unity.
Proyecto terminado
Para completar el proyecto, solo necesitamos adjuntar scripts a los objetos correspondientes y establecer varias variables. Primero, vaya desde la ventana de
Navegación a la ventana del
Inspector :
Figura 34: transición a la ventana del Inspector.
Después de eso, comencemos con el objeto
Player . Selecciónelo en la ventana
Jerarquía y luego, en la parte inferior de la ventana del
Inspector , haga clic en el botón
Agregar componente y agregue el script del
reproductor . Esto completa el objeto
Player .
Figura 35: Componente de script del reproductor.
A continuación, seleccione el objeto
Guardia . Como antes, adjunte la secuencia de comandos
Guard al objeto. Esta vez necesitamos decirle al
Guardián quién es el jugador. Para hacer esto, arrastre el objeto
Player de la
Jerarquía al campo
Player del componente de script
Guard , como se muestra en la Figura 36.
Figura 36: Convertir el objeto del jugador en el valor del campo del jugador .También necesitamos deshabilitar el script
Guard . En nuestro proyecto,
Guardia perseguirá al jugador después de encender su guión. Este script de
Guardia debe incluirse solo después de que el jugador toque el objeto
Looker . Todo lo que necesita hacer es desmarcar la casilla junto al texto
Guard (Script) en el componente:
Figura 37: Deshabilitar la secuencia de comandos Guard .Finalmente, pasemos al objeto
Looker y
adjuntemos el script
Looker al mismo. Esta vez, el objeto
Looker necesitará un objeto
Guard como el valor de su variable
Guard . Así como asignamos el objeto
Player a la variable
Player del script
Guard , haremos lo mismo con el objeto
Guard y el script
Looker . Arrastre la
Guardia desde la
Jerarquía al campo
Guardia de la secuencia de comandos
Looker . ¡Y el proyecto está terminado! Haga clic en el botón Reproducir en la parte superior del editor de Unity para probar su proyecto.
Figura 38: Prueba de un proyecto.Intenta mover el objeto
Player al objeto
Looker (¡recuerda que el movimiento se realiza con flechas!). Tenga en cuenta que después de esto, el objeto
Guard comenzará a perseguir al jugador. Continuará la búsqueda durante unos 5 segundos, después de lo cual se dará por vencido.
Figura 39: Un proyecto completamente completado en acción.Conclusión
Esta IA es muy simple, pero puede expandirse fácilmente. Supongamos que si imaginamos que el objeto
Looker es una cámara y el guardia mira a través de él para encontrarte, será lógico darle al objeto
Guard su propio par de ojos. El jugador puede acercarse a las cámaras, pero deben tener en cuenta los ojos del guardia. También puedes combinar este proyecto con el
concepto de encontrar el camino : dale al guardia el camino que seguirá, creando así un ambiente más interesante para el jugador.
Una IA tan simple se puede desarrollar de muchas maneras diferentes. Es posible que no desee hacer nada de lo anterior y decida hacer algo por su cuenta. Te aconsejo que experimentes, quizás tengas la idea de un proyecto interesante, que vale la pena llevar al final.