Cómo utilizar correctamente UNITY3D para crear juegos FPS
Parte 1: Introducción
En este tutorial, analizamos más de cerca cómo crear un juego de disparos en primera persona (FPS) sencillo. Introducirá algunos conceptos básicos de programación de juegos 3D y algunos consejos sobre cómo pensar como un programador de juegos.
Requisitos previos
Este tutorial asume que ya está familiarizado con las operaciones básicas del software Unity y domina los conceptos básicos de secuencias de comandos.
Crea un nuevo proyecto
Descarga el archivo comprimido FPS_Tutorial.zip, descomprímelo y abre el archivo del proyecto en Unity.
Importe el paquete de recursos Standard Assets desde el directorio de instalación de Unity.
Después de importar el proyecto, verá el contenido de estos recursos en la carpeta "Activos estándar" en el panel del proyecto de Unity. Cuando importamos nuevos recursos, lo mejor es instalarlos y agruparlos según funciones de recursos, como: cohetes, explosiones, audio, etc.
Configura el entorno del juego
Después de importar recursos, notarás que hay muchas carpetas en el panel del proyecto.
En el panel del proyecto, seleccione "mainLevelMesh" de la carpeta "Object/mainLevelMesh".
En el panel de parámetros, en las opciones de FBXImporter, encontrarás la opción "Generar Colisionadores", marca esta opción. Si no realizas este paso, el jugador en el juego cruzará el suelo y caerá directamente al abismo (en realidad activará "colisión" para generar interacción)
Arrastra y suelta "mainLevelMesh" en la escena. .
No es necesario agregar luces a la escena. Todas las escenas de este nivel ya se han aplicado con mapas de luz. Se mapeó la luz de toda la escena para todas las luces, utilizando "sombras precocidas". Los mapas de luz son de gran ayuda para mostrar efectos, especialmente en entornos de iluminación complejos.
Ahora puedes añadir un personaje a la escena.
Agregar el personaje principal
Lo siguiente agrega un objeto de personaje controlable a la escena. Unity tiene muchos controladores integrados preestablecidos para juegos de disparos en primera persona, en Activos estándar->Prefabs en el panel del proyecto.
Para agregar un controlador en primera persona, haga clic en el pequeño triángulo junto a Activos estándar en el panel del proyecto para que aparezca la lista de recursos. Busque la carpeta Prefabs, haga clic en el triángulo pequeño y aparecerá la lista de recursos. Arrastra el "Controlador en primera persona" a la escena.
En este momento, aparecerá en la escena un cilindro que representa al jugador. Tres flechas grandes representan la posición del objeto en el espacio 3D (si no ves las flechas, selecciona el objeto y presiona el botón). Tecla "W"). La superficie blanca representa la perspectiva actual del objeto. Ahora que el controlador FPS está en la posición predeterminada de la cámara, puedes cambiar la vista del juego moviéndolo. Mueve el personaje a una posición sobre el suelo del nivel del entorno del juego.
La cámara principal ahora no sirve y se puede eliminar.
Haz clic en el botón "Reproducir" y ahora deberías poder moverte por el terreno nivelado usando el mouse y el teclado (cursor o "W, A, S, D")
Ahora creamos un FSP muy simple y ahora agregamos armas al personaje.
Agregar armas
A continuación le daremos al personaje del juego un objeto parecido a una granada que puede lanzarse en el juego. Para implementar esta función, necesitas crear algún lenguaje de scripting para indicarle al arma cómo actuar en Unity.
Entonces, ¿qué queremos lograr exactamente? Queremos que el personaje del juego pueda disparar desde cualquier lugar de la cámara. Sin embargo, pensemos primero en los personajes y las armas del juego. El personaje del juego está desde una perspectiva en primera persona, por lo que la cámara está colocada paralela a los ojos. Si el jugador dispara un arma, el arma debe disparar a la posición de la mano del personaje en lugar de a la posición de los ojos.
Entonces necesitamos agregar un "objeto del juego" para representar el lanzagranadas y colocarlo donde está el arma cuando el personaje del juego la sostiene. Esto asegura que no haya problemas con la posición de disparo.
Crea un lanzagranadas
Primero, crea un "objeto de juego" para representar el lanzagranadas. Un objeto del juego es cualquier objeto (personaje, nivel, sonido) en el mundo 3D, y las partes son los atributos del objeto del juego. Por lo tanto, también necesitamos agregar partes al objeto del juego:
Selecciona GameObject>Great Vacuum en la barra de menú principal y asígnale el nombre "Lanzador" en el panel Jerarquía. Tenga en cuenta que el objeto vacío no es visible en la escena, solo se usa para colocar el lanzamisiles.
Ahora acerca la vista al controlador FPS en la escena para que podamos colocar el lanzador de armas.
Selecciona el controlador FPS en el panel de jerarquía, asegúrate de que el mouse esté en la vista de escena y presiona la tecla "F". Centra la ventana en el objeto seleccionado actualmente.
Seleccione el emisor en el panel de jerarquía y seleccione Game Objectgt en la barra de menú principal. Mover a ver. Observe cómo el emisor se acerca al controlador FPS. Luego usa el mango para mover el emisor aproximadamente a la posición de la mano del personaje.
Nota: Puedes establecer si el personaje del juego es zurdo o diestro estableciendo la posición de este objeto, sin escribir código.
Establezca el modo de ventana de Unity en modo "2by3" (windowgt; Layoutsgt; 2by3) y haga clic en el botón de reproducción (reproducir). Asegúrate de que el emisor esté seleccionado en el panel de jerarquía y mueve el personaje mientras miras en la ventana de la escena. Encontrarás que el emisor no se mueve con el personaje (ahora haz clic en el botón de reproducción nuevamente para detener la ejecución del juego)
Para resolver este problema, en el panel de jerarquía, arrastra y suelta el emisor debajo del FPS. controlador en la cámara principal. Haga clic en "Sí" en el cuadro de diálogo emergente. Ejecute el juego nuevamente y observe la ventana de la escena. El emisor se ha movido en línea con el personaje. De esta forma asociamos el transmisor con la cámara.
Crear misiles
Ahora creemos misiles que se pueden lanzar cuando el jugador hace clic en el botón de disparo.
Primero utilizamos un objeto simple, una esfera, para reemplazar el misil. Haga clic en Assetsgt;Creatgt;;Prefab en la barra de menú principal de Unity para crear un objeto prefabricado llamado "Misil"
Crear una esfera (GameObjectgt;Create Objectgt;Sphere)
Nivel en el panel , arrastre y suelte la esfera sobre el objeto prefabricado del misil (Misil), y el icono del objeto prefabricado cambiará. Puede eliminar esferas desde el panel de jerarquía.
Consejos: Todos los objetos del juego generados durante la ejecución del juego deben ser objetos prefabricados (Prefab).
Escribir un guión para un lanzador de misiles
El controlador FPS es un objeto prefabricado que contiene varios objetos y componentes del juego. El controlador FPS en sí es un cilindro que solo puede girar a lo largo del eje Y. Por lo tanto, si asignamos directamente el script del iniciador al controlador FPS, no podemos disparar hacia arriba y hacia abajo. Entonces le damos el guión a la cámara principal en el controlador que puede girar.
Ahora escribamos el primer código JavaScript que describa el comportamiento del emisor.
Haga clic en Assetsgt;Greategt;JavaScript para crear un documento JavaScript vacío. Aparecerá un recurso llamado "NewBehaviourScript" en el panel del proyecto; cámbiele el nombre a "MissileLauncher".
Consejo: haga clic en el Editor de secuencias de comandos externo a través de Unity>Preferencias para personalizar el editor de secuencias de comandos externo.
Crear una carpeta "WeaponScripts" en el panel del proyecto para colocar todos nuestros scripts de armas. Arrastre el script MissileLauncher y Missile Prefab a este archivo.
Echemos un vistazo al script JavaScript completo para el lanzamisiles.
Piensa más, ¿qué efecto queremos conseguir? Queremos detectar si el jugador presiona el botón de disparo, luego generar un misil y luego lanzarlo a cierta velocidad en la dirección hacia la que mira el jugador. Analicemos el script con cuidado:
proyectil var: Rigibody;
velocidad var=20;
función Actualización( )
{
Este es el comienzo del script, definiendo algunas propiedades y habilitando la función "Actualizar"
if(Input.GetButtonDown("Fire1"))
Primero necesitamos detectar si el jugador presionó la tecla de disparo. "Disparo 1" asigna el botón izquierdo del mouse y las teclas en el teclado configurado actualmente (se puede configurar a través de Editorgt; Configuración del proyecto; Entrada en la barra de menú principal)
{
var instanciatedProjectile: Rigidbody=Instantiate(
projectile, transform.position, transform.rotation);
Usamos variables para definir la generación objeto. El tipo de variable es Rigibody (cuerpo rígido) porque el misil tiene propiedades físicas.
La función utilizada para generar nuevos objetos en Unity es Instantiate, que tiene tres parámetros: el objeto generado, la posición en el espacio 3D del objeto generado y la rotación del objeto. También tiene otra estructura de sintaxis, consulte el manual de API, aquí solo usamos esta estructura.
El primer parámetro, proyectil, representa el objeto que queremos crear. Entonces, ¿qué se está lanzando exactamente? Los objetos específicos generados se pueden configurar manualmente. Método de implementación: defina Projectile como una variable externa de la función, para que pueda mostrarse en el panel de parámetros. Los objetos emitidos también se pueden crear mediante código, pero si desea que una variable sea ajustable, utilice el método anterior.
El segundo parámetro, transform.position, hace que el objeto generado sea consistente con la posición espacial del emisor. ¿Por qué es un transmisor? Porque si no hay problema con la ubicación donde se genera el misil, el script debe estar asociado al lanzador. (Los datos de transformación leídos por transform son los datos de transformación del objeto del juego asignado al script)
El tercer parámetro transform.rotation es similar al segundo, excepto que su valor es el mismo que el de rotación. valor del emisor de.
La siguiente parte del código pone el misil en movimiento. Para lograr movimiento, necesitamos darle una velocidad al misil, pero ¿en qué dirección (X, Y, Z) ocurre la velocidad? En la escena, haga clic en el controlador FPS y aparecerán las flechas de movimiento (si no aparecen, presione la tecla "W"). Una de las flechas es roja, una es verde y la otra es azul. El rojo representa el eje X, el verde representa el eje Y y el azul representa el eje Z. Debido a que el azul apunta en la misma dirección en la que mira el jugador, debemos darle al misil una velocidad en el eje Z.
(Velocity) La velocidad es una propiedad de instanciatedProjectile. ¿Cómo sabemos esto? Debido a que instanciatedProjectile es un tipo de cuerpo rígido, si miramos el manual de API, sabremos que la velocidad es una de las propiedades de un cuerpo rígido.
Observe también las otras propiedades de los cuerpos rígidos. Para establecer la velocidad, debemos establecer valores en cada eje. Pero hay un pequeño problema. Los objetos en el espacio 3D generalmente utilizan dos modelos de coordenadas: sistema de coordenadas local y sistema de coordenadas mundial. En el sistema de coordenadas local, el eje del objeto sólo está relacionado con el objeto mismo. En el sistema de coordenadas mundial, el eje es absoluto, por ejemplo: hacia arriba. La dirección hacia arriba es la misma para todos los objetos.
Rigidbody.VellocityLa velocidad de los objetos de cuerpo rígido debe utilizar el sistema de coordenadas mundial. Por lo tanto, al definir la velocidad, debe convertir el eje Z (dirección de avance) en el sistema de coordenadas local a la dirección correspondiente en el sistema de coordenadas mundial. Puedes utilizar la función transform.TransformDirection, que tiene tres vectores como argumentos. La velocidad variable también debe definirse como una variable externa para que el valor pueda ajustarse más tarde directamente en el editor.
Finalmente, necesitamos desactivar la colisión entre misiles y personajes del juego. Si no haces esto, el misil puede colisionar con el personaje cuando se genera. Los detalles se pueden encontrar en el manual de API en IgnoreCollision.
El código completo de MissileLauncher.js es el siguiente:
Asigna el script MissileLauncher al lanzador en el controlador FPS. Haga clic en el iniciador en el panel de jerarquía y verifique si el script MissileLauncher se muestra en el panel de parámetros.
El objeto prefabricado de misil creado anteriormente no se ha asociado con la variable proyectil en el script. Necesitamos crearlo en el editor. El proyectil variable sólo puede asociarse con un cuerpo rígido, por lo que primero debemos darle al misil un cuerpo rígido.
Haga clic en Misil en el panel del proyecto y luego seleccione Componentes>Física>Cuerpo rígido en la barra de menú principal. Esto le dará al misil que queremos disparar una propiedad de cuerpo rígido. Tenemos que asegurarnos de que el tipo de objeto que queremos emitir en el juego sea el mismo tipo de objeto que el tipo de objeto requerido por la variable externa en el script.
Crea un vínculo entre el misil y el proyectil variable en el script. Primero haga clic en el lanzador en el panel de jerarquía, luego arrastre el objeto prefabricado del misil desde el panel del proyecto y colóquelo en la sección del script MissileLauncher del panel de parámetros del lanzador.
Si ejecutas el juego, encontrarás que al hacer clic en el botón de disparo se puede emitir una pequeña bola afectada por la gravedad.
Explosión de misil
A continuación, cuando el misil choca con otros objetos, se añade un efecto de explosión. Para lograr este efecto, necesitamos escribir un nuevo script para asignar misiles.
Crea un nuevo script y llámalo Proyectil. Arrástrelo y suéltelo en la carpeta WeaponScripts del panel del proyecto.
Entonces, ¿qué efecto queremos que logre el guión Projectile? Queremos detectar si el misil choca y luego crear un efecto de explosión en el punto de colisión. El código es el siguiente:
La función del código del programa en la función OnCollisionEnter es calcular si el objeto asignado al script colisiona con otros objetos.
En la función OnCollisionEnter, principalmente queremos generar una nueva explosión en el punto donde el misil choca en el espacio 3D. Entonces, ¿dónde ocurrió la colisión? La función OnCollisionEnter tiene la función de registrar esta información. La información sobre el punto donde ocurrió la colisión se almacena en la variable ContactPoint.
Aquí usamos la función Instanciar para crear una explosión. Ya sabemos que la función instatiate tiene tres parámetros: (1) el objeto generado (2) la posición espacial 3D del objeto
(3) la rotación del objeto.
El primer parámetro, lo asignaremos a un objeto del juego con un sistema de partículas más adelante.
Al mismo tiempo, también queremos implementar esta función a través del editor, por lo que configuramos la variable como una variable externa.
El segundo parámetro, la ubicación del punto donde ocurrió la explosión, es donde ocurrió la colisión.
El tercer parámetro, la configuración de la rotación de la explosión, necesita explicación. Necesitamos que la dirección de la explosión en el eje Y sea consistente con la dirección normal de la superficie donde el misil choca con otros objetos. Esto significa que si es una pared, la explosión mirará hacia afuera, y si es un piso, mirará hacia arriba. Entonces, en realidad queremos que el eje Y del sistema de coordenadas local de la explosión sea consistente con la dirección normal a la superficie del objeto con el que choca el misil (sistema de coordenadas mundial).
Por último, queremos que el misil desaparezca del juego tras la colisión, lo cual se consigue mediante la función Destroy(), cuyo parámetro es gameObject (gameObject representa el objeto asignado a este script).
El código completo de Projectile.js es el siguiente:
Asigne el script a la casa prefabricada Missile.
A continuación vamos a crear un objeto con efecto de explosión que explota cuando el misil choca.
Primero, crea un nuevo objeto prefabricado (llamado Explosión) para almacenar los recursos del efecto de explosión.
Hay un buen objeto prefabricado de explosión en el paquete de activos estándar, con el sistema de partículas y la iluminación configurada. Arrastre y suelte la explosión prefabricada (en Activos estándar/Partículas/explosión) en el panel de jerarquía.
Ajusta los parámetros de este efecto de explosión hasta que estés satisfecho, luego arrástralo desde el panel de jerarquía y suéltalo en Explosion Prefab en el panel de proyecto.
Ahora configure la explosión del misil:
Haga clic en Missile Prefab, en la columna Variable de explosión del panel de parámetros, arrastre y suelte la explosión en el panel del proyecto.
Definir el comportamiento de la explosión
Ahora crearemos otro script para definir las características de la explosión en sí.
Cree un nuevo script: Explosión, colóquelo en la carpeta Armas, haga doble clic en el script para editarlo.
Otra función comúnmente utilizada en los scripts se llama Inicio(). El código de la función Start() solo se ejecuta una vez cuando el objeto para el que está configurado se genera en el juego. El efecto que queremos lograr es eliminar la explosión del juego después de un cierto período de tiempo. Implementamos esto a través del segundo parámetro de la función Destroy(), que se utiliza para definir el período de tiempo antes de que se realice la eliminación.
La variable explosionTime se establece como una variable externa para facilitar el ajuste.
Al insertar el código anterior en un nuevo script, elimine la función Update().
Asigna el script Explosión al objeto prefabricado de explosión.
Efectos de sonido
El mundo del juego actual es demasiado silencioso, agreguemos algunos efectos de sonido a los efectos de explosión.
Primero, agrega una pieza de audio a la casa prefabricada de explosión.
Antes de agregar efectos de sonido a la explosión, primero debemos agregar un componente de fuente de audio (Fuente de audio), haga clic en Componente—Audio—Fuente de audio en el menú principal. Verá que el componente de fuente de audio tiene un atributo de clip de audio.
Añade el efecto de sonido "RocketLauncherImpact" a la variable externa AudioClip de la casa prefabricada de explosión. Unity admite múltiples formatos de audio.
¡Ejecuta el juego y habrá un sonido al lanzar misiles!
Agregue una interfaz gráfica
Agreguemos una GUI, que es un poco como un dispositivo de visualización en la cabeza (HUD). La GUI que queremos hacer es muy simple, solo una mira.
Agregar una mira:
Crea una carpeta GUI en la barra del proyecto.
Cree un nuevo script, asígnele el nombre "Crosshair" y arrástrelo a la carpeta GUI.
Escribe el siguiente script en Crosshair:
Primero configuramos dos variables. La primera variable define la forma opcional en la que vamos a seleccionar la textura de los gráficos. La segunda variable define un intervalo cuadrado, que es el rango de posición de la textura del gráfico en la pantalla.
La función en start() se utiliza para establecer la posición de la textura de los gráficos en la pantalla. En la función, se utilizan cuatro parámetros para definir el tamaño y la posición del área cuadrada. El primer parámetro define el borde izquierdo del área cuadrada, el segundo es el borde inferior y el tercer y cuarto parámetros definen el ancho y el alto.
En la función OnGUI(), se utiliza un programa de clase GUI para mostrar gráficos en la pantalla. Los parámetros position y crosshairTexture de la función DrawTexture() harán que la cruz se muestre en el centro de la pantalla.
Guardar el guión.
Crea un nuevo objeto vacío y llámalo "GUI".
Asigne el script "Crosshair" al objeto GUI.
Haga clic en el objeto GUI, arrastre y suelte los gráficos que desea usar en la carpeta Texturelaim en la variable Crosshair Texture del panel de parámetros.
Ejecuta el juego y la mira se mostrará en la pantalla.
Efectos especiales físicos:
Ahora queremos que los objetos del juego sean lo más realistas posible, lo cual se consigue añadiendo efectos especiales físicos. En esta sección, agregaremos algunos objetos al entorno que reaccionan en consecuencia cuando son alcanzados por misiles. Primero hay algunos conceptos nuevos que explicar.
Corrección (Actualización)
Anteriormente, escribimos código en la función Update() para que el código pueda ejecutarse en cada cuadro. Un ejemplo es detectar cuando un jugador hace clic en el botón de disparo. La velocidad de fotogramas no es un valor fijo, se determina en función de factores como la complejidad de la escena. La diferencia de tiempo entre fotogramas puede provocar reacciones erráticas de los objetos. Por lo tanto, si desea agregar objetos físicamente sensibles (cuerpos rígidos, etc.) a la escena, el código debe escribirse en la función FixUpdate(). El valor deltaTime en Unity se usa para medir el tiempo que lleva renderizar dos fotogramas consecutivos.
En términos generales, la diferencia entre las funciones Actualizar y Actualización Fija es la siguiente:
Actualizar(): el código que contiene se usa generalmente para el comportamiento de los personajes, la lógica del juego, etc. El valor deltaTime en esta función no es fijo.
FixedUpdate(): el código que contiene se utiliza normalmente para objetos de cuerpo rígido (el comportamiento de las propiedades físicas). El valor de deltaTime en una función suele ser fijo.
La frecuencia con la que se llama a la función FixUpdate está determinada por la propiedad FixTimestep de Edit-Project Settings-Time en el menú principal y, por supuesto, se puede cambiar. El segundo atributo Escala de tiempo es leer la velocidad de fotogramas por segundo y el valor recíproco correspondiente.
Consejos: al definir el valor de FixedTimestep, preste atención al equilibrio: cuanto menor sea el valor, más realista será el efecto físico, pero afectará la velocidad de ejecución del juego. Se debe garantizar al mismo tiempo la velocidad del juego y la autenticidad de los efectos físicos.
Finalmente, hablemos de rendimiento, que equivale a pausar la función que se está ejecutando actualmente.
Volviendo al juego, el efecto que queremos lograr:
Permitir a los jugadores lanzar misiles (ya implementado).
Si el misil choca con otros objetos de cuerpo rígido, verifique si hay otros objetos en su clase de alcance a los que se les asignen atributos de cuerpo rígido.
Se aplica una fuerza en dirección ascendente a cada objeto rígido dentro del rango de impacto de la explosión, lo que hace que reaccionen al misil.
Echemos un vistazo al script de explosión modificado (Explosion Javascript)
Primero verifique si hay objetos con colisionadores alrededor del punto de impacto del misil. La función Physics.OverlapSphere() toma dos parámetros: una posición 3D y un valor de radio, y devuelve una matriz de colisionadores detectados dentro del radio.
Una vez obtenidos estos conjuntos, se aplica una fuerza en una dirección específica a cada cuerpo rígido correspondiente al colisionador.
Luego añadimos una fuerza (ExplosionPower) en dirección ascendente en el punto de explosión del misil. Sin embargo, el efecto de explosión disminuye con la distancia y la fuerza no puede ser la misma en todo el radio. La fuerza ejercida sobre objetos rígidos en la posición circunferencial debe ser menor que en el centro del punto de explosión. La función tiene en cuenta este efecto. Ajustando los valores de las variables externas explosionPower y explosionRadius, se puede obtener más fácilmente el efecto deseado.