Os jogos de defesa de torre estão ganhando popularidade, e isso não é surpreendente - pouco pode ser comparado com o prazer de observar suas próprias linhas de defesa que destroem inimigos do mal! Neste tutorial em duas partes, criaremos um jogo de defesa de torre no mecanismo
Unity !
Você aprenderá como fazer o seguinte:
- Crie ondas de inimigos
- Faça-os seguir pontos de rota
- Construa e atualize torres e também ensine-os a quebrar inimigos em pequenos pixels
No final, obtemos o quadro do jogo, que pode ser desenvolvido ainda mais!
Nota : você precisa de conhecimentos básicos do Unity (por exemplo, precisa saber como ativos e componentes são adicionados, o que são prefabs) e os conceitos básicos de C # . Para aprender tudo isso, recomendo que você siga os tutoriais sobre Unity de Sean Duffy ou a série Beginning C # with Unity de Brian Mockley.
Vou trabalhar no Unity para OS X, mas este tutorial também é adequado para Windows.
Através das janelas da torre de marfim
Neste tutorial, criaremos um jogo de defesa de torre no qual inimigos (pequenos bugs) rastejam para um cookie pertencente a você e a seus lacaios (é claro, esses são monstros!). O jogador pode colocar monstros em pontos estratégicos e atualizá-los em ouro.
O jogador deve matar todos os bugs até chegar ao cookie. Cada nova onda de inimigos está se tornando cada vez mais difícil de derrotar. O jogo termina quando você sobrevive a todas as ondas (vitória!) Ou quando cinco inimigos rastejam até os biscoitos (perda!).
Aqui está uma captura de tela do jogo finalizado:
Monstros, uni-vos! Proteja o biscoito!Começando a trabalhar
Faça o download deste
projeto em branco , descompacte-o e abra o projeto
TowerDefense-Part1-Starter no Unity.
O projeto de rascunho possui recursos de gráficos e sons, animações prontas e vários scripts úteis. Os scripts não estão diretamente relacionados aos jogos de defesa, então não vou falar sobre eles aqui. No entanto, se você quiser saber mais sobre a criação de animações 2D no Unity, confira este
tutorial do Unity 2D .
O projeto também contém prefabs, que adicionaremos posteriormente para criar caracteres. Finalmente, há uma cena no projeto com um plano de fundo e uma interface de usuário personalizada.
Abra o
GameScene localizado na pasta
Cenas e defina o modo Jogo com uma proporção de
4: 3 para que todos os rótulos correspondam corretamente ao plano de fundo. No modo de jogo, você verá o seguinte:
Autoria:- Os gráficos do projeto foram retirados do pacote Wiki Wenderlich grátis! Outros trabalhos gráficos podem ser encontrados em seu site gameartguppy .
- Ótima música tirada do BenSound , que tem outras trilhas sonoras incríveis!
- Agradeço também a Michael Jesper pela muito útil função de trepidação da câmera.
.
O local está marcado com uma cruz: a localização dos monstros
Monstros só podem ser colocados em pontos marcados com um
x .
Para adicioná-los à cena, arraste
Images \ Objects \ Openspot do
Project Browser para a janela
Scene . Enquanto a posição não é importante para nós.
Depois de selecionar o
Openspot na hierarquia, clique em
Adicionar componente no
Inspetor e selecione
Box Collider 2D . Na janela Cena, o Unity exibirá um colisor retangular com uma linha verde. Usaremos esse colisor para reconhecer os cliques do mouse neste local.
Adicione o componente
Audio \ Audio Source ao
Openspot da mesma maneira. Para o parâmetro
AudioClip do componente Audio Source, selecione o arquivo
tower_place localizado na pasta
Audio e desative
Play On Awake .
Precisamos criar mais 11 pontos. Embora exista uma tentação de repetir todas essas etapas, o Unity tem uma solução melhor:
Prefab !
Arraste
Openspot da
hierarquia para a pasta
Prefabs dentro do
Project Browser . Seu nome ficará azul na Hierarquia, o que significa que está anexado à pré-fabricada. Algo assim:
Agora que temos o espaço em branco pré-fabricado, podemos criar quantas cópias quisermos. Basta arrastar e soltar o
Openspot da pasta
Prefabs dentro do
Project Browser na janela
Scene . Repita isso 11 vezes e 12 objetos Openspot aparecerão na cena.
Agora use o
Inspetor para definir esses 12 objetos Openspot com as seguintes 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)
Quando você fizer isso, a cena ficará assim:
Colocamos monstros
Para simplificar o posicionamento, há uma pré-fabricada
Monster na pasta
Pré -
fabricada do projeto.
Monster Prefab pronto para usoNo momento, ele consiste em um objeto de jogo vazio com três sprites diferentes e animações de tiro quando crianças.
Cada sprite é um monstro com diferentes níveis de poder. A pré-fabricada também contém o componente
Fonte de áudio , que será lançado para reproduzir som quando um monstro disparar um laser.
Agora vamos criar um script que
hospedará o Monster no
Openspot .
No
Navegador de projeto, selecione o objeto
Openspot na pasta
Prefabs . No
Inspetor, clique em
Adicionar componente e selecione
Novo script e nomeie o script como
PlaceMonster . Selecione
C Sharp como o idioma e clique em
Criar e adicionar . Como adicionamos o script à pré-fabricada
Openspot , todos os objetos Openspot na cena agora terão esse script. Ótimo!
Clique duas vezes no script para abri-lo no IDE. Em seguida, adicione duas variáveis:
public GameObject monsterPrefab; private GameObject monster;
Vamos criar uma instância do objeto armazenado no
monsterPrefab
para criar o monstro e armazená-lo no
monster
para que ele possa ser manipulado durante o jogo.
Um monstro por ponto
Para que apenas um monstro possa ser colocado em um ponto, adicione o seguinte método:
private bool CanPlaceMonster() { return monster == null; }
Em
CanPlaceMonster()
podemos verificar se a variável
monster
ainda é
null
. Nesse caso, não há monstro no momento, e podemos colocá-lo.
Agora adicione o seguinte código para colocar o monstro quando o jogador clicar neste GameObject:
Este código localiza o monstro quando você clica no mouse ou toca na tela. Como ele trabalha?
- O Unity chama automaticamente o
OnMouseUp
quando um jogador toca no colisor físico GameObject. - Quando chamado, esse método coloca um monstro se
CanPlaceMonster()
retornar true
. - Criamos um monstro usando o método
Instantiate
, que cria uma instância da pré-fabricada especificada com a posição e rotação especificadas. Nesse caso, monsterPrefab
, fornecemos a posição atual do GameObject sem rotação, transferimos o resultado para o GameObject
e salvamos no monster
- No final, chamamos
PlayOneShot
para reproduzir o efeito sonoro anexado ao componente AudioSource
do objeto.
Agora, nosso script do
PlaceMonster
pode ter um novo monstro, mas ainda precisamos especificar uma pré-fabricada.
Usando o Prefab certo
Salve o arquivo e retorne ao Unity.
Para definir a variável
monsterPrefab , primeiro selecione o objeto
Openspot na pasta
Prefabs no navegador do projeto.
No
Inspetor, clique no círculo à direita do campo
Monster Prefab do componente
PlaceMonster (Script) e selecione
Monster na caixa de diálogo exibida.
Isso é tudo. Inicie a cena e crie monstros em lugares diferentes, clicando com o mouse ou tocando na tela.
Ótimo! Agora podemos criar monstros. No entanto, eles parecem uma bagunça estranha, porque todos os sprites infantis do monstro são atraídos. Agora vamos consertar isso.
Aumentar o nível de monstros
A figura abaixo mostra que, com um aumento de nível, os monstros parecem cada vez mais assustadores.
Que gracinha! Mas se você tentar roubar seus biscoitos, esse monstro se tornará um assassino.O script é usado como base para a implementação do sistema de níveis de monstros. Ele rastreia o poder do monstro em cada nível e, é claro, o nível atual do monstro.
Adicione este script.
Selecione a pré-fabricada
/ Pré- fabricada
/ Monster no
Project Browser . Adicione um novo script
C # chamado
MonsterData . Abra o script no IDE e adicione o seguinte código
acima da classe
MonsterData
.
[System.Serializable] public class MonsterLevel { public int cost; public GameObject visualization; }
Então criamos o
MonsterLevel
. Ele agrupa o preço (em ouro, que iremos apoiar abaixo) e uma representação visual do nível do monstro.
Adicionamos em cima de
[System.Serializable]
para que instâncias de classe possam ser modificadas no inspetor. Isso nos permite alterar rapidamente todos os valores da classe Level, mesmo quando o jogo está rodando. Isso é incrivelmente útil para equilibrar o jogo.
Definir níveis de monstro
No nosso caso, armazenaremos o
MonsterLevel
especificado na
List<T>
.
Por que não usar o
MonsterLevel[]
? Vamos precisar do índice de um objeto
MonsterLevel
específico várias vezes. Embora seja fácil escrever código para isso, ainda precisamos usar
IndexOf()
, que implementa a funcionalidade
Lists
. Não faz sentido reinventar a roda.
Reinventar a bicicleta geralmente é uma má idéia.Na parte superior do
MonsterData.cs, adicione o seguinte
using
construção:
using System.Collections.Generic;
Isso nos dá acesso a estruturas de dados generalizadas para que possamos usar a classe
List<T>
no script.
Nota : generalizações são um poderoso conceito de C #. Eles permitem que você especifique estruturas de dados com segurança de tipo sem ter que aderir ao tipo. Isso é útil para classes de contêineres, como listas e conjuntos. Para saber mais sobre estruturas genéricas, leia o livro Introdução aos C # Genéricos .
Agora adicione a seguinte variável ao
MonsterData
para manter a lista
MonsterLevel
:
public List<MonsterLevel> levels;
Graças a generalizações, podemos garantir que a
List
do
level
contenha apenas objetos
MonsterLevel
.
Salve o arquivo e mude para o Unity para configurar cada nível.
Selecione
Prefabs / Monster no
Project Browser . O
Inspetor agora exibe o campo
Níveis do componente
MonsterData (Script) . Defina o
tamanho como
3 .
Em seguida, defina o
custo para cada nível:
- Elemento 0 : 200
- Elemento 1 : 110
- Elemento 2 : 120
Agora, atribuímos os valores dos campos de exibição visual.
Expanda
Prefabs / Monster no navegador do Projeto para ver seus filhos. Arraste o filho
Monster0 para o campo de
elemento de visualização 0 .
Em seguida, defina o
Elemento 1 como
Monster1 e o
Elemento 2 como
Monster2 . O GIF mostra este processo:
Quando você seleciona
Prefabs / Monster , a pré-fabricada deve ficar assim:
Definir nível atual
Volte para
MonsterData.cs no IDE e adicione outra variável ao
MonsterData
.
private MonsterLevel currentLevel;
Na variável privada
currentLevel
, armazenaremos o nível atual do monstro.
Agora defina
currentLevel
e torne-o visível para outros scripts. Adicione as seguintes linhas ao
MonsterData
juntamente com a declaração das variáveis da instância:
Grande parte do código C #, certo? Vamos tomá-lo em ordem:
- Defina a propriedade da variável privada
currentLevel
. Ao definir a propriedade, podemos chamá-la como qualquer outra variável: como CurrentLevel
(dentro da classe) ou como monster.CurrentLevel
(fora). Podemos definir qualquer comportamento no método getter ou setter de uma propriedade e, criando apenas um getter, setter ou ambos, você pode controlar as propriedades da propriedade: somente leitura, somente leitura e gravação / leitura. - No getter, retornamos o valor de
currentLevel
. - No setter, atribuímos a
currentLevel
novo valor. Em seguida, obtemos o índice do nível atual. Por fim, percorremos todos os níveis e ativamos / desativamos a exibição visual, dependendo do currentLevelIndex
. Isso é ótimo porque, quando o currentLevel
muda, o sprite é atualizado automaticamente. Propriedades são uma coisa muito conveniente!
Adicione a seguinte implementação
OnEnable
:
void OnEnable() { CurrentLevel = levels[0]; }
Aqui configuramos
CurrentLevel
ao colocar. Isso garante que apenas o sprite desejado seja exibido.
Nota : é importante inicializar a propriedade em OnEnable
, e não em OnStart
, porque chamamos os métodos ordinais ao criar instâncias pré-fabricadas.
OnEnable
será chamado imediatamente quando a pré-fabricada for criada (se a pré-fabricada tiver sido salva no estado ativado), mas o OnStart
não OnStart
chamado até que o objeto comece a ser executado como parte da cena.
Precisamos verificar esses dados antes de colocar o monstro, então inicializamos para OnEnable
.
Salve o arquivo e retorne ao Unity. Execute o projeto e coloque os monstros; agora eles exibem os sprites corretos do nível mais baixo.
Monster Upgrade
Retorne ao IDE e adicione o seguinte método ao
MonsterData
:
public MonsterLevel GetNextLevel() { int currentLevelIndex = levels.IndexOf (currentLevel); int maxLevelIndex = levels.Count - 1; if (currentLevelIndex < maxLevelIndex) { return levels[currentLevelIndex+1]; } else { return null; } }
Em
GetNextLevel
, obtemos o índice
currentLevel
e o índice de nível mais alto; se o monstro não atingiu o nível máximo, o próximo nível retornará. Caso contrário,
null
retornado.
Você pode usar este método para descobrir se é possível uma atualização de monstro.
Para aumentar o nível do monstro, adicione o seguinte método:
public void IncreaseLevel() { int currentLevelIndex = levels.IndexOf(currentLevel); if (currentLevelIndex < levels.Count - 1) { CurrentLevel = levels[currentLevelIndex + 1]; } }
Aqui obtemos o índice do nível atual e, em seguida, certifique-se de que este não seja o nível máximo, verificando se é menor que os
levels.Count - 1
.
CurrentLevel
caso,
CurrentLevel
para o próximo nível.
Verificando a funcionalidade de atualização
Salve o arquivo e retorne para
PlaceMonster.cs no IDE. Adicione um novo método:
private bool CanUpgradeMonster() { if (monster != null) { MonsterData monsterData = monster.GetComponent<MonsterData>(); MonsterLevel nextLevel = monsterData.GetNextLevel(); if (nextLevel != null) { return true; } } return false; }
Primeiro, verificamos se há um monstro que pode ser melhorado comparando a variável
monster
com
null
. Se isso for verdade, obtemos o nível de monstro atual de seus
MonsterData
.
Em seguida, verificamos se o próximo nível está disponível, ou seja, se
GetNextLevel()
não retorna
null
. Se um aumento de nível for possível, retornamos
true
; caso contrário, retorne
false
.
Implementamos melhorias para o ouro
Para habilitar a opção de atualização, adicione a ramificação
else if
ao
OnMouseUp
:
if (CanPlaceMonster()) {
Verificamos a possibilidade de uma atualização usando
CanUpgradeMonster()
. Se possível,
MonsterData
componente
MonsterData
usando
GetComponent()
e chamamos
IncreaseLevel()
, o que aumenta o nível do monstro. Finalmente, lançamos o Monster
AudioSource .
Salve o arquivo e retorne ao Unity. Execute o jogo, coloque e atualize
qualquer número de monstros (mas por enquanto).
Pagando Ouro - Game Manager
Embora possamos construir e melhorar imediatamente qualquer monstro, será interessante no jogo?
Vejamos a questão do ouro. O problema com o rastreamento é que precisamos transferir informações entre diferentes objetos do jogo.
A figura abaixo mostra todos os objetos que devem participar disso.
Todos os objetos de jogo selecionados devem saber quanto ouro um jogador possui.Para armazenar esses dados, usaremos um objeto comum que outros objetos podem acessar.
Clique com o botão direito do mouse na
Hierarquia e selecione
Criar Vazio . Nomeie o novo objeto
GameManager .
Adicione um novo script
C # chamado
GameManagerBehavior ao GameManager e abra-o no IDE. Vamos exibir a quantidade total de ouro do jogador no rótulo, portanto, na parte superior do arquivo, adicione a seguinte linha:
using UnityEngine.UI;
Isso nos permitirá acessar classes de interface do usuário, como
Text
, que é usado para rótulos. Agora adicione a seguinte variável à classe:
public Text goldLabel;
Ele armazenará um link para o componente
Text
usado para exibir a quantidade de ouro que um jogador possui.
Agora que o
GameManager
conhece o rótulo, como sincronizamos a quantidade de ouro armazenada na variável e o valor exibido no rótulo? Vamos criar uma propriedade.
Adicione o seguinte código ao
GameManagerBehavior
:
private int gold; public int Gold { get { return gold; } set { gold = value; goldLabel.GetComponent<Text>().text = "GOLD: " + gold; } }
Ele parece familiar? O código é semelhante ao
CurrentLevel
, que definimos no
Monster
. Primeiro, criamos uma variável privada
gold
para armazenar a quantidade atual de ouro. Em seguida, definimos a propriedade
Gold
(inesperadamente, certo?) E implementamos o getter e o setter.
O getter simplesmente retorna o valor do
gold
. O levantador é mais interessante. Além de definir o valor da variável, também define o campo de
text
para
goldLabel
para exibir o novo valor de ouro.
Quão generosos seremos? Adicione a seguinte linha ao
Start()
para dar ao jogador
1000 gold ou menos se você sentir pena do dinheiro:
Gold = 1000;
Atribuindo um objeto de rótulo a um script
Salve o arquivo e retorne ao Unity. Na
Hierarquia, selecione
GameManager . No
Inspetor, clique no círculo à direita do
rótulo dourado . Na caixa de diálogo
Selecionar texto , selecione a guia
Cena e selecione
GoldLabel .
Execute a cena e o rótulo exibirá
Ouro: 1000 .
Verificando a "carteira" do jogador
Abra o script
PlaceMonster.cs no IDE e adicione a seguinte variável de instância:
private GameManagerBehavior gameManager;
Usaremos o
gameManager
para acessar o componente
GameManagerBehavior
objeto
GameManagerBehavior
na cena. Para especificá-lo, adicione o seguinte a
Start()
:
gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
Obtemos um GameObject chamado GameManager usando a função GameObject.Find
GameObject.Find()
, que retorna o primeiro objeto de jogo encontrado com esse nome. Em seguida, obtemos seu componente
GameManagerBehavior
e o salvamos para o futuro.
Nota : você pode fazer isso definindo um campo no editor do Unity ou adicionando um método estático ao GameManager
que retorna uma instância do singleton a partir da qual podemos obter o GameManagerBehavior
.
No entanto, no bloco de código mostrado acima, há uma confusão: o método Find
, que funciona mais lentamente durante a execução do aplicativo; mas é conveniente e pode ser usado com moderação.
Pegue meu dinheiro!
Ainda não
OnMouseUp()
ouro, portanto, adicionaremos essa linha
duas vezes ao
OnMouseUp()
, substituindo cada um dos comentários
// TODO:
:
gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;
Salve o arquivo e volte para o Unity, atualize alguns monstros e veja a atualização do valor Gold. Agora deduzimos ouro, mas os jogadores podem construir monstros desde que tenham espaço suficiente; eles apenas pedem dinheiro emprestado.
Crédito infinito? Ótimo! Mas não podemos permitir. O jogador deve poder apostar em monstros enquanto tiver ouro suficiente.Verificação de ouro para monstros
Alterne no IDE para
PlaceMonster.cs e substitua o conteúdo de
CanPlaceMonster()
seguinte:
int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost; return monster == null && gameManager.Gold >= cost;
Nós
MonsterData
preço de colocação de monstros nos
levels
em seus
MonsterData
. Depois, verificamos que o
monster
não
monster
null
e que
gameManager.Gold
mais do que esse preço.
A tarefa para você: adicione independentemente ao
CanUpgradeMonster()
verificação se o jogador possui ouro suficiente.
Solução dentroSubstitua a linha:
return true;
sobre isso:
return gameManager.Gold >= nextLevel.cost;
Ele verificará se o jogador tem mais
ouro do que o preço de atualização.
Salve e execute a cena no Unity. Agora tente aqueles como adicionar monstros ilimitadamente!
Agora só podemos construir um número limitado de monstros.Política da torre: inimigos, ondas e pontos de referência
É hora de "abrir o caminho" para nossos inimigos. Os inimigos aparecem no primeiro ponto da rota, passam para o próximo e repetem o processo até atingirem o cookie.
Você pode fazer os inimigos se moverem assim:
- Defina o caminho que os inimigos seguirão
- Mova o inimigo pela estrada
- Vire o inimigo para que ele olhe para a frente
Criando uma estrada a partir de waypoints
Clique com o botão direito do mouse na
Hierarquia e selecione
Criar Vazio para criar um novo objeto de jogo vazio. Nomeie-o como
Estrada e posicione-o em
(0, 0, 0) .
Agora clique com o botão direito do mouse em
Road in the
Hierarchy e crie outro objeto de jogo vazio como filho de Road. Nomeie-o como
Waypoint0 e coloque-o no ponto
(-12, 2, 0) - a partir daqui os inimigos começarão seu movimento.
Da mesma forma, crie mais cinco pontos de rota com os seguintes nomes e posições:
- Ponto de passagem1: (X: 7, Y: 2, Z: 0)
- Waypoint2: (X: 7, Y: -1, Z: 0)
- Ponto de referência3: (X: -7.3, Y: -1, Z: 0)
- Ponto de referência4: (X: -7.3, Y: -4.5, Z: 0)
- Ponto de referência5: (X: 7, Y: -4,5, Z: 0)
A captura de tela abaixo mostra os pontos da rota e o caminho resultante.
Fazendo inimigos
Agora crie alguns inimigos para que eles possam se mover pela estrada. Há uma pré-
fabricação inimiga na pasta
Prefabs . Sua posição é
(-20, 0, 0) , portanto, novas instâncias serão criadas fora da tela.
Em todos os outros aspectos, ele é configurado quase da mesma maneira que o pré-fabricado Monster, possui o
AudioSource
e uma subsidiária da
Sprite
, e podemos rotacionar esse sprite no futuro sem virar a barra de integridade.
Movemos inimigos ao longo da estrada
Adicione um novo script
C # chamado
MoveEnemy à
prefab Prefabs \ Enemy . Abra o script no IDE e adicione as seguintes variáveis:
[HideInInspector] public GameObject[] waypoints; private int currentWaypoint = 0; private float lastWaypointSwitchTime; public float speed = 1.0f;
Nos
waypoints
, uma cópia dos pontos de rota é armazenada na matriz, e a linha
[HideIn inspector ]
acima dos
waypoints
garante que não possamos alterar acidentalmente esse campo no
Inspector , mas ainda assim teremos acesso a partir de outros scripts.
currentWaypoint
rastreia a localização da rota do inimigo no momento atual e
lastWaypointSwitchTime
armazena o tempo que o inimigo passou por ela. Além disso, armazenamos a
speed
inimigo.
Adicione esta linha ao
Start()
:
lastWaypointSwitchTime = Time.time;
Portanto, inicializamos
lastWaypointSwitchTime
com o valor do horário atual.
Para que o inimigo se mova ao longo da rota, adicione o seguinte código a
Update()
:
Vamos analisar o código passo a passo:
- A partir da matriz de pontos de rota, obtemos as posições inicial e final do segmento de rota atual.
- Calculamos o tempo necessário para percorrer toda a distância usando a fórmula tempo = distância / velocidade e, em seguida, determinamos a hora atual na rota. Usando
Vector2.Lerp
, interpolamos a posição atual do inimigo entre o segmento exato inicial e final. - Verifique se o inimigo atingiu
endPosition
. Se sim, então processamos dois cenários possíveis:
- O inimigo ainda não atingiu o último ponto da rota, então aumente o valor do
currentWaypoint
e atualize lastWaypointSwitchTime
. Mais tarde, adicionaremos um código para transformar o inimigo, para que ele olhe na direção de seu movimento. - O inimigo atingiu o último ponto da rota, depois a destruímos e iniciamos o efeito sonoro. Mais tarde, adicionaremos um código que reduz a
health
do jogador.
Salve o arquivo e retorne ao Unity.
Informamos os inimigos da direção do movimento
No estado atual, os inimigos não sabem a ordem dos pontos da rota.
Selecione
Estrada na
Hierarquia e adicione um novo script
C # chamado
SpawnEnemy . Abra-o no IDE e adicione a seguinte variável:
public GameObject[] waypoints;
Usaremos
waypoints
para armazenar referências ao waypoint na cena na ordem desejada.
Salve o arquivo e retorne ao Unity. Selecione
Estrada na
Hierarquia e defina o
tamanho da matriz de
Waypoints como
6 .
Arraste cada um dos filhos da Estrada para os campos colando
Waypoint0 no
Elemento 0 ,
Waypoint1 no
Elemento 1 e assim por diante.
Agora temos uma matriz que contém os pontos de rota na ordem correta - lembre-se, os inimigos nunca recuam, eles persistentemente lutam por uma recompensa doce.
Veja como tudo funciona
Abra
SpawnEnemy no IDE e adicione a seguinte variável:
public GameObject testEnemyPrefab;
Ele armazenará uma referência à
testEnemyPrefab
do
Inimigo em
testEnemyPrefab
.
Para criar um inimigo ao executar o script, adicione o seguinte código ao
Start()
:
Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;
Portanto, criaremos uma nova cópia da pré-fabricada armazenada no
testEnemy
e atribuiremos uma rota a ela.
Salve o arquivo e retorne ao Unity. Selecione o objeto
Estrada na
Hierarquia e selecione a
predefinição do
Inimigo para o parâmetro
Test Enemy .
Inicie o projeto e veja como o inimigo se move ao longo da estrada (no GIF, para maior clareza, a velocidade é aumentada em 20 vezes).Percebeu que ele nem sempre olha para onde está indo? É engraçado, mas estamos tentando fazer um jogo profissional. Portanto, na segunda parte do tutorial, ensinaremos os inimigos a olhar para frente.Para onde ir a seguir?
Já fizemos muito e estamos avançando rapidamente para criar nosso próprio jogo de defesa de torre.Os jogadores podem criar um número limitado de monstros, e o inimigo corre ao longo da estrada, indo em direção ao nosso cookie. Os jogadores têm ouro e podem atualizar monstros.Faça o download do resultado final aqui .Na segunda parte, consideraremos a criação de enormes ondas de inimigos e sua destruição. Até breve!