[Unity Mini Game] Caso de desarrollo de juegos, ¡crea fácilmente un juego de defensa de torres! (superior)

Los juegos de defensa de torres son increíblemente populares y no hay nada más satisfactorio que ver cómo tus defensas destruyen a los malvados invasores. ¡En este tutorial de dos partes, crearás un juego de defensa de torres usando Unity !

Aprenderás a…

  • Crea oleadas de enemigos
  • Haga que se muevan siguiendo los puntos de ruta
  • Construye y mejora torres para reducir a tus enemigos a nada.

¡Finalmente tendrás un framework de este tipo que podrás ampliar!

Nota : necesitas conocer los conceptos básicos de Unity, como cómo agregar recursos y componentes del juego, comprender las casas prefabricadas y conocer algunos conceptos básicos de C# .

Defensa de la torre en su totalidad

En este tutorial, crearás un juego de defensa de torres en el que los enemigos (insectos) se arrastran hacia las galletas que te pertenecen a ti y a tus secuaces, ¡que por supuesto son monstruos! Puedes colocar y mejorar monstruos en puntos estratégicos para ganar un poco de oro.

Los jugadores deben matar los insectos antes de que se coman las galletas. Cada oleada de enemigos es más difícil de derrotar. El juego termina cuando sobrevives a todas las oleadas (¡victoria!) o cinco enemigos alcanzan la galleta. (¡fallar!)

Aquí hay capturas de pantalla del juego completo:

¡Los monstruos se unen!  ¡Protege tu galleta!

¡Los monstruos se unen! ¡Protege las galletas!

comenzar

Abra el proyecto TowerDefense-Part1-Starter en Unity .

El proyecto inicial incluye recursos artísticos y sonoros, así como animaciones prediseñadas y algunos guiones útiles. Estos guiones no están directamente relacionados con los juegos de defensa de torres y no se explicarán aquí. Sin embargo, si desea obtener más información sobre la creación de animaciones 2D de Unity, consulte este tutorial de Unity 2D .

El proyecto también contiene casas prefabricadas que luego ampliarás para crear el personaje. Finalmente, el proyecto incluye una escena con su fondo y configuración de interfaz de usuario.

Abra GameScene en la carpeta " Escenas " y configure la relación de aspecto de la vista del juego en 4:3 para asegurarse de que las etiquetas estén alineadas correctamente con el fondo. Deberías ver lo siguiente en la vista Juego:

Captura de pantalla del proyecto inicial

crédito:

  • ¡El arte de este proyecto proviene del paquete de arte gratuito de Vicki Wenderlich! Puedes encontrar gráficos más impresionantes en gameartguppy .
  • La música genial proviene de BenSound , ¡tiene bandas sonoras geniales!
  • Gracias a Michael Jasper por la genialidad .

Proyecto inicial: ¡compruébalo!
Recursos – ¡Compruebe!
Da tu primer paso hacia la dominación mundial... bueno, me refiero a tu juego de defensa de torres... ¡ya terminaste!

Marcador X: Lugar

Los monstruos sólo se pueden publicar en áreas marcadas con _x_.

Para agregarlos a la escena, arrastre y suelte Imágenes\Objetos\Openspot desde el Explorador de proyectos a la vista Escena. Por ahora, la posición no importa.

Con Openspot seleccionado en Jerarquía, haga clic en Agregar componente en el Inspector y seleccione Box Collider 2D . Unity muestra colisionadores de cuadros con líneas verdes en la vista de escena. Utilizará este colisionador para detectar clics del mouse en esta ubicación.

Unity detecta automáticamente el tamaño adecuado para el colisionador.  ¿Cuan genial es eso?

Unity detectará automáticamente el tamaño apropiado del colisionador. ¿Qué tan genial es esto?

Siga los mismos pasos para agregar el componente Audio\Audio Source a Openspot . Configure el clip de audio de la fuente de audio en tower_place , que puede encontrar en la carpeta " Audio ", y luego desactive " Reproducir al despertar ".

Necesitas crear 11 puntos más. Si bien es tentador repetir todos estos pasos, Unity tiene una gran solución: ¡ prefabricados !

Arrastre y suelte Openspot desde la Jerarquía a la carpeta Prefabs en el Explorador de proyectos . Luego, su nombre se vuelve azul en la jerarquía para mostrar que está conectado a la casa prefabricada. como esto:

casa prefabricada

Ahora que tienes tu casa prefabricada, puedes crear tantas copias como necesites. Simplemente arrastre y suelte Openspot desde la carpeta Prefabs en el Explorador de proyectos a la vista de escena. Haga esto 11 veces para crear un total de 12 objetos Openspot en la escena.

Ahora use el Inspector para establecer las posiciones de estos 12 objetos Openspot en 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 termine, la escena debería verse así.

Encuentra posiciones para el juego de defensa de torres.

lugar monstruo

Para facilitar la colocación, la carpeta prefabricada del proyecto contiene un _monster__prefab_part.

Casa prefabricada Monster - Lista para usar

Prefabricados Monster: listos para usar

En este punto, consiste en un objeto de juego vacío que contiene las animaciones de disparo de tres sprites diferentes y sus elementos secundarios.

Cada sprite representa un monstruo con un nivel de poder diferente. La casa prefabricada también contiene un componente AudioSource que activas para reproducir un sonido cada vez que el monstruo dispara su láser.

Ahora creará un script que puede colocar Monster en Openspot

En el Explorador de proyectos , seleccione Openspot en la carpeta Prefabs . En el Inspector, haga clic en Agregar componente , luego elija Nuevo script y asígnele el nombre PlaceMonster. Seleccione C sostenido como idioma y haga clic en Crear y agregar. Desde que agregó el script a Openspot _Prefab, todos los Openspots en la escena ahora también tienen el script adjunto. ¡ordenado!

Haga doble clic en el script para abrirlo en el IDE. Luego agregue estas dos variables:

public GameObject monsterPrefab;
private GameObject monster;

Crearás una copia del objeto almacenado en él monsterPrefabpara crear el monstruo y lo almacenarás en él monsterpara poder manipularlo durante el juego.

Un monstruo por ubicación

Agrega el siguiente método para permitir solo un monstruo por ubicación:

private bool CanPlaceMonster()
{
  return monster == null;
}

Después de CanPlaceMonster()verificar monstersi la variable todavía está allí null, si lo está, significa que actualmente no hay ningún monstruo aquí y puedes poner uno.

Ahora agrega el siguiente código para colocar el monstruo cuando el jugador hace clic en este objeto del juego:

void OnMouseUp()
{
  
  if (CanPlaceMonster())
  {
    
    monster = (GameObject) 
      Instantiate(monsterPrefab, transform.position, Quaternion.identity);
    
    AudioSource audioSource = gameObject.GetComponent<AudioSource>();
    audioSource.PlayOneShot(audioSource.clip);

    
  }
}

Este código coloca un monstruo al hacer clic o hacer clic con el mouse. Entonces, ¿cómo se logra esto?

  1. OnMouseUpUnity llama automáticamente a esto cuando el jugador hace clic en el colisionador de física del objeto del juego.
  2. CanPlaceMonster()Cuando se llama, si se devuelve, este método colocará un nuevo monstruo true.
  3. Creas un monstruo usando Instantiateeste método, que crea una instancia de la casa prefabricada dada con una posición y rotación específicas. En este caso, copia monsterPrefab, le asigna la posición del objeto del juego actual y sin rotación, convierte el resultado a GameObjecty lo almacena en un archivo monster.
  4. Finalmente, llama a PlayOneShotReproducir el efecto de sonido adjunto al AudioSourcecomponente del objeto.

Ahora tu PlaceMonsterscript puede colocar un nuevo monstruo, pero aún tienes que especificar la casa prefabricada.

Utilice la casa prefabricada adecuada

Guarde el archivo y vuelva a Unity.

Para asignar la variable monsterPrefab , primero seleccione Openspot en la carpeta Prefabs en el Explorador de proyectos .

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 .

Asignar prefabricado

Eso es todo. Ejecuta la escena y construye monstruos en varios puntos x con clics o toques.

¡Éxito!  Puedes construir monstruos.  Sin embargo, parecen una papilla extraña porque todos los sprites infantiles de tu monstruo están dibujados.  Arreglarás esto a continuación.

¡éxito! Puedes construir monstruos. Sin embargo, parecen una papilla extraña porque todos los sprites de tu monstruo están dibujados. A continuación, resolverá este problema.

Mejora esos monstruos

En la imagen a continuación, verás que tu monstruo parece cada vez más aterrador en niveles más altos.

¡Es tan esponjoso!  Pero si intentas robarle la galleta, este monstruo puede convertirse en un verdadero asesino.

¡Tan esponjoso! Pero este monstruo puede convertirse en un asesino si intentas robar sus galletas.

El guión sirve como base para implementar un sistema de actualización para monstruos. Realiza un seguimiento de qué tan poderoso debe ser el monstruo en cada nivel y, por supuesto, el nivel actual del monstruo.

Ahora agregue este script.

Seleccione Prefab/Monsters en el Navegador de proyectos. Agregue un nuevo script C# denominado MonsterData . Abra el script en el IDE y agregue el siguiente código _arriba_ de la clase.MonsterData

[System.Serializable]
public class MonsterLevel
{
  public int cost;
  public GameObject visualization;
}

Esto creará MonsterLevelAgrupa el costo (en oro, que se admitirá más adelante) y una representación visual del nivel de un monstruo específico.

[System.Serializable]Puede agregar en la parte superior para que las instancias de la clase sean editables desde el inspector. Esto te permite cambiar rápidamente todos los valores en la clase Nivel, incluso mientras el juego se está ejecutando. Es muy útil para equilibrar tu juego.

Definir nivel de monstruo

怪物等级En este ejemplo, almacena los predefinidos 列表<T>en formato .
¿Por qué no simplemente utilizar MonsterLevel[]? MonsterLevelBueno, necesitarás el índice de un objeto específico muchas veces. Si bien no es difícil codificar esto, utilizará IndexOf()la funcionalidad que implementa Lists. Esta vez no es necesario volver a escribir un método. :]

En la parte superior de MonsterData.cs , ​​agregue las siguientes declaraciones:using

using System.Collections.Generic;

Esto le brinda acceso a estructuras de datos comunes para que pueda usar la clase en sus scripts.List<T>

Nota : Los genéricos son una parte importante de C#. Le permiten definir estructuras de datos con seguridad de tipos sin comprometer tipos. Esto es muy útil para clases contenedoras como listas y colecciones. Para obtener más información sobre los genéricos, consulte Introducción a los genéricos en C# .

Ahora agregue las siguientes variables para MonsterDataalmacenar MonsterLevella lista:

public List<MonsterLevel> levels;

Al utilizar genéricos, se asegura de que solo pueda contener objetos.levels``List``MonsterLevel

Guarde el archivo y cambie a Unity para configurar cada etapa.

Seleccione Prefab/Monsters en el Navegador de proyectos. En __Inspector__ ahora puede ver el campo "Nivel " en el componente MonsterData (script) . Establezca su _tamaño_ en 3 .

Captura de pantalla 24/07/2015 a las 11.26.28

A continuación, establezca el costo de cada nivel en los siguientes valores:

  • Elemento 0 : 200
  • Elemento 1 : 110
  • Elemento 2 : 120

Ahora asigne los valores del campo de visualización.

Expanda Prefab/Monsters en el Explorador de proyectos para que pueda ver sus elementos secundarios. Arrastre y suelte el hijo Monster0 en el campo Visualización de Element0.

Repita esto, asignando el monstruo 1 al elemento 1 y el monstruo 2 al elemento 2. Vea el GIF a continuación que demuestra este proceso:

asignar-monstruos2

Al seleccionar prefab_/monster, prefab_ debería verse así:

Definición de los niveles de los monstruos en el inspector.

Define el nivel del monstruo en el inspector.

Definir el nivel actual

En el IDE, vuelva a MonsterData.cs y agréguele otra variable MonsterData.

private MonsterLevel currentLevel;

En la variable privada currentLevelalmacenarás...espéralo...el nivel actual del monstruo. ]

Ahora configúrelo currentLevely hágalo accesible para otros scripts. Agregue lo siguiente a MonsterData, junto con la declaración de variable de instancia:

public MonsterLevel CurrentLevel
{
  
  get 
  {
    return currentLevel;
  }
  
  set
  {
    currentLevel = value;
    int currentLevelIndex = levels.IndexOf(currentLevel);

    GameObject levelVisualization = levels[currentLevelIndex].visualization;
    for (int i = 0; i < levels.Count; i++)
    {
      if (levelVisualization != null) 
      {
        if (i == currentLevelIndex) 
        {
          levels[i].visualization.SetActive(true);
        }
        else
        {
          levels[i].visualization.SetActive(false);
        }
      }
    }
  }
}

Existen bastantes scripts de C#, ¿eh? Échales un vistazo a todos:

  1. Defina las propiedades de variables_privadas currentLevel. _Después de definir una propiedad, puedes llamarla como cualquier otra variable: como CurrentLevel(desde dentro de la clase) o como monster.CurrentLevel(desde fuera de la clase). Puede definir un comportamiento personalizado en el método getter o setter de una propiedad, y puede controlar si una propiedad es de solo lectura, solo escritura o lectura/escritura proporcionando solo un getter, un setter o ambos.
  2. En un captador, currentLevelel valor devuelto.
  3. En la biblioteca de recursos, asigne el nuevo valor a currentLevel. A continuación, obtendrá el índice del nivel actual. Finalmente, recorre todos los niveles y establece la visualización en activa o inactiva, dependiendo del currentLevelIndex. Esto es genial porque significa que cada vez que alguien establece el currentLevel, el sprite se actualiza automáticamente. ¡Las propiedades definitivamente te serán útiles!

Agregue la siguiente implementación OnEnable:

void OnEnable()
{
  CurrentLevel = levels[0];
}

Este CurrentLevel se establecerá en la ubicación, asegurando que solo muestre el sprite correcto.

NOTA : OnEnableEs muy importante inicializar las propiedades en lugar del OnStartmétodo de orden, ya que puede llamar al método de orden al crear una instancia de la casa prefabricada.

Se llamará inmediatamente cuando se cree la casa prefabricada OnEnable(si la casa prefabricada se guarda en un estado habilitado), pero no hasta que el objeto comience a ejecutarse como parte de la escena OnStart.

Debes verificar estos datos antes de colocar el monstruo, para poder OnEnableinicializarlo en formato .

Guarde el archivo y cambie a Unity. Ejecute el proyecto y coloque los monstruos; ahora muestran los sprites correctos y de nivel más bajo.

No más blanda

Mejora esos monstruos

Vuelva a su 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 GetNextLevelpuedes obtener el índice del nivel actual y el 级别的índice más alto, siempre que el monstruo no haya alcanzado el nivel máximo para regresar al siguiente nivel. En caso contrario, regresa null.

Puedes utilizar este método para determinar si un monstruo se puede actualizar.

Se agregaron los siguientes métodos para aumentar los niveles de monstruos:

public void IncreaseLevel()
{
  int currentLevelIndex = levels.IndexOf(currentLevel);
  if (currentLevelIndex < levels.Count - 1)
  {
    CurrentLevel = levels[currentLevelIndex + 1];
  }
}

Aquí puede obtener el índice del nivel actual y luego asegurarse de que no sea el nivel máximo verificando si es menor que eso. Si es así, pase al siguiente nivel.levels.Count - 1``CurrentLevel

Capacidades de actualización de prueba

Guarde el archivo, luego cambie a PlaceMonster.cs en el IDE y agregue el siguiente método nuevo:

private bool CanUpgradeMonster()
{
  if (monster != null)
  {
    MonsterData monsterData = monster.GetComponent<MonsterData>();
    MonsterLevel nextLevel = monsterData.GetNextLevel();
    if (nextLevel != null)
    {
      return true;
    }
  }
  return false;
}

Primero verifique si hay un monstruo que pueda actualizarse verificando 怪物si la variable 为 null. Si este es el caso, puedes 数据obtener el nivel actual del monstruo a través del monstruo.

Luego pruebe si hay un nivel superior disponible, es decir, cuando GetNextLevel()no se devuelve null. Devolver si es posible realizar una actualización; truede lo contrario, devolverlo false.

Habilitar actualización de oro

Para habilitar la opción de actualización, else ifagregue la rama a OnMouseUp:

if (CanPlaceMonster())
{
  
}
else if (CanUpgradeMonster())
{
  monster.GetComponent<MonsterData>().IncreaseLevel();
  AudioSource audioSource = gameObject.GetComponent<AudioSource>();
  audioSource.PlayOneShot(audioSource.clip);
  
}

Comprueba si puedes CanUpgradeMonster()actualizar usando . Si es así, puedes usar GetComponent()el MonsterDatacomponente de acceso y llamarlo, IncreaseLevel(),lo que aumentará el nivel del monstruo. Finalmente, activas la fuente de audio del monstruo.

Guarde el archivo y vuelva a Unity. Ejecuta el juego, coloca y mejora cualquier cantidad de monstruos... por ahora.

Mejora todos los monstruos

Todos los monstruos mejorados

Pagar monedas - Administrador de juegos

Ahora, todos los monstruos se pueden construir y mejorar instantáneamente, pero ¿dónde está el desafío?

Profundicemos en la cuestión del oro. El problema con el seguimiento es que necesitas compartir información entre diferentes objetos del juego.

La siguiente imagen muestra todos los objetos que estarán involucrados.

Todos los objetos del juego resaltados necesitan saber cuánto oro posee el jugador.

Todos los objetos del juego resaltados necesitan saber cuántas monedas de oro tiene el jugador.

Utilizará un objeto compartido al que puedan acceder otros objetos para almacenar estos datos.

Haga clic derecho en Jerarquía y seleccione Crear vacío . Nombra el nuevo objeto del juego _GameManager_.

Agregue un script C# llamado GameManagerBehavior a GameManager y abra el nuevo script en el IDE. Mostrarás el oro total del jugador en la etiqueta, así que agrega la siguiente línea en la parte superior del archivo:

using UnityEngine.UI;

Esto le brinda acceso a clases específicas de la interfaz de usuario que, por ejemplo, el proyecto utiliza para las etiquetas. Ahora agregue las siguientes variables a la clase:Text

public Text goldLabel;

TextEsto almacenará una referencia al componente utilizado para mostrar cuántas monedas tiene el jugador.

Ahora que GameManagerconoce la etiqueta, ¿cómo se asegura de que la cantidad de oro almacenada en la variable esté sincronizada con la cantidad que se muestra en la etiqueta? Crearás 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 resulta familiar? Es similar a lo que define en CurrentLevel Monster. Primero, cree una variable privada goldpara almacenar la cantidad total actual de oro. Luego defines una Goldpropiedad llamada – creativa, ¿verdad? -- – e implementar un captador y definidor.

El captador simplemente devuelve goldel valor. El colocador es más interesante. Además de establecer el valor de la variable, también textestablece el campo en "activado" para goldLabelmostrar la nueva cantidad de oro.

¿Qué tan generoso te sientes? Agrega la siguiente línea para Start()darle al jugador 1000 de oro, o asigna menos si te sientes tacaño:

Gold = 1000;

Asignar objeto de etiqueta al script

Guarde el archivo y cambie 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 .

Asignar etiqueta dorada

Al ejecutar el escenario, la etiqueta muestra _Oro : 1000_.

1000 de oro

Verifique la "billetera" del jugador

Abra PlaceMonster_.cs en el IDE y agregue las siguientes variables de instancia:

private GameManagerBehavior gameManager;

El componente del GameManager que utilizarás gameManagerpara acceder GameManagerBehaviora la escena . Para asignarlo, agregue lo siguiente a :Start()

gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();

Puedes usar Obtener un objeto de juego llamado GameManager, que devuelve el primer objeto de juego que encuentra con un nombre determinado. Luego, recupere sus componentes y guárdelos para su uso posterior.GameObject.Find()``GameManagerBehavior

NotaGameManager : Puede hacer esto configurando un campo en el Editor de Unity o agregando un método estático que devuelva una instancia singleton de la que pueda obtener 游戏管理器行为.

Sin embargo, hay un método oscuro en el bloque anterior: , que es más lento en tiempo de ejecución, pero conveniente y puede usarse con precaución.Find

¡llevar dinero!

Aún no has deducido oro, así que OnMouseUp()agrega esta línea dos veces, reemplazando cada comentario// TODO: 扣除金币:

gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;

Guarde el archivo y cambie a Unity, actualice algunos monstruos y observe cómo se actualizan las lecturas de oro. Ahora se deduce el oro, pero los jugadores pueden construir monstruos siempre que tengan espacio.

crédito infinito

¿Capacidades ilimitadas? ¡Excelente! Pero no puedes permitir que esto suceda. Los monstruos sólo deben colocarse si el jugador tiene suficientes monedas de oro.

Los monstruos necesitan monedas de oro.

Cambie a PlaceMonster.cs en el IDE y CanPlaceMonster()reemplace el contenido con lo siguiente:

int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost;
return monster == null && gameManager.Gold >= cost;

levelsRecupera el costo de colocar el monstruo MonsterData. Luego compruebas que monsterno lo es nully es gameManager.Goldmayor que el coste.

CanUpgradeMonster()Desafío: añádete para comprobar si el jugador tiene suficientes monedas de oro.

Reemplace esta línea:

return true; 

Con este:

return gameManager.Gold >= nextLevel.cost;

Esto verificará si el _oro_ que tiene el jugador excede el costo de la actualización.

Guarde y ejecute la escena en Unity. ¡Ven e intenta colocar monstruos ilimitados!

Oro limitado.

Ahora sólo puedes construir un número limitado de monstruos.

Política de la torre: enemigos, oleadas y puntos de ruta

Es hora de "allanar el camino" para tus enemigos. Los enemigos aparecen en el primer punto de ruta, pasa al siguiente punto de ruta y repite hasta que lleguen a tu cookie.

Harás marchar al enemigo:

  1. Define un camino para el enemigo.
  2. Mueve a los enemigos por el camino.
  3. Gira al enemigo para que mire hacia adelante.

Crear una carretera con waypoints

Haga clic derecho en la Jerarquía y seleccione Crear nulo para crear un nuevo objeto de juego nulo. Nómbrelo Carretera y asegúrese de que esté en la posición (0, 0, 0).

Ahora, haga clic derecho en Road en la Jerarquía y cree otro objeto de juego vacío como hijo de Road. Nómbrelo Waypoint0 y establezca su posición en (-12, 2, 0); aquí es donde el enemigo comenzará su ataque.

Carretera - jerarquía de waypoints

Cree cinco puntos de ruta más de la misma manera usando los siguientes nombres y ubicaciones:

  • Punto de navegación 1: (X: 7, Y: 2, Z: 0)
  • Punto de navegación 2: (X: 7, Y: -1, Z: 0)
  • Punto de navegación 3: (X: -7.3, Y: -1, Z: 0)
  • Punto de navegación 4: (X: -7,3, Y: -4,5, Z: 0)
  • Punto de navegación 5: (X: 7, Y: -4,5, Z: 0)

La siguiente captura de pantalla resalta las ubicaciones de los puntos de referencia y la ruta resultante.

Captura de pantalla 24/07/2015 a las 12.09.11

generar enemigos

Ahora crea algunos enemigos a los que seguir. La carpeta _Prefabs_ contiene casas prefabricadas _enemigas_. Su posición es (-20, 0, 0), por lo que la nueva instancia se generará fuera de la pantalla.

De lo contrario, está configurado de manera muy similar a la casa prefabricada de Monster, con uno AudioSourcey un niño Sprite, y es un objeto para que puedas rotarlo más tarde sin tener que rotar la barra de salud que necesitarás pronto.

### Mueve al monstruo a la carretera.

Agregue un nuevo script de C# denominado MoveEnemy a Prefabs_\Enemy Prefabs_. 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;

waypointsAlmacenar una copia del punto de ruta en una matriz mientras lo anterior garantiza que no cambie accidentalmente el campo en el __inspector__, pero aún pueda acceder a él desde otros scripts.[HideIn_inspector_]``waypoints

currentWaypointRealiza un seguimiento del punto de ruta que el enemigo está abandonando actualmente y lastWaypointSwitchTimealmacena la hora a la que el enemigo lo pasó. Finalmente, almacena los del enemigo speed.

Start()Añade esta línea en :

lastWaypointSwitchTime = Time.time;

Esto se inicializará lastWaypointSwitchTimea la hora actual.

Para hacer que los enemigos se muevan a lo largo de un camino, agregue el siguiente código a Update():

Vector3 startPosition = waypoints [currentWaypoint].transform.position;
Vector3 endPosition = waypoints [currentWaypoint + 1].transform.position;

float pathLength = Vector3.Distance (startPosition, endPosition);
float totalTimeForPath = pathLength / speed;
float currentTimeOnPath = Time.time - lastWaypointSwitchTime;
gameObject.transform.position = Vector2.Lerp (startPosition, endPosition, currentTimeOnPath / totalTimeForPath);

if (gameObject.transform.position.Equals(endPosition)) 
{
  if (currentWaypoint < waypoints.Length - 2)
  {
    
    currentWaypoint++;
    lastWaypointSwitchTime = Time.time;
    
  }
  else
  {
    
    Destroy(gameObject);

    AudioSource audioSource = gameObject.GetComponent<AudioSource>();
    AudioSource.PlayClipAtPoint(audioSource.clip, transform.position);
    
  }
}

Paso a paso:

  1. Desde la matriz de puntos de ruta, puede recuperar las posiciones inicial y final del segmento de ruta actual.
  2. Calcule el tiempo requerido para todo el viaje usando la fórmula tiempo = distancia/velocidad y luego determine el tiempo actual en la ruta. UsandoVector2.Lerp, puedes insertar la posición actual del enemigo entre la posición inicial y final del segmento.
  3. Comprueba si el enemigo ha llegado endPosition. En caso afirmativo, maneje estos dos escenarios posibles:
    1. Los enemigos aún no están en el último punto de ruta, por lo que se agregaron currentWaypointy actualizaron lastWaypointSwitchTime. Más adelante, agregarás código para rotar al enemigo de modo que también apunte en la dirección en la que se mueve.
    2. El enemigo llega al último punto de ruta, por lo que lo destruye y activa el efecto de sonido. Más adelante también agregarás código para reducir el tamaño del reproductor health.

Guarde el archivo y cambie a Unity.

Dale al enemigo un sentido de dirección.

En su estado actual, el enemigo desconoce el orden de las señales de tráfico.

Seleccione Road en la Jerarquía y agregue un nuevo script C# llamado SpawnEnemy . Luego ábrelo en tu IDE y agrega las siguientes variables:

public GameObject[] waypoints;

Usarás esto waypointspara almacenar puntos de referencia en tu escena en el orden correcto.

Guarde el archivo y cambie a Unity. Seleccione Carreteras en Jerarquía y establezca el Tamaño de la matriz de puntos de referencia en 6 .

Arrastre cada elemento secundario de Road al campo, colocando Waypoint0 en el Elemento 0 , Waypoint1 en el Elemento 1, y así sucesivamente.

puntos de referencia2

Ahora tienes una serie con puntos de ruta cuidadosamente ordenados para que haya un camino; ten en cuenta que nunca se retirarán; morirán intentando llegar a los dulces.

muerte segura

Comprueba si todo está bien

Vaya a SpawnEnemy en el IDE y agregue las siguientes variables:

public GameObject testEnemyPrefab;

Esto mantendrá testEnemyPrefabuna referencia a la casa prefabricada Enemy en .

Para crear enemigos cuando se inicia el script, agregue el siguiente código aStart():

Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;

Esto creará testEnemyuna nueva copia de la casa prefabricada almacenada y le asignará un punto de ruta a seguir.

Guarde el archivo y cambie a Unity. Seleccione el Camino en la Jerarquía y establezca su Enemigo de prueba en el prefabricado Enemigo .

Ejecuta el proyecto y observa enemigos caminando por este camino.

Ejecuta el proyecto para ver a los enemigos viajando por el camino.

ErrorSigueCaminoSinRotar

¿Alguna vez has notado que no siempre miran hacia dónde van? ¡interesante! Si desea llevar este proyecto un paso más allá, continúe con la Parte 2 y perfeccione el proyecto para aprender cómo hacer que funcionen mejor.

Hacer un seguimiento

Has trabajado mucho y estás en camino de tener tu propio juego de defensa de torres.

Los jugadores pueden construir monstruos, pero no en cantidades ilimitadas, y hacer que un enemigo corra hacia tu galleta. Los jugadores tienen monedas de oro y también pueden mejorar monstruos.

En la segunda parte, cubrirás cómo generar una gran cantidad de enemigos y eliminarlos. Nos vemos en la segunda parte

El blogger es un jugador autodidacta. Si también eres principiante de Unity, bienvenido a unirte a mi chat grupal para ayuda y comunicación mutua: 618012892

Supongo que te gusta

Origin blog.csdn.net/weixin_72715182/article/details/130629887
Recomendado
Clasificación