#12 Interacciones en Unity. Personaje-Puertas. [Laberinto en Primera Persona]

Introducción

En este artículo vamos a ver una forma de resolver las interacciones en Unity entre el jugador y objetos como la puerta o el pedestal que contiene la espada.

Para ello haremos uso del método RayCast que nos permitirá trazar rayos desde el jugador a la posición a donde está mirando y examinar contra qué chocan esos rayos.

Página principal del proyecto

Actualmente he creado una mejor versión del sistema de interacción que está basada en la que hacemos aquí.

Ver el nuevo sistema de interacción



Archivos de descarga

My first game in Unity – Video 12 Files

¿Qué vamos a hacer en este artículo?

Vamos a comenzar colocando fuego sobre las antorchas de las puertas, para ello vamos a usar uno de los prefabricados de Standard Assets.

antorcha ardiendo en unity, prefab de standard assets
Fig. 1: Vamos a hacer que las antorchas estén encendidas.

El objetivo principal es hacer que el jugador sea capaz de interactuar con las puertas y con el pedestal, esto lo resolveremos utilizando trazado de rayos y analizar contra qué chocan esos rayos.

al acercarnos a un portal en el juego en unity aparece un mensaje informando el estado
Fig. 2: Al acercarnos a la puerta nos informará si podemos irnos o aún debemos cumplir el objetivo.

al acercarnos al pedestal en el juego en unity aparece un mensaje informando que podemos interactuar
Fig. 3: Al acercarnos el pedestal nos aparece un mensaje indicando que podemos interactuar.

Importar archivos y configuración

Comenzamos descargando y extrayendo el archivo proporcionado más arriba. En la figura 4 se observan los archivos que vienen en el paquete.

assets varios para juego en unity
Fig. 4: Archivos que vienen en el ZIP.

Seleccionamos estos archivos y los llevamos arrastramos hacia la ventana de Unity.

assets varios importados en unity
Fig. 5: Llevamos los archivos extraidos a Unity.

Luego creamos todas las carpetas necesarias para organizarnos de acuerdo a nuestras necesidades.

carpetas en projecto de juego de laberinto en unity
Fig. 6: Vamos a crear una carpeta para las fuentes de texto.

Vamos a modificar el sonido de las pisadas del prefab first person controller de Standard Assets, reemplazando los sonidos con los que vienen en el paquete.

componentes de script first person controller de standard assets en el inspector de unity
Fig. 7: Seleccionamos el prefab del personaje y vamos al final del Script donde están asignados los sonidos de pisadas.

sonidos de pisadas para aplicar a control en primera persona en unity
Fig. 8: Buscamos los nuevos sonidos importados.

Los llamé de la misma forma que los sonidos de Standard Assets, pero en la figura 9 los sonidos que están aplicados son los que vienen en la descarga. Además eliminé los sonidos de salto y aterrizaje.

componentes de script first person controller de standard assets en el inspector de unity
Fig. 9: Asignamos los nuevos sonidos y eliminamos los otros dos.

Fondo para los textos

Ahora vamos a aplicar la fuente que viene en el paquete a los textos de la interfaz gráfica. Seleccionamos el GameObject Timer que tiene asignado un componente Text, en la figura 11 vemos que la fuente asignada es Arial.

jerarquia de un proyecto de juego de laberinto en unity
Fig. 10: Seleccionamos el gameobject Timer de la jerarquía, creado anteriormente.

componente texto de un gameobject en unity
Fig. 11: En el inspector vamos a modificar la fuente estándar por la que viene en el paquete.

Hacemos clic sobre el punto a la derecha de Arial para seleccionar una nueva fuente.

En mi caso voy a usar “akaPostley” que es la fuente que suelo utilizar cuando hago videillos para el canal. Pero si lo prefieren pueden buscar su propia fuente o incluso crear una personalizada.

seleccion de fuente en unity
Fig. 12: En la ventana emergente seleccionamos la fuente.

Dejo unos enlaces a páginas donde se pueden conseguir fuentes:

Da Font

1001 Fonts

Luego elegimos el color, en mi caso simplemente voy a elegir blanco.

seleccion de color en unity
Fig. 13: También elegimos un color para la fuente, en mi caso será blanco para que contraste con el fondo.

En la figura 14 vemos cómo se ve el timer con los cambios mencionados.

temporizador en unity, timer
Fig. 14: Nueva fuente y color para el temporizador.

Lo siguiente que vamos a hacer es crear un fondo para el texto del temporizador. Seleccionamos el GameObject Timer y creamos un objeto imagen.

jerarquia de un proyecto de juego de laberinto en unity
Fig. 15: Creamos una imagen para hacer el fondo del timer.

assets varios importados en unity
Fig. 16: Seleccionamos la imagen que importamos del zip.

Ubicamos la imagen de fondo que se observa en la figura 16, la seleccionamos y vamos a configurarla como una textura tipo Sprite.

configuracion de tipo de textura en unity
Fig. 17: En el inspector vamos a seleccionar como tipo de textura Sprite, para que tenga transparencia.

Con esta configuración la imagen de fondo tiene transparencia. Arrastramos la textura al campo source image de la componente imagen.

assets varios importados en unity
Fig. 18: Ahora vemos que la imagen tiene transparencia.

componente imagen de un gameobject en unity
Fig. 19: Aplicamos la textura a la imagen que usaremos de fondo del timer.

Modificamos el resto de parámetros a gusto, en la figura 20 se ve la configuración que elegí.

gameobject imagen en unity
Fig. 20: Configuramos la imagen de fondo a gusto, estos son mis valores.

En la figura 21 se observa que las letras en lugar de ser blancas se ven teñidas con el color de la imagen de fondo. Esto se debe a que la imagen se está renderizando por encima del texto.

Para solucionar este problema debemos colocar la imagen de fondo más arriba en la jerarquía, en la figura 22 se ve el orden de los GameObjects y en la figura 23 el resultado del cambio.

temporizador en unity, timer
Fig. 21: Los números no se ven blancos porque la imagen está por delante del texto.

jerarquia de un proyecto de juego de laberinto en unity
Fig. 22: Para corregir el problema vamos a la jerarquía y cambiamos de orden los GameObjects.
temporizador en unity, timer
Fig. 23: Ahora los números del Timer están por delante de la imagen de fondo.

Crear fuego para las antorchas

Hacemos doble clic sobre algún GameObject de la puerta en la jerarquía, con esto centraremos la cámara sobre una de ellas.

objeto puerta en unity
Fig. 24: Seleccionamos una de las puertas en la jerarquía.

Ubicamos el prefabricado FireMobile de Standard Assets, en la figura 25 se ve la ruta donde se encuentra.

sistemas de particulas prefabricados en unity
Fig. 25: Vamos a la carpeta Particle Systems de Standard Assets y elegimos el prefab Fire Mobile.

Tomamos el prefabricado y lo arrastramos a la jerarquía como hijo de la puerta.

objeto puerta en unity
Fig. 26: Arrastramos el prefabricado Fire Mobile y lo hacemos hijo de la puerta.

Cuando seleccionamos el prefabricado en la jerarquía podemos ver que se simula el sistema de partículas en la ventana Scene.

sistema de particulas para simular fuego en unity
Fig. 27: Así se ve el prefabricado Fire Mobile.

En la figura 28 vemos la configuración que utilicé para el sistea de partículas, básicamente disminuí un poco el tamaño.

configuracion de sistema de particulas en unity
Fig. 28: Configuramos los parámetros del sistema de partículas.

Utilizando las vistas colocamos el fuego en la punta de la antorcha.

sistema de particulas para simular fuego en unity
Fig. 29: Posicionamos el fuego sobre la antorcha usando las vistas frontal y lateral.

sistema de particulas para simular fuego en unity
Fig. 30: Posicionamos el fuego sobre la antorcha usando las vistas frontal y lateral.

Luego haremos dos copias del objeto, una para la antorcha que se encuentra en el lado derecho de la puerta y otro para la antorcha que se encuentra varios metros por encima de la puerta.

sistema de particulas para simular fuego en unity
Fig. 31: Duplicamos el fuego y lo colocamos sobre la otra antorcha.

sistema de particulas para simular fuego en unity
Fig. 32: Volvemos a duplicar el fuego y lo llevamos a la punta de la antorcha que está sobre la puerta.

El propósito de esta última antorcha es que se vea desde distintas partes del laberinto.

sistema de particulas para simular fuego en unity
Fig. 33: Esta llama será visible desde distintos puntos del laberinto.

Cuando terminamos de trabajar en la puerta aplicamos los cambios para que se extiendan a las demás puertas.

inspector de un gameobject en unity
Fig. 34: Volvemos a seleccionar el objeto puerta y aplicamos los cambios para que se extiendan a las demás puertas.

Programar comportamiento – Scripts

En esta ocasión vamos a crear tres Scripts que llamaremos: “Gate”, “Pedestal” y “UIManager”.

El Script Gate se encargará de modelar el comportamiento de la puerta, el Script Pedestal se encargará del pedestal que contiene la espada y nos permitirá removerla. Y el Script UIManager se encargará de modificar los elementos de la interfaz gráfica.

scripts c sharp en unity
Fig. 35: Creamos tres nuevos Scripts llamados Gate, Pedestal y UIManager.

Seleccionamos una puerta y le asignamos el Script Gate, luego aplicamos los cambios para las demás puertas.

asignacion de script c sharp a gameobject en unity
Fig. 36: El Script Gate lo asignamos al GameObject Gate y aplicamos los cambios.

Ubicamos el prefabricado del pedestal con la espada y lo seleccionamos.

assets varios importados en unity
Fig. 37: Seleccionamos el prefabricado del pedestal.

Asignamos el Script Pedestal a este GameObject. Si es necesario podemos bloquear la ventana inspector con el candadito que se observa en la esquina superior derecha en la figura 38. También podemos colocar el prefabricado en la jerarquía, asignarle el Script, aplicar los cambios y eliminar el GameObject de la jerarquía.

asignacion de script c sharp a gameobject en unity
Fig. 38: Al pedestal le asignamos el Script Pedestal.

Seleccionamos el GameObject Control y le asignamos el Script UIManager.

jerarquia de un proyecto de juego de laberinto en unity
Fig. 39: Seleccionamos el objeto control de la jerarquía.

asignacion de script c sharp a gameobject en unity
Fig. 40: Al objeto Control le asignamos el Script UIManager.

Completar Scripts

Vamos a comenzar adaptando lo que teníamos resuelto de la interfaz gráfica al nuevo objeto UIManager que se va a encargar de controlar lo que se muestra en pantalla.

Entramos en el Script Timer y seleccionamos los métodos que se observan en la figura 41, luego vamos al Script UIManager y los pegamos.

script c sharp en unity para resolver la interaccion del personaje con objetos
Fig. 41: Abrimos el Script Timer, seleccionamos estas instrucciones y las cortamos.

script c sharp en unity para resolver la interaccion del personaje con objetos
Fig. 42: Abrimos el Script UIManager y pegamos las instrucciones cortadas del Timer.

También nos llevamos la definición de los campos necesarios, por ejemplo timerText que es la referencia del texto del temporizador.

script c sharp en unity para resolver las interacciones en unity del personaje con objetos
Fig. 43: También nos llevamos de Timer los objetos necesarios.

script c sharp en unity para resolver las interacciones en unity del personaje con objetos
Fig. 44: Pegamos los objetos cortados de Timer e importamos el namespace UnityEngine.UI.

Cuando colocamos el campo timerText en UIManager dejamos de tener el error en el método WriteTimer.

script c sharp en unity para resolver las interacciones en unity del personaje con objetos
Fig. 45: Debemos hacer público el método WriteTimer porque lo ejecutaremos desde un contexto externo.

Ahora tenemos un error en el Script Timer porque intentamos ejecutar el método WriteTimer, el cual ya no está definido en este Script. Para resolver el problema vamos a definir un objeto tipo UIManager y encontrar la referencia en el método Start, como se observa en la figura 46.

script c sharp en unity para resolver las interacciones en unity del personaje con objetos
Fig. 46: En el Script Timer definimos un objeto tipo UIManager y encontramos la referencia en el método Start.

Luego all llamado del método WriteTimer le anteponemos la referencia del objeto UIManager y el operador punto, indicando que estamos queriendo ejecutar el método WriteTimer definido en el objeto UIManager.

script c sharp en unity para implementar temporizador
Fig. 47: Para ejecutar el método WriteTimer debemos anteponer la referencia del objeto UIManager.

No necesitamos que el Script Timer tenga el namespace UnityEngine.UI (previamente definido en la línea 4 del Script Timer, figura 48), así que eliminamos el “using UnityEngine.UI”.

script c sharp en unity para implementar temporizador
Fig. 48: Ya no se necesita el namespace UnityEngine.UI en el Script Timer. Además eliminamos los objetos innecesarios.

Cuando voy a la consola me encuentro con un error, figura 49 en rojo. Nos dice que el problema está en el Script Timer, en la línea 22.

Si observamos la figura 48 vemos que el problema está en la ejecución del método GetComponent<UIManager>, faltó abrir y cerrar paréntesis.

error en script c sharp en unity
Fig. 49: En consola aparece un error en el Script Timer.

En la figura 50 hemos resuelto el problema.

correccion de error en script c sharp en unity
Fig. 50: El problema era la ausencia de paréntesis en la ejecución del método GetComponent.

Lo siguiente que hacemos es asignar el texto del temporizador al campo TimerText en el inspector del GameObject Control.

inspector de un gameobject en unity
Fig. 51: Asignamos el texto del timer en el UIManager.

Script GameControl

Para controlar las interacciones entre el personaje y los objetos del escenario vamos a definir algunos campos y métodos en el Script GameControl que se encargarán de hacer el trazado de rayos y analizar las colisiones.

En la figura 52 vemos los nuevos campos entre el comentario “//Video 12” y el método Start.

script c sharp en unity para control un juego de laberinto y resolver las interacciones entre el personaje y los objetos del escenario
Fig. 52: Definimos estos campos en el Script GameControl

Vamos a definir el método CheckRaycast que ejecutaremos al final del método Update, como vemos en la figura 53.

script c sharp en unity para control un juego de laberinto y resolver las interacciones entre el personaje y los objetos del escenario
Fig. 53: Definimos el método CheckRaycast y lo ejecutamos en Update.

Script Pedestal

En el Script Pedestal vamos a escribir lo que se ve en la figura 54.

Definiremos un GameObject Sword para la referencia de la espada que está en el pedestal y un AudioSource para que el pedestal emita sonido cuando retiramos la espada.

Luego tenemos el método público RemoveSword que ejecutaremos cuando el personaje esté lo suficientemente cerca del pedestal, esté apuntando hacia la espada y presione la tecla E.

script c sharp en unity para controlar el pedestal en el juego del laberinto
Fig. 54: En el Script Pedestal definimos estos campos y métodos.

Seleccionamos el prefab del Pedestal y utilizando Add Component agregamos un componente AudioSource.

componente audio source de un gameobject en unity
Fig. 55: Agregamos una fuente de audio al pedestal

Ubicamos el audio “Steel” que venía dentro del paquete y lo aplicamos al componente AudioSource del pedestal, también desmarcamos la casilla “Play On Awake” y movemos el Slider “Spacial Blend” a 3D.

assets varios importados en unity
Fig. 56: Seleccionamos el sonido Steel que viene en el zip descargado.

componente audio source de un gameobject en unity
Fig. 57: Asignamos el sonido de acero en el componente AudioSource del pedestal.

Vamos a colocar el prefabricado del pedestal en la jerarquía.

jerarquia de un proyecto de juego de laberinto en unity
Fig. 58: Colocamos el pedestal en la jerarquía.

Seleccionamos el GameObject Sword que se ve en la figura 58 (puede que tenga la nombre Espada) y lo llevamos al campo “Sword” del Script Pedestal. De esta forma cuando ejecutemos el método RemoveSword, este GameObject es el que se desactivará.

inspector de un gameobject en unity
Fig. 59: Asignamos el GameObject de la espada al Script Pedestal.

Mensajes de interacciones del Jugador

Vamos al Script UIManager y definimos los campos necesarios para mostrar las posibles interacciones entre el personaje y los elementos del escenario.

Vamos a definir un GameObject que será el contenedor del mensaje, es decir cuando lo desactivemos no se mostrará en pantalla y cuando lo activemos si. Un Text que será el componente texto del mensaje.

script c sharp en unity para controlar la interfaz grafica del juego del laberinto y mostrar las interacciones entre el personaje y los objetos del escenario
Fig. 60: Definimos estos nuevos campos en el Script UIManager.

Definimos los métodos ShowMessage y ClearMessage, el primero tomará como parámetro un String que es el mensaje que se debe mostrar. El segundo no lleva parámetros y simplemente se encarga de ocultar el GameObject que contiene al mensaje.

script c sharp en unity para controlar la interfaz grafica del juego del laberinto y mostrar las interacciones entre el personaje y los objetos del escenario
Fig. 61: Definimos estos nuevos métodos en el Script UIManager.

Ahora vamos a crear el elemento de la interfaz gráfica que mostrará los mensajes de interacciones.

Comenzamos creando una imagen que actuará de fondo y luego, como hijo, un objeto texto. En la figura 62 vemos estos dos objetos llamados “MessageBackground” y “MessageText”.

jerarquia de un proyecto de juego de laberinto en unity, el mensaje muestra las posibles interacciones entre el personaje y los objetos del escenario
Fig. 62: Creamos una imagen para usar como fondo del mensaje de interacción. Luego un texto como hijo.

Configuramos todos los parámetros visuales hasta que quede como nos guste, en mi caso en la figura 63 vemos el resultado.

interfaz grafica simple del juego del laberinto en unity que muestra las interacciones entre el jugador y los objetos del escenario
Fig. 63: Configuramos todo a gusto, este fue mi resultado.

Vamos al GameObject Control y arrastramos los objetos a los nuevos campos definidos en UIManager.

el ui manager va a reflejar las interacciones entre el jugador y los objetos mostrando mensajes en pantalla
Fig. 64: Asignamos los nuevos objetos a la componente UIManager del objeto Control.

Luego me di cuenta de que es más directo serializar el componente Text en lugar del GameObject que contiene el Text, así que como se ve en la figura 65, comenté la línea en la que se define el GameObject “messageTextGameObject” y le agregué SerializeField al Text “messageText”.

script c sharp en unity para controlar la interfaz grafica del juego del laberinto
Fig. 65: Modificamos de esta forma los campos de UIManager.

Esto nos modifica los campos que se ven en el inspector, arrastramos nuevamente los objetos necesarios.

inspector de un gameobject en unity
Fig. 66: Volvemos a asignar los objetos a UIManager.

También completamos los campos nuevos del componente GameControl.

La distancia mínima de interacción será 4 metros. El mensaje de interacción que se muestra cuando miramos una puerta pero aún no tenemos la espada será:

This gate is currently locked. You have to find the sword first.”

El mensaje que nos indica que podemos interactuar dirá:

“Press E to interact.”

componente gamecontrol para controlar el juego del laberinto en unity, entre los parametros se encuentran los mensajes de las posibles interacciones entre el jugador y los objetos del escenario
Fig. 67: Completamos los campos del componente GameControl.

Resolver Raycasting

Para identificar qué objetos tenemos en frente, lo que vamos a hacer es crear un rayo desde el centro de la cámara en la dirección en la que está viendo el personaje.

Este rayo puede chocar con un objeto que tenga Collider o irse al infinito. Si resulta que choca con algún objeto, vamos a fijarnos si la distancia que hay ente el personaje y el objeto es menor a la distancia de interacción. Si esto se cumple vamos a intentar obtener del objeto una componente Gate o una componente Pedestal. Si el objeto no tiene ninguna de estas dos componentes (por ejemplo un muro o el suelo), en las variables van a estar en null.

Si en cambio la variable que contiene el objeto Gate es distinta de null, quiere decir que estamos mirando a la puerta a una distancia menor que la de interacción, por lo tanto podríamos interactuar con la puerta.

Esta es la escencia de la solución escrita en la figura 68 para el método CheckRaycast.

metodo check raycast para resolver la interaccion entre el personaje y objetos del escenario en el juego del laberinto en unity
Fig. 68: Método CheckRaycast para resolver la interacción del personaje con los objetos del escenario.

Si el personaje está mirando el pedestal a una distancia menor a la de interacción vamos a comprobar si presiona la tecla E, si esto pasa ejecutaremos el método removeSword de pedestal y pondremos en true la variable swordFound, para indicar que el personaje encontró la espada.

Como detalle final ponemos la variable swordFound en false en el método Start.

metodo start del script game control para controlar el juego del laberinto en unity y resolver las posibles interacciones entre el jugador y los objetos del escenario
Fig. 69: En el método Start hacemos la falsa la variable swordFound.

En las figuras 70 y 71 podemos ver el resultado de lo que estuvimos haciendo a lo largo de ese artículo.

interacciones que se muestran cuando el personaje se acerca a un objeto en el juego del laberinto en unity
Fig. 70: Al acercarnos a la puerta nos aparece el mensaje indicado en el componente GameControl.

interacciones que se muestran cuando el personaje se acerca a un objeto en el juego del laberinto en unity
Fig. 71: Al acercarnos al pedestal y apuntar a la espada nos aparece el mensaje de interacción que indicamos.

Conclusión

En este artículo hemos visto cómo resolver interacciones entre el personaje y ciertos elementos del escenario.

Para esto utilizamos el método RayCast de la clase Physics, que se encarga de trazar un rayo desde donde le indiquemos y en la dirección que le demos y entrega una vairbale booleana si resulta que ese rayo ha chocado contra algo.

Cuando sabemos que el rayo ha chocado contra algo, verificamos que la distancia a ese punto sea una distancia razonable en la cual el jugador pueda interactuar con un objeto.

Luego fue necesario determinar si el objeto contra el que el rayo choca es una puerta, un pedestal u otro objeto. Esto lo logramos intentando obtener las referencias de alguno de los Scripts que nos interesan y que podrían estar asignadas al objeto contra el que el rayo chocó.

Esto es una forma que se me ocurrió en la que se puede resolver las interacciones entre el jugador y distintos elementos del escenario. Me gustaría crear una solución mejor y con más posibilidades, luego de escribir este artículo he ido pensando nuevas ideas, así que posiblemente haga otros artículos sobre esto más adelante.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *