Los juegos de defensa de la torre están ganando popularidad, y esto no es sorprendente: ¡poco se puede comparar con el placer de observar sus propias líneas de defensa que destruyen a los malvados enemigos! ¡En este tutorial de dos partes, crearemos un juego de torre de defensa en el motor de
Unity !
Aprenderá a hacer lo siguiente:
- Crea oleadas de enemigos
- Haz que sigan los puntos de ruta
- Construye y mejora torres, y también enséñales cómo dividir a los enemigos en píxeles pequeños
Al final, obtenemos el marco del juego, que puede desarrollarse aún más.
Nota : necesita conocimientos básicos de Unity (por ejemplo, necesita saber cómo se agregan los activos y componentes, qué son los prefabricados) y los conceptos básicos de C # . Para aprender todo esto, le recomiendo que lea los tutoriales sobre Unity de Sean Duffy o la serie Beginning C # with Unity de Brian Mockley.
Trabajaré en Unity para OS X, pero este tutorial también es adecuado para Windows.
A través de las ventanas de la torre de marfil
En este tutorial, crearemos un juego de defensa de la torre en el que los enemigos (pequeños insectos) se arrastran hacia una galleta que te pertenece a ti y a tus secuaces (por supuesto, ¡estos son monstruos!). El jugador puede colocar monstruos en puntos estratégicos y mejorarlos para obtener oro.
El jugador debe matar a todos los errores hasta que lleguen a la cookie. Cada nueva ola de enemigos se está volviendo cada vez más difícil de vencer. El juego termina cuando sobrevives a todas las olas (¡victoria!) O cuando cinco enemigos se arrastran hacia las galletas (¡pérdida!).
Aquí hay una captura de pantalla del juego terminado:
¡Monstruos, uníos! ¡Protege la galleta!Llegar al trabajo
Descargue este
proyecto en blanco , descomprímalo y abra el proyecto
TowerDefense-Part1-Starter en Unity.
El proyecto borrador tiene recursos de gráficos y sonidos, animaciones listas para usar y varios scripts útiles. Los guiones no están directamente relacionados con los juegos de defensa de la torre, por lo que no hablaré de ellos aquí. Sin embargo, si desea obtener más información sobre la creación de animaciones 2D en Unity, consulte este
tutorial de Unity 2D .
El proyecto también contiene prefabricados, que agregaremos más adelante para crear personajes. Finalmente, hay una escena en el proyecto con un fondo y una interfaz de usuario personalizada.
Abra el
GameScene ubicado en la carpeta
Escenas y configure el modo Juego en una relación de aspecto de
4: 3 para que todas las etiquetas coincidan con el fondo correctamente. En el modo Juego, verá lo siguiente:
Autoría:- ¡Los gráficos para el proyecto están tomados del paquete gratuito Wiki Wenderlich! Otros trabajos gráficos se pueden encontrar en su sitio web gameartguppy .
- ¡ Buena música tomada de BenSound , que tiene otras bandas sonoras increíbles!
- También agradezco a Michael Jesper por la útil función de movimiento de la cámara.
.
El lugar está marcado con una cruz: la ubicación de los monstruos.
Los monstruos solo se pueden colocar en puntos marcados con una
x .
Para agregarlos a la escena, arrastre
Imágenes \ Objetos \ Openspot desde el
Navegador de proyectos a la ventana
Escena . Si bien la posición no es importante para nosotros.
Una vez que haya seleccionado
Openspot en la jerarquía, haga clic en
Agregar componente en el
Inspector y seleccione
Box Collider 2D . En la ventana Escena, Unity mostrará un colisionador rectangular con una línea verde. Utilizaremos este colisionador para reconocer los clics del mouse en esta ubicación.
Agregue el componente
Audio \ Audio Source a
Openspot de la misma manera. Para el parámetro
AudioClip del componente Fuente de audio, seleccione el archivo
tower_place ubicado en la carpeta
Audio y desactive
Play On Awake .
Necesitamos crear 11 puntos más. Aunque existe la tentación de repetir todos estos pasos, Unity tiene una mejor solución: ¡
Prefab !
Arrastre
Openspot desde la
Jerarquía a la carpeta
Prefabs dentro del
Navegador de proyectos . Su nombre se volverá azul en la Jerarquía, lo que significa que está adjunto al prefabricado. Algo como esto:
Ahora que tenemos el espacio prefabricado en blanco, podemos crear tantas copias como queramos. Simplemente arrastre y suelte
Openspot desde la carpeta
Prefabs dentro del
Navegador de proyectos en la ventana
Escena . Repita esto 11 veces y aparecerán 12 objetos Openspot en la escena.
Ahora use el
Inspector para configurar estos 12 objetos Openspot con las siguientes coordenadas:
- (X: -5.2, Y: 3.5, Z: 0)
- (X: -2.2, Y: 3.5, Z: 0)
- (X: 0.8, Y: 3.5, Z: 0)
- (X: 3.8, Y: 3.5, Z: 0)
- (X: -3.8, Y: 0.4, Z: 0)
- (X: -0.8, Y: 0.4, Z: 0)
- (X: 2.2, Y: 0.4, Z: 0)
- (X: 5.2, Y: 0.4, Z: 0)
- (X: -5.2, Y: -3.0, Z: 0)
- (X: -2.2, Y: -3.0, Z: 0)
- (X: 0.8, Y: -3.0, Z: 0)
- (X: 3.8, Y: -3.0, Z: 0)
Cuando haces esto, la escena se verá así:
Colocamos monstruos
Para simplificar la colocación, hay una prefabricada de
Monster en la carpeta
Prefab del proyecto.
Monster Prefab listo para usarPor el momento, consiste en un objeto de juego vacío con tres sprites diferentes y animaciones de disparos cuando eran niños.
Cada sprite es un monstruo con diferentes niveles de poder. El prefabricado también contiene el componente
Fuente de audio , que se lanzará para reproducir sonido cuando un monstruo dispara un láser.
Ahora crearemos un script que alojará a
Monster en
Openspot .
En el
Navegador de proyectos, seleccione el objeto
Openspot en la carpeta
Prefabs . En el
Inspector, haga clic en
Agregar componente y luego seleccione
Nuevo guión y
asigne un nombre al guión
PlaceMonster . Seleccione
C Sharp como el idioma y haga clic en
Crear y Agregar . Como agregamos el script al prefabricado de
Openspot , todos los objetos de Openspot en la escena ahora tendrán este script. Genial
Haga doble clic en el script para abrirlo en el IDE. Luego agregue dos variables:
public GameObject monsterPrefab; private GameObject monster;
Crearemos una instancia del objeto almacenado en
monsterPrefab
para crear el monstruo y lo almacenaremos en un
monster
para que pueda manipularse durante el juego.
Un monstruo por punto
Para que solo se pueda poner un monstruo en un punto, agregue el siguiente método:
private bool CanPlaceMonster() { return monster == null; }
En
CanPlaceMonster()
podemos verificar si la variable
monster
sigue siendo
null
. Si es así, entonces no hay ningún monstruo en el punto, y podemos ubicarlo.
Ahora agregue el siguiente código para colocar el monstruo cuando el jugador haga clic en este GameObject:
Este código localiza al monstruo cuando haces clic con el mouse o tocas la pantalla. Como trabaja el
- Unity llama automáticamente a
OnMouseUp
cuando un jugador toca el colisionador físico GameObject. - Cuando se llama, este método pone un monstruo si
CanPlaceMonster()
devuelve true
. - Creamos un monstruo usando el método
Instantiate
, que crea una instancia del prefabricado dado con la posición y rotación especificadas. En este caso, copiamos monsterPrefab
, le damos la posición actual de GameObject y no giramos, transferimos el resultado a GameObject
y lo GameObject
en monster
- Al final, llamamos a
PlayOneShot
para reproducir el efecto de sonido adjunto al componente AudioSource
del objeto.
Ahora nuestro script
PlaceMonster
puede tener un nuevo monstruo, pero aún necesitamos especificar un prefabricado.
Usando el prefabricado correcto
Guarde el archivo y regrese a Unity.
Para configurar la variable
monsterPrefab , primero seleccione el objeto
Openspot de la carpeta
Prefabs en el navegador del proyecto.
En el
Inspector, haga clic en el círculo a la derecha del campo
Monster Prefab del componente
PlaceMonster (Script) y seleccione
Monster en el cuadro de diálogo que aparece.
Eso es todo Inicie la escena y cree monstruos en diferentes lugares haciendo clic con el mouse o tocando la pantalla.
Genial Ahora podemos crear monstruos. Sin embargo, se ven como un desastre extraño, porque todos los niños sprites del monstruo están dibujados. Ahora lo arreglaremos.
Elevar el nivel de monstruos
La siguiente figura muestra que con un aumento en el nivel, los monstruos se ven cada vez más aterradores.
¡Qué linda! Pero si intentas robarle las galletas, este monstruo se convertirá en un asesino.El script se utiliza como base para la implementación del sistema de niveles de monstruos. Rastrea el poder del monstruo en cada nivel y, por supuesto, el nivel actual del monstruo.
Agrega este script.
Seleccione
Prefabs / Monster prefab en
Project Browser . Agregue un nuevo script de
C # llamado
MonsterData . Abra el script en el IDE y agregue el siguiente código
sobre la clase
MonsterData
.
[System.Serializable] public class MonsterLevel { public int cost; public GameObject visualization; }
Entonces creamos
MonsterLevel
. Agrupa el precio (en oro, que apoyaremos a continuación) y una representación visual del nivel del monstruo.
Agregamos encima de
[System.Serializable]
para que las instancias de clase se puedan modificar en el inspector. Esto nos permite cambiar rápidamente todos los valores de la clase Level, incluso cuando el juego se está ejecutando. Esto es increíblemente útil para equilibrar el juego.
Establecer niveles de monstruos
En nuestro caso, almacenaremos el
MonsterLevel
especificado en la
List<T>
.
¿Por qué no usar
MonsterLevel[]
? Necesitaremos el índice de un objeto
MonsterLevel
específico varias veces. Aunque es fácil escribir código para esto, todavía tenemos que usar
IndexOf()
, que implementa la funcionalidad
Lists
. No tiene sentido reinventar la rueda.
Reinventar la bicicleta suele ser una mala idea.En la parte superior de
MonsterData.cs, agregue lo siguiente
using
construct:
using System.Collections.Generic;
Nos da acceso a estructuras de datos generalizadas para que podamos usar la clase
List<T>
en el script.
Nota : las generalizaciones son un poderoso concepto de C #. Le permiten especificar estructuras de datos de tipo seguro sin tener que adherirse al tipo. Esto es útil para clases de contenedor como listas y conjuntos. Para obtener más información sobre las estructuras genéricas, lea el libro Introducción a los genéricos de C # .
Ahora agregue la siguiente variable a
MonsterData
para mantener la lista
MonsterLevel
:
public List<MonsterLevel> levels;
Gracias a las generalizaciones, podemos garantizar que la
List
del
level
solo contendrá objetos
MonsterLevel
.
Guarde el archivo y cambie a Unity para configurar cada nivel.
Seleccione
Prefabs / Monster en
Project Browser . El
Inspector ahora muestra el campo
Niveles del componente
MonsterData (Script) . Establezca el
tamaño en
3 .
A continuación, establezca el
costo para cada nivel:
- Elemento 0 : 200
- Elemento 1 : 110
- Elemento 2 : 120
Ahora asignamos los valores de los campos de visualización.
Expanda
Prefabs / Monster en el navegador de proyectos para ver sus elementos
secundarios . Arrastre el niño
Monster0 al campo
Elemento de visualización 0 .
A continuación, establezca el
Elemento 1 en
Monster1 y el
Elemento 2 en
Monster2 . El GIF muestra este proceso:
Cuando selecciona
Prefabs / Monster , el prefab debería verse así:
Establecer nivel actual
Regrese a
MonsterData.cs en el IDE y agregue otra variable a
MonsterData
.
private MonsterLevel currentLevel;
En la variable privada
currentLevel
almacenaremos el nivel actual del monstruo.
Ahora configure
currentLevel
y
currentLevel
visible para otros scripts. Agregue las siguientes líneas a
MonsterData
junto con la declaración de variables de instancia:
Bastante gran parte del código C #, ¿verdad? Tomémoslo en orden:
- Establezca la propiedad de la variable privada
currentLevel
. Al establecer la propiedad, podemos llamarla como cualquier otra variable: ya sea como CurrentLevel
(dentro de la clase) o como monster.CurrentLevel
(fuera). Podemos definir cualquier comportamiento en el método getter o setter de una propiedad, y al crear solo un getter, setter o ambos, puede controlar las propiedades de la propiedad: solo lectura, solo escritura y escritura / lectura. - En el captador, devolvemos el valor de
currentLevel
. - En el setter, asignamos a
currentLevel
nuevo valor. Luego obtenemos el índice del nivel actual. Finalmente, recorremos todos los niveles y habilitamos / deshabilitamos la visualización visual dependiendo de currentLevelIndex
. Esto es genial porque cuando currentLevel
cambia, el sprite se actualiza automáticamente. ¡Las propiedades son una cosa muy conveniente!
Agregue la siguiente implementación de
OnEnable
:
void OnEnable() { CurrentLevel = levels[0]; }
Aquí establecemos
CurrentLevel
al colocar. Esto asegura que solo se muestre el sprite deseado.
Nota : es importante inicializar la propiedad en OnEnable
, y no en OnStart
, porque llamamos a los métodos ordinales al crear instancias prefabricadas.
OnEnable
se llamará inmediatamente cuando se OnEnable
(si el prefab se guardó en el estado habilitado), pero no se llama a OnStart
hasta que el objeto comience a ejecutarse como parte de la escena.
Necesitamos verificar estos datos antes de colocar el monstruo, por lo que lo inicializamos en OnEnable
.
Guarde el archivo y regrese a Unity. Ejecute el proyecto y coloque los monstruos; ahora muestran los sprites correctos del nivel más bajo.
Actualización de monstruo
Regrese al IDE y agregue el siguiente método a
MonsterData
:
public MonsterLevel GetNextLevel() { int currentLevelIndex = levels.IndexOf (currentLevel); int maxLevelIndex = levels.Count - 1; if (currentLevelIndex < maxLevelIndex) { return levels[currentLevelIndex+1]; } else { return null; } }
En
GetNextLevel
obtenemos el índice
currentLevel
y el índice de nivel más alto; Si el monstruo no ha alcanzado el nivel máximo, el siguiente nivel regresa. De lo contrario,
null
devuelve
null
.
Puede usar este método para averiguar si es posible una actualización monstruosa.
Para elevar el nivel del monstruo, agregue el siguiente método:
public void IncreaseLevel() { int currentLevelIndex = levels.IndexOf(currentLevel); if (currentLevelIndex < levels.Count - 1) { CurrentLevel = levels[currentLevelIndex + 1]; } }
Aquí obtenemos el índice del nivel actual, y luego nos aseguramos de que este no sea el nivel máximo, verificando que sea inferior a los
levels.Count - 1
. Si es así,
CurrentLevel
al siguiente nivel.
Comprobación de la funcionalidad de actualización
Guarde el archivo y regrese a
PlaceMonster.cs en el IDE. Agrega un nuevo método:
private bool CanUpgradeMonster() { if (monster != null) { MonsterData monsterData = monster.GetComponent<MonsterData>(); MonsterLevel nextLevel = monsterData.GetNextLevel(); if (nextLevel != null) { return true; } } return false; }
Primero verificamos si hay un monstruo que pueda mejorarse comparando la variable del
monster
con
null
. Si esto es cierto, obtenemos el nivel de monstruo actual de su
MonsterData
.
Luego verificamos si el siguiente nivel está disponible, es decir, si
GetNextLevel()
no devuelve
null
. Si es posible un aumento de nivel, entonces devolvemos
true
; de lo contrario, devuelve
false
.
Implementamos mejoras para el oro.
Para habilitar la opción de actualización, agregue el
else if
OnMouseUp
a
OnMouseUp
:
if (CanPlaceMonster()) {
Verificamos la posibilidad de una actualización usando
CanUpgradeMonster()
. Si es posible, accedemos al componente
MonsterData
usando
GetComponent()
y llamamos a
IncreaseLevel()
, que aumenta el nivel del monstruo. Finalmente, lanzamos Monster
AudioSource .
Guarde el archivo y regrese a Unity. Ejecuta el juego, coloca y actualiza
cualquier cantidad de monstruos (pero por ahora).
Paying Gold - Game Manager
Si bien podemos construir y mejorar de inmediato cualquier monstruo, ¿será interesante en el juego?
Veamos el tema del oro. El problema con el seguimiento es que tenemos que transferir información entre diferentes objetos del juego.
La siguiente figura muestra todos los objetos que deberían participar en esto.
Todos los objetos de juego seleccionados deben saber cuánto oro tiene un jugador.Para almacenar estos datos, utilizaremos un objeto común al que pueden acceder otros objetos.
Haga clic derecho en la
Jerarquía y seleccione
Crear vacío . Nombra el nuevo objeto
GameManager .
Agregue un nuevo script
C # llamado
GameManagerBehavior a GameManager , y luego ábralo en el IDE. Mostraremos la cantidad total de oro del jugador en la etiqueta, por lo que en la parte superior del archivo agregue la siguiente línea:
using UnityEngine.UI;
Esto nos permitirá acceder a clases de IU como
Text
, que se usa para etiquetas. Ahora agregue la siguiente variable a la clase:
public Text goldLabel;
Almacenará un enlace al componente de
Text
utilizado para mostrar la cantidad de oro que tiene un jugador.
Ahora que
GameManager
conoce la etiqueta, ¿cómo sincronizamos la cantidad de oro almacenada en la variable y el valor que se muestra en la etiqueta? Crearemos una propiedad.
Agregue el siguiente código a
GameManagerBehavior
:
private int gold; public int Gold { get { return gold; } set { gold = value; goldLabel.GetComponent<Text>().text = "GOLD: " + gold; } }
¿Te parece familiar? El código es similar a
CurrentLevel
, que configuramos en
Monster
. Primero creamos un
gold
variable privado para contener la cantidad actual de oro. Luego establecemos la propiedad
Gold
(inesperadamente, ¿verdad?) E implementamos el getter y setter.
El captador simplemente devuelve el valor del
gold
. El setter es más interesante. Además de establecer el valor de la variable, también establece el campo de
text
para que
goldLabel
muestre el nuevo valor de oro.
¿Cuán generosos seremos? Agregue la siguiente línea a
Start()
para darle al jugador
1000 de oro, o menos si siente pena por el dinero:
Gold = 1000;
Asignación de un objeto de etiqueta a un script
Guarde el archivo y regrese a Unity. En la
Jerarquía, seleccione
GameManager . En el
Inspector, haga clic en el círculo a la derecha de la
etiqueta dorada . En el cuadro de diálogo
Seleccionar texto , seleccione la pestaña
Escena y seleccione
GoldLabel .
Ejecute la escena y la etiqueta mostrará
Gold: 1000 .
Comprobando la "billetera" del jugador
Abra el script
PlaceMonster.cs en el IDE y agregue la siguiente variable de instancia:
private GameManagerBehavior gameManager;
Utilizaremos
gameManager
para acceder al componente
GameManagerBehavior
objeto
GameManagerBehavior
en la escena. Para especificarlo, agregue lo siguiente a
Start()
:
gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
Obtenemos un GameObject llamado GameManager usando la función
GameObject.Find()
, que devuelve el primer objeto del juego encontrado con ese nombre. Luego obtenemos su componente
GameManagerBehavior
y lo
GameManagerBehavior
para el futuro.
Nota : puede hacer esto configurando un campo en el editor de Unity o agregando un método estático a GameManager
que devuelva una instancia del singleton del que podemos obtener GameManagerBehavior
.
Sin embargo, en el bloque de código que se muestra arriba hay un caballo oscuro: el método Find
, que funciona más lentamente durante la ejecución de la aplicación; pero es conveniente y se puede usar con moderación.
Toma mi dinero!
Todavía no hemos restado el oro, por lo que agregaremos esta línea
dos veces a
OnMouseUp()
, reemplazando cada uno de los comentarios
// TODO:
:
gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;
Guarde el archivo y regrese a Unity, actualice algunos monstruos y mire la actualización del valor Gold. Ahora deducimos oro, pero los jugadores pueden construir monstruos siempre que tengan suficiente espacio; solo piden prestado dinero.
Crédito infinito? Genial Pero no podemos permitirlo. El jugador debe poder apostar monstruos mientras tenga suficiente oro.Cheque de oro para monstruos
Cambie el IDE a
PlaceMonster.cs y reemplace el contenido de
CanPlaceMonster()
siguiente:
int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost; return monster == null && gameManager.Gold >= cost;
Obtenemos
MonsterData
precio de colocación de monstruos de los
levels
en su
MonsterData
. Luego verificamos que el
monster
no
monster
null
, y que
gameManager.Gold
más que este precio.
La tarea para usted: agregar independientemente a
CanUpgradeMonster()
cheque si el jugador tiene suficiente oro.
Solución en el interiorReemplace la línea:
return true;
en esto:
return gameManager.Gold >= nextLevel.cost;
Verificará si el jugador tiene más
Oro que el precio de actualización.
Guarda y ejecuta la escena en Unity. ¡Ahora prueba cómo agregar monstruos ilimitadamente!
Ahora solo podemos construir un número limitado de monstruos.Política de la torre: enemigos, olas y puntos de referencia
Es hora de "allanar el camino" a nuestros enemigos. Los enemigos aparecen en el primer punto de la ruta, se mueven al siguiente y repiten el proceso hasta que alcanzan la cookie.
Puedes hacer que los enemigos se muevan así:
- Establece el camino que seguirán los enemigos
- Mueve al enemigo por el camino
- Gira al enemigo para que mire hacia adelante
Creando un camino desde waypoints
Haga clic derecho en la
Jerarquía y seleccione
Crear vacío para crear un nuevo objeto de juego vacío. Nómbrelo
Road y colóquelo en
(0, 0, 0) .
Ahora haz clic derecho en
Road en la
Jerarquía y crea otro objeto de juego vacío como hijo de Road. Nómbralo
Waypoint0 y
colócalo en el punto
(-12, 2, 0) : desde aquí, los enemigos comenzarán su movimiento.
Del mismo modo, cree cinco puntos de ruta más con los siguientes nombres y posiciones:
- Waypoint1: (X: 7, Y: 2, Z: 0)
- Waypoint2: (X: 7, Y: -1, Z: 0)
- Waypoint3: (X: -7.3, Y: -1, Z: 0)
- Waypoint4: (X: -7.3, Y: -4.5, Z: 0)
- Waypoint5: (X: 7, Y: -4.5, Z: 0)
La captura de pantalla siguiente muestra los puntos de ruta y la ruta resultante.
Haciendo enemigos
Ahora crea algunos enemigos para que puedan moverse por el camino. Hay un
prefab Enemigo en la carpeta
Prefabs . Su posición es
(-20, 0, 0) , por lo que se crearán nuevas instancias fuera de la pantalla.
En todos los demás aspectos, está configurado casi de la misma manera que el monstruo prefabricado, tiene
AudioSource
y un niño
Sprite
, y podemos rotar este sprite en el futuro sin girar la barra de salud.
Movemos enemigos por el camino
Agregue un nuevo script de
C # llamado
MoveEnemy al
prefabricado Prefabs \ Enemy . Abra el script en el IDE y agregue las siguientes variables:
[HideInInspector] public GameObject[] waypoints; private int currentWaypoint = 0; private float lastWaypointSwitchTime; public float speed = 1.0f;
En los
waypoints
, una copia de los
waypoints
se almacena en la matriz, y la línea
[HideIn inspector ]
encima de los
waypoints
asegura que no podemos cambiar accidentalmente este campo en el
Inspector , pero aún tendremos acceso a él desde otros scripts.
currentWaypoint
realiza un seguimiento de dónde proviene la ruta del enemigo en el momento actual, y
lastWaypointSwitchTime
almacena el tiempo que el enemigo pasó por ella. Además, almacenamos la
speed
enemigo.
Agregue esta línea a
Start()
:
lastWaypointSwitchTime = Time.time;
Entonces inicializamos
lastWaypointSwitchTime
con el valor de la hora actual.
Para que el enemigo se mueva a lo largo de la ruta, agrega el siguiente código a
Update()
:
Analicemos el código paso a paso:
- Del conjunto de puntos de ruta obtenemos las posiciones de inicio y finalización del segmento de ruta actual.
- Calculamos el tiempo requerido para cubrir toda la distancia usando la fórmula tiempo = distancia / velocidad , y luego determinamos el tiempo actual en la ruta. Usando
Vector2.Lerp
, interpolamos la posición actual del enemigo entre el segmento exacto inicial y final. - Comprueba si el enemigo ha llegado al
endPosition
. En caso afirmativo, procesamos dos escenarios posibles:
- El enemigo aún no ha alcanzado el último punto de la ruta, así que aumente el valor de
currentWaypoint
y actualice lastWaypointSwitchTime
. Más tarde agregaremos un código para convertir al enemigo para que mire en la dirección de su movimiento. - El enemigo ha llegado al último punto de la ruta, luego lo destruimos y comenzamos el efecto de sonido. Más adelante agregaremos un código que reduce la
health
del jugador.
Guarde el archivo y regrese a Unity.
Informamos a los enemigos de la dirección del movimiento.
En su estado actual, los enemigos no conocen el orden de los puntos de ruta.
Seleccione
Road en la
Jerarquía y agregue un nuevo script de
C # llamado
SpawnEnemy . Ábralo en el IDE y agregue la siguiente variable:
public GameObject[] waypoints;
Utilizaremos
waypoints
para almacenar referencias al waypoint en la escena en el orden deseado.
Guarde el archivo y regrese a Unity. Seleccione
Carretera en la
Jerarquía y establezca el
Tamaño de la matriz de
Waypoints en
6 .
Arrastre cada uno de los elementos secundarios de Road a los campos pegando
Waypoint0 en el
Elemento 0 ,
Waypoint1 en el
Elemento 1, y así sucesivamente.
Ahora tenemos una matriz que contiene los puntos de ruta en el orden correcto: ten en cuenta que los enemigos nunca retroceden, se esfuerzan persistentemente por una dulce recompensa.
Mira cómo funciona todo
Abra
SpawnEnemy en el IDE y agregue la siguiente variable:
public GameObject testEnemyPrefab;
Almacenará una referencia al
testEnemyPrefab
enemigo en
testEnemyPrefab
.
Para crear un enemigo al ejecutar el script, agregue el siguiente código a
Start()
:
Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;
Entonces crearemos una nueva copia del
testEnemy
almacenado en
testEnemy
y le asignaremos una ruta.
Guarde el archivo y regrese a Unity. Seleccione el objeto
Road en la
Jerarquía y seleccione el prefabricado
Enemigo para el parámetro
Test Enemy .
Inicie el proyecto y vea cómo se mueve el enemigo a lo largo del camino (en GIF, para mayor claridad, la velocidad aumenta en 20 veces).¿Notó que no siempre mira a dónde va? Es divertido, pero estamos tratando de hacer un juego profesional. Por lo tanto, en la segunda parte del tutorial, enseñaremos a los enemigos a mirar hacia adelante.¿A dónde ir después?
Ya hemos hecho mucho y estamos avanzando rápidamente hacia la creación de nuestro propio juego de defensa de la torre.Los jugadores pueden crear un número limitado de monstruos, y el enemigo corre a lo largo del camino, en dirección a nuestra galleta. Los jugadores tienen oro y pueden actualizar monstruos.Descargue el resultado final desde aquí .En la segunda parte, consideraremos la creación de enormes oleadas de enemigos y su destrucción. Hasta pronto!