Les jeux de tower defense gagnent en popularité, et cela n'est pas surprenant - peu de choses peuvent être comparées au plaisir d'observer vos propres lignes de défense qui détruisent les ennemis maléfiques! Dans ce tutoriel en deux parties, nous allons créer un jeu de tower defense sur le moteur
Unity !
Vous apprendrez comment procéder comme suit:
- Créez des vagues d'ennemis
- Faites-leur suivre les points de l'itinéraire
- Construisez et améliorez des tours et apprenez-leur également à briser les ennemis en petits pixels
En fin de compte, nous obtenons le cadre du jeu, qui peut être développé davantage!
Remarque : vous avez besoin des connaissances de base d'Unity (par exemple, vous devez savoir comment les actifs et les composants sont ajoutés, quels préfabriqués sont) et les bases de C # . Pour tout savoir, je vous recommande de parcourir les tutoriels sur Unity de Sean Duffy ou la série Beginning C # with Unity de Brian Mockley.
Je travaillerai dans Unity pour OS X, mais ce tutoriel convient également pour Windows.
À travers les fenêtres de la tour d'ivoire
Dans ce tutoriel, nous allons créer un jeu de tower defense dans lequel les ennemis (petits bugs) rampent vers un cookie vous appartenant et vos serviteurs (bien sûr, ce sont des monstres!). Le joueur peut placer des monstres à des points stratégiques et les améliorer en or.
Le joueur doit tuer tous les bugs jusqu'à ce qu'ils arrivent au cookie. Chaque nouvelle vague d'ennemis devient de plus en plus difficile à vaincre. Le jeu se termine lorsque vous survivez à toutes les vagues (victoire!) Ou lorsque cinq ennemis rampent vers les cookies (perte!).
Voici une capture d'écran du jeu terminé:
Monstres, unissez-vous! Protégez le cookie!Se rendre au travail
Téléchargez ce
projet vierge , décompressez-le et ouvrez le projet
TowerDefense-Part1-Starter dans Unity.
Le projet de projet a des atouts graphiques et sonores, des animations toutes faites et plusieurs scripts utiles. Les scripts ne sont pas directement liés aux jeux de tower defense, donc je n'en parlerai pas ici. Cependant, si vous souhaitez en savoir plus sur la création d'animations 2D dans Unity, consultez ce
didacticiel Unity 2D .
Le projet contient également des préfabriqués, que nous ajouterons plus tard pour créer des personnages. Enfin, il y a une scène dans le projet avec un arrière-plan et une interface utilisateur personnalisée.
Ouvrez le
GameScene situé dans le dossier
Scenes et réglez le mode Game sur un rapport d'aspect de
4: 3 afin que toutes les étiquettes correspondent correctement à l'arrière-plan. En mode Jeu, vous verrez ce qui suit:
Paternité:- Les graphismes du projet sont tirés du pack Wiki Wenderlich gratuit! D'autres œuvres graphiques peuvent être trouvées sur son site Web gameartguppy .
- Super musique tirée de BenSound , qui a d'autres bandes sonores impressionnantes!
- Je remercie également Michael Jesper pour la fonction très utile de bougé de l'appareil photo.
.
L'endroit est marqué d'une croix: l'emplacement des monstres
Les monstres ne peuvent être placés que sur des points marqués d'un
x .
Pour les ajouter à la scène, faites glisser
Images \ Objects \ Openspot de
Project Browser vers la fenêtre
Scene . Alors que la position n'est pas importante pour nous.
Une fois que vous avez sélectionné
Openspot dans la hiérarchie, cliquez sur
Ajouter un composant dans l'
inspecteur et sélectionnez
Box Collider 2D . Dans la fenêtre Scène, Unity affichera un collisionneur rectangulaire avec une ligne verte. Nous utiliserons ce collisionneur pour reconnaître les clics de souris à cet endroit.
Ajoutez le composant
Audio \ Source audio à
Openspot de la même manière. Pour le paramètre
AudioClip du composant Audio Source, sélectionnez le fichier
tower_place situé dans le dossier
Audio et désactivez
Play On Awake .
Nous devons créer 11 points supplémentaires. Bien qu'il y ait une tentation de répéter toutes ces étapes, Unity a une meilleure solution:
Prefab !
Faites glisser
Openspot de la
hiérarchie vers le dossier
Prefabs dans l'
arborescence du
projet . Son nom deviendra bleu dans la Hiérarchie, ce qui signifie qu'il est attaché au préfabriqué. Quelque chose comme ça:
Maintenant que nous avons le blanc préfabriqué, nous pouvons créer autant de copies que nous voulons.
Faites simplement glisser et déposez
Openspot depuis le dossier
Prefabs dans le
Navigateur du projet dans la fenêtre
Scène . Répétez cette opération 11 fois et 12 objets Openspot apparaîtront dans la scène.
Utilisez maintenant l'
inspecteur pour définir ces 12 objets Openspot avec les coordonnées suivantes:
- (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)
Lorsque vous faites cela, la scène ressemblera à ceci:
Nous plaçons des monstres
Pour simplifier le placement, il existe un préfabriqué
Monster dans le dossier
Prefab du projet.
Monster Prefab prêt à l'emploiÀ l'heure actuelle, il se compose d'un objet de jeu vide avec trois sprites différents et des animations de tir en tant qu'enfants.
Chaque sprite est un monstre avec différents niveaux de puissance. Le préfabriqué contient également le composant
Source audio , qui sera lancé pour jouer du son lorsqu'un monstre tire un laser.
Nous allons maintenant créer un script qui
hébergera Monster sur
Openspot .
Dans l'
arborescence du projet, sélectionnez l'objet
Openspot dans le dossier
Prefabs . Dans l'
inspecteur, cliquez sur
Ajouter un composant , puis sélectionnez
Nouveau script et nommez le script
PlaceMonster . Sélectionnez
C Sharp comme langue et cliquez sur
Créer et ajouter . Depuis que nous avons ajouté le script au préfabriqué
Openspot , tous les objets Openspot de la scène auront désormais ce script. Super!
Double-cliquez sur le script pour l'ouvrir dans l'EDI. Ajoutez ensuite deux variables:
public GameObject monsterPrefab; private GameObject monster;
Nous allons créer une instance de l'objet stocké dans
monsterPrefab
pour créer le monstre, et le stocker dans
monster
afin qu'il puisse être manipulé pendant le jeu.
Un monstre par point
Pour qu'un seul monstre puisse être placé sur un point, ajoutez la méthode suivante:
private bool CanPlaceMonster() { return monster == null; }
Dans
CanPlaceMonster()
nous pouvons vérifier si la variable
monster
est toujours
null
. Si c'est le cas, alors il n'y a pas de monstre à ce point, et nous pouvons le placer.
Ajoutez maintenant le code suivant pour placer le monstre lorsque le joueur clique sur ce GameObject:
Ce code localise le monstre lorsque vous cliquez sur la souris ou touchez l'écran. Comment fonctionne-t-il?
- Unity appelle automatiquement
OnMouseUp
lorsqu'un joueur touche le collisionneur physique GameObject. - Lorsqu'elle est appelée, cette méthode place un monstre si
CanPlaceMonster()
renvoie true
. - Nous créons un monstre à l'aide de la méthode
Instantiate
, qui crée une instance du préfabriqué donné avec la position et la rotation spécifiées. Dans ce cas, nous copions monsterPrefab
, lui donnons la position actuelle de GameObject et aucune rotation, transférons le résultat vers GameObject
et l'enregistrons dans monster
- À la fin, nous appelons
PlayOneShot
pour lire l'effet sonore attaché au composant AudioSource
de l'objet.
Maintenant, notre script
PlaceMonster
peut avoir un nouveau monstre, mais nous devons toujours spécifier un préfabriqué.
Utiliser le bon préfabriqué
Enregistrez le fichier et revenez à Unity.
Pour définir la variable
monsterPrefab , sélectionnez d'abord l'objet
Openspot dans le dossier
Prefabs du navigateur du projet.
Dans l'
inspecteur, cliquez sur le cercle à droite du champ
Monster Prefab du
composant PlaceMonster (Script) et sélectionnez
Monster dans la boîte de dialogue qui apparaît.
C’est tout. Lancez la scène et créez des monstres à différents endroits en cliquant sur la souris ou en touchant l'écran.
Super! Maintenant, nous pouvons créer des monstres. Cependant, ils ressemblent à un étrange gâchis, car tous les sprites enfants du monstre sont dessinés. Maintenant, nous allons le réparer.
Augmentez le niveau des monstres
La figure ci-dessous montre qu'avec une augmentation de niveau, les monstres ont de plus en plus peur.
Quelle mignonne! Mais si vous essayez de voler ses cookies, ce monstre se transformera en tueur.Le script est utilisé comme base pour la mise en œuvre du système de niveaux de monstre. Il suit la puissance du monstre à chaque niveau et, bien sûr, le niveau actuel du monstre.
Ajoutez ce script.
Sélectionnez le préfabriqué
Prefab / Monster dans l'
arborescence du projet . Ajoutez un nouveau script
C # appelé
MonsterData . Ouvrez le script dans l'EDI et ajoutez le code suivant
au -
dessus de la classe
MonsterData
.
[System.Serializable] public class MonsterLevel { public int cost; public GameObject visualization; }
Nous créons donc
MonsterLevel
. Il regroupe le prix (en or, que nous soutiendrons ci-dessous) et une représentation visuelle du niveau du monstre.
Nous ajoutons au-dessus de
[System.Serializable]
afin que les instances de classe puissent être modifiées dans l'inspecteur. Cela nous permet de changer rapidement toutes les valeurs de la classe Level, même lorsque le jeu est en cours d'exécution. C'est incroyablement utile pour équilibrer le jeu.
Définition des niveaux de monstre
Dans notre cas, nous stockons le
MonsterLevel
spécifié dans la
List<T>
.
Pourquoi ne pas simplement utiliser
MonsterLevel[]
? Nous aurons besoin de l'index d'un objet
MonsterLevel
spécifique plusieurs fois. Bien qu'il soit facile d'écrire du code pour cela, nous devons encore utiliser
IndexOf()
, qui implémente la fonctionnalité
Lists
. Cela n'a aucun sens de réinventer la roue.
Réinventer le vélo est généralement une mauvaise idée.En haut de
MonsterData.cs, ajoutez ce qui suit à l'
using
construction:
using System.Collections.Generic;
Il nous donne accès à des structures de données généralisées afin que nous puissions utiliser la classe
List<T>
dans le script.
Remarque : les généralisations sont un puissant concept C #. Ils vous permettent de spécifier des structures de données de type sécurisé sans avoir à adhérer au type. Ceci est utile pour les classes de conteneurs telles que les listes et les ensembles. Pour en savoir plus sur les structures génériques, lisez le livre Introduction aux génériques C # .
Ajoutez maintenant la variable suivante à
MonsterData
pour contenir la liste
MonsterLevel
:
public List<MonsterLevel> levels;
Grâce aux généralisations, nous pouvons garantir que la
List
partir du
level
ne contiendra que des objets
MonsterLevel
.
Enregistrez le fichier et passez à Unity pour configurer chaque niveau.
Sélectionnez
Prefabs / Monster dans le
navigateur de projet . L'
inspecteur affiche désormais le champ
Niveaux du
composant MonsterData (Script) . Définissez la
taille sur
3 .
Ensuite, définissez le
coût pour chaque niveau:
- Élément 0 : 200
- Élément 1 : 110
- Élément 2 : 120
Maintenant, nous attribuons les valeurs des champs d'affichage visuel.
Développez
Prefabs / Monster dans le navigateur du projet pour voir ses enfants. Faites glisser l'enfant
Monster0 dans le champ
Elément de visualisation 0 .
Ensuite, définissez l'
élément 1 sur
Monster1 et l'
élément 2 sur
Monster2 . Le GIF montre ce processus:
Lorsque vous sélectionnez
Prefabs / Monster , le préfabriqué devrait ressembler à ceci:
Définir le niveau actuel
Revenez à
MonsterData.cs dans l'EDI et ajoutez une autre variable à
MonsterData
.
private MonsterLevel currentLevel;
Dans la variable privée
currentLevel
nous stockons le niveau actuel du monstre.
currentLevel
maintenant
currentLevel
et rendez-le visible pour les autres scripts. Ajoutez les lignes suivantes à
MonsterData
avec la déclaration des variables d'instance:
Assez gros morceau de code C #, non? Prenons-le dans l'ordre:
- Définissez la propriété de la variable privée
currentLevel
. En définissant la propriété, nous pouvons l'appeler comme n'importe quelle autre variable: soit comme CurrentLevel
(à l'intérieur de la classe), soit comme CurrentLevel
(à l'extérieur). Nous pouvons définir n'importe quel comportement dans la méthode getter ou setter d'une propriété, et en créant uniquement un getter, un setter ou les deux, vous pouvez contrôler les propriétés de la propriété: lecture seule, écriture seule et écriture / lecture. - Dans le getter, nous retournons la valeur de
currentLevel
. - Dans le setter, nous attribuons à
currentLevel
nouvelle valeur. Ensuite, nous obtenons l'indice du niveau actuel. Enfin, nous parcourons tous les niveaux et activons / désactivons l'affichage visuel en fonction de currentLevelIndex
. C'est formidable car lorsque currentLevel
change, le sprite se met à jour automatiquement. Les propriétés sont une chose très pratique!
Ajoutez l'implémentation
OnEnable
suivante:
void OnEnable() { CurrentLevel = levels[0]; }
Ici, nous définissons
CurrentLevel
lors du placement. Cela garantit que seul le sprite souhaité est affiché.
Remarque : il est important d'initialiser la propriété dans OnEnable
, et non dans OnStart
, car nous appelons les méthodes ordinales lors de la création d'instances préfabriquées.
OnEnable
sera appelé immédiatement lorsque le préfabriqué est créé (si le préfabriqué a été enregistré dans l'état activé), mais OnStart
appelé que lorsque l'objet commence à s'exécuter dans le cadre de la scène.
Nous devons vérifier ces données avant de placer le monstre, nous l'initialisons donc sur OnEnable
.
Enregistrez le fichier et revenez à Unity. Exécutez le projet et placez les monstres; ils affichent maintenant les sprites corrects du niveau le plus bas.
Mise à niveau de monstre
Revenez à l'EDI et ajoutez la méthode suivante à
MonsterData
:
public MonsterLevel GetNextLevel() { int currentLevelIndex = levels.IndexOf (currentLevel); int maxLevelIndex = levels.Count - 1; if (currentLevelIndex < maxLevelIndex) { return levels[currentLevelIndex+1]; } else { return null; } }
Dans
GetNextLevel
nous obtenons l'index
currentLevel
et l'index de niveau le plus élevé; si le monstre n'a pas atteint le niveau maximum, le niveau suivant revient. Sinon,
null
renvoyé.
Vous pouvez utiliser cette méthode pour savoir si une mise à niveau de monstre est possible.
Pour élever le niveau du monstre, ajoutez la méthode suivante:
public void IncreaseLevel() { int currentLevelIndex = levels.IndexOf(currentLevel); if (currentLevelIndex < levels.Count - 1) { CurrentLevel = levels[currentLevelIndex + 1]; } }
Ici, nous obtenons l'index du niveau actuel, puis nous nous assurons que ce n'est pas le niveau maximum, en vérifiant qu'il est inférieur aux
levels.Count - 1
. Si tel est le cas,
CurrentLevel
au niveau suivant.
Vérification de la fonctionnalité de mise à niveau
Enregistrez le fichier et revenez à
PlaceMonster.cs dans l'IDE. Ajoutez une nouvelle méthode:
private bool CanUpgradeMonster() { if (monster != null) { MonsterData monsterData = monster.GetComponent<MonsterData>(); MonsterLevel nextLevel = monsterData.GetNextLevel(); if (nextLevel != null) { return true; } } return false; }
Nous vérifions d'abord s'il existe un monstre qui peut être amélioré en comparant la variable
monster
avec
null
. Si cela est vrai, nous obtenons le niveau actuel du monstre à partir de ses
MonsterData
.
Ensuite, nous vérifions si le niveau suivant est disponible, c'est-à-dire si
GetNextLevel()
ne retourne pas
null
. Si une augmentation de niveau est possible, alors nous retournons
true
; sinon retournez
false
.
Nous mettons en œuvre des améliorations pour l'or
Pour activer l'option de mise à niveau, ajoutez la branche
else if
à
OnMouseUp
:
if (CanPlaceMonster()) {
Nous vérifions la possibilité d'une mise à niveau en utilisant
CanUpgradeMonster()
. Si possible, nous
MonsterData
composant
MonsterData
aide de
GetComponent()
et appelons
IncreaseLevel()
, ce qui augmente le niveau du monstre. Enfin, nous lançons Monster
AudioSource .
Enregistrez le fichier et revenez à Unity. Exécutez le jeu, placez et améliorez
n'importe quel nombre de monstres (mais pour l'instant).
Payer l'or - Game Manager
Bien que nous puissions immédiatement construire et améliorer des monstres, mais sera-t-il intéressant dans le jeu?
Examinons la question de l'or. Le problème avec le suivi est que nous devons transférer des informations entre différents objets de jeu.
La figure ci-dessous montre tous les objets qui devraient y participer.
Tous les objets de jeu sélectionnés doivent savoir combien d'or un joueur possède.Pour stocker ces données, nous utiliserons un objet commun auquel d'autres objets peuvent accéder.
Cliquez avec le bouton droit sur la
hiérarchie et sélectionnez
Créer vide . Nommez le nouvel objet
GameManager .
Ajoutez un nouveau script
C # appelé
GameManagerBehavior à GameManager , puis ouvrez-le dans l'EDI. Nous afficherons la quantité totale d'or du joueur dans l'étiquette, donc en haut du fichier, ajoutez la ligne suivante:
using UnityEngine.UI;
Cela nous permettra d'accéder à des classes d'interface utilisateur comme
Text
, qui est utilisé pour les étiquettes. Ajoutez maintenant la variable suivante à la classe:
public Text goldLabel;
Il stockera un lien vers le composant
Text
utilisé pour afficher la quantité d'or d'un joueur.
Maintenant que le
GameManager
connaît l'étiquette, comment synchroniser la quantité d'or stockée dans la variable et la valeur affichée sur l'étiquette? Nous allons créer une propriété.
Ajoutez le code suivant à
GameManagerBehavior
:
private int gold; public int Gold { get { return gold; } set { gold = value; goldLabel.GetComponent<Text>().text = "GOLD: " + gold; } }
Semble-t-il familier? Le code est similaire à
CurrentLevel
, que nous avons défini dans
Monster
. Nous créons d'abord un
gold
variable privé pour contenir la quantité d'or actuelle. Ensuite, nous définissons la propriété
Gold
(de manière inattendue, non?) Et implémentons le getter et le setter.
Le getter renvoie simplement la valeur de l'
gold
. Le passeur est plus intéressant. En plus de définir la valeur de la variable, il définit également le champ de
text
pour
goldLabel
pour afficher la nouvelle valeur d'or.
Sommes-nous généreux? Ajoutez la ligne suivante à
Start()
pour donner au joueur
1000 pièces d' or, ou moins si vous vous sentez désolé pour l'argent:
Gold = 1000;
Affectation d'un objet d'étiquette à un script
Enregistrez le fichier et revenez à Unity. Dans la
hiérarchie, sélectionnez
GameManager . Dans l'
inspecteur, cliquez sur le cercle à droite du
Gold Label . Dans la boîte de dialogue
Sélectionner le texte , sélectionnez l'onglet
Scène et sélectionnez
GoldLabel .
Exécutez la scène et l'étiquette affichera
Gold: 1000 .
Vérification du "portefeuille" du joueur
Ouvrez le script
PlaceMonster.cs dans l'EDI et ajoutez la variable d'instance suivante:
private GameManagerBehavior gameManager;
Nous utiliserons
gameManager
pour accéder au composant
GameManagerBehavior
de l'objet
GameManagerBehavior
dans la scène. Pour le spécifier, ajoutez ce qui suit à
Start()
:
gameManager = GameObject.Find("GameManager").GetComponent<GameManagerBehavior>();
Nous obtenons un GameObject appelé GameManager à l'aide de la fonction
GameObject.Find()
, qui renvoie le premier objet de jeu trouvé avec ce nom. Ensuite, nous obtenons son composant
GameManagerBehavior
et l'enregistrons pour l'avenir.
Remarque : vous pouvez le faire en définissant un champ dans l'éditeur Unity ou en ajoutant à GameManager
une méthode statique qui renvoie une instance du singleton à partir de laquelle nous pouvons obtenir GameManagerBehavior
.
Cependant, dans le bloc de code ci-dessus, il y a un cheval noir: la méthode Find
, qui fonctionne plus lentement pendant l'exécution de l'application; mais il est pratique et peut être utilisé avec modération.
Prends mon argent!
Nous n'avons pas encore soustrait d'or, nous allons donc ajouter cette ligne
deux fois à
OnMouseUp()
, en remplaçant chacun des commentaires
// TODO:
:
gameManager.Gold -= monster.GetComponent<MonsterData>().CurrentLevel.cost;
Enregistrez le fichier et revenez à Unity, mettez à niveau certains monstres et regardez la mise à jour de la valeur Gold. Maintenant, nous déduisons de l'or, mais les joueurs peuvent construire des monstres tant qu'ils ont suffisamment d'espace; ils empruntent juste de l'argent.
Crédit infini? Super! Mais nous ne pouvons pas le permettre. Le joueur doit pouvoir parier des monstres tant qu'il a suffisamment d'or.Chèque d'or pour les monstres
Basculez l'IDE vers
PlaceMonster.cs et remplacez le contenu de
CanPlaceMonster()
suit:
int cost = monsterPrefab.GetComponent<MonsterData>().levels[0].cost; return monster == null && gameManager.Gold >= cost;
Nous
MonsterData
prix de placement des monstres à partir des
levels
dans ses
MonsterData
. Ensuite, nous vérifions que le
monster
pas
null
et que
gameManager.Gold
supérieur à ce prix.
La tâche pour vous: ajouter indépendamment à
CanUpgradeMonster()
vérification si le joueur a suffisamment d'or.
Solution à l'intérieurRemplacez la ligne:
return true;
à ce sujet:
return gameManager.Gold >= nextLevel.cost;
Il vérifiera si le joueur a plus d'
or que le prix de mise à niveau.
Enregistrez et exécutez la scène dans Unity. Essayez maintenant de savoir comment ajouter des monstres à volonté!
Maintenant, nous ne pouvons construire qu'un nombre limité de monstres.Politique de la tour: ennemis, vagues et waypoints
Il est temps de «préparer le terrain» à nos ennemis. Les ennemis apparaissent au premier point de l'itinéraire, passent au suivant et répètent le processus jusqu'à ce qu'ils atteignent le cookie.
Vous pouvez faire bouger les ennemis comme ceci:
- Définissez la route que les ennemis suivront
- Déplacez l'ennemi le long de la route
- Tournez l'ennemi pour qu'il regarde vers l'avant
Création d'une route à partir de waypoints
Cliquez avec le bouton droit sur la
hiérarchie et sélectionnez
Créer vide pour créer un nouvel objet de jeu vide. Nommez-le
Road et placez-le à
(0, 0, 0) .
Maintenant, faites un clic droit sur
Road dans la
hiérarchie et créez un autre objet de jeu vide en tant qu'enfant de Road. Nommez-le
Waypoint0 et placez-le au point
(-12, 2, 0) - à partir de là, les ennemis commenceront leur mouvement.
De même, créez cinq autres points d'itinéraire avec les noms et positions suivants:
- 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)
- Point de cheminement5: (X: 7, Y: -4,5, Z: 0)
La capture d'écran ci-dessous montre les points de l'itinéraire et le chemin résultant.
Se faire des ennemis
Créez maintenant des ennemis pour qu'ils puissent se déplacer le long de la route. Il y a un préfabriqué
ennemi dans le dossier
Prefabs . Sa position est
(-20, 0, 0) , donc de nouvelles instances seront créées hors écran.
À tous les autres égards, il est configuré presque de la même manière que le préfabriqué Monster, a
AudioSource
et une filiale
Sprite
, et nous pouvons faire pivoter ce sprite à l'avenir sans tourner la barre de santé.
Nous déplaçons des ennemis le long de la route
Ajoutez un nouveau script
C # appelé
MoveEnemy au
préfabriqué Prefabs \ Enemy . Ouvrez le script dans l'EDI et ajoutez les variables suivantes:
[HideInInspector] public GameObject[] waypoints; private int currentWaypoint = 0; private float lastWaypointSwitchTime; public float speed = 1.0f;
Dans les
waypoints
, une copie des
waypoints
est stockée dans le tableau, et la ligne
[HideIn inspector ]
au-dessus des
waypoints
garantit que nous ne pouvons pas modifier accidentellement ce champ dans l'
inspecteur , mais y aurons toujours accès à partir d'autres scripts.
currentWaypoint
conserve la trace de la route de l'ennemi à l'heure actuelle et
lastWaypointSwitchTime
stocke l'heure à laquelle l'ennemi l'a traversé. De plus, nous stockons la
speed
ennemi.
Ajoutez cette ligne à
Start()
:
lastWaypointSwitchTime = Time.time;
Nous initialisons donc
lastWaypointSwitchTime
avec la valeur de l'heure actuelle.
Pour que l'ennemi se déplace le long de l'itinéraire, ajoutez le code suivant à
Update()
:
Analysons le code étape par étape:
- À partir du tableau de points d'itinéraire, nous obtenons les positions de début et de fin du segment d'itinéraire actuel.
- Nous calculons le temps nécessaire pour parcourir toute la distance en utilisant la formule temps = distance / vitesse , puis déterminons l'heure actuelle sur l'itinéraire. En utilisant
Vector2.Lerp
, nous interpolons la position actuelle de l'ennemi entre le segment exact de début et de fin. - Vérifiez si l'ennemi a atteint
endPosition
. Si oui, alors nous traitons deux scénarios possibles:
- L'ennemi n'a pas encore atteint le dernier point de l'itinéraire, alors augmentez la valeur de
currentWaypoint
et mettez à jour lastWaypointSwitchTime
. Plus tard, nous ajouterons un code pour retourner l'ennemi afin qu'il regarde dans la direction de son mouvement. - L'ennemi a atteint le dernier point de la route, puis nous le détruisons et commençons l'effet sonore. Plus tard, nous ajouterons un code qui réduit la
health
du joueur.
Enregistrez le fichier et revenez à Unity.
Nous informons les ennemis de la direction du mouvement
Dans leur état actuel, les ennemis ne connaissent pas l'ordre des points de route.
Sélectionnez
Road dans la
hiérarchie et ajoutez un nouveau script
C # appelé
SpawnEnemy . Ouvrez-le dans l'EDI et ajoutez la variable suivante:
public GameObject[] waypoints;
Nous utiliserons des
waypoints
pour stocker les références au waypoint dans la scène dans l'ordre souhaité.
Enregistrez le fichier et revenez à Unity. Sélectionnez
Route dans la
hiérarchie et définissez la
taille du tableau de
waypoints sur
6 .
Faites glisser chacun des enfants Road dans les champs en collant
Waypoint0 dans l'
élément 0 ,
Waypoint1 dans l'
élément 1, etc.
Nous avons maintenant un tableau contenant les points de route dans le bon ordre - attention, les ennemis ne reculent jamais, ils s'efforcent constamment d'obtenir une douce récompense.
Vérifiez comment tout cela fonctionne
Ouvrez
SpawnEnemy dans l'EDI et ajoutez la variable suivante:
public GameObject testEnemyPrefab;
Il stockera une référence au
testEnemyPrefab
Enemy dans
testEnemyPrefab
.
Pour créer un ennemi lors de l'exécution du script, ajoutez le code suivant à
Start()
:
Instantiate(testEnemyPrefab).GetComponent<MoveEnemy>().waypoints = waypoints;
Nous allons donc créer une nouvelle copie du préfabriqué stocké dans
testEnemy
et lui affecter un itinéraire.
Enregistrez le fichier et revenez à Unity. Sélectionnez l'objet
Route dans la
hiérarchie et sélectionnez le préfabriqué
ennemi pour le paramètre
Test Enemy .
Lancez le projet et voyez comment l'ennemi se déplace le long de la route (en GIF, pour plus de clarté, la vitesse est augmentée de 20 fois).Vous avez remarqué qu'il ne regarde pas toujours où il va? C'est drôle, mais nous essayons de créer un jeu professionnel. Par conséquent, dans la deuxième partie du didacticiel, nous apprendrons aux ennemis à regarder en avant.Où aller ensuite?
Nous avons déjà beaucoup fait et nous nous dirigeons rapidement vers la création de notre propre jeu de tower defense.Les joueurs peuvent créer un nombre limité de monstres, et l'ennemi court le long de la route, se dirigeant vers notre cookie. Les joueurs ont de l'or et ils peuvent améliorer les monstres.Téléchargez le résultat final d'ici .Dans la deuxième partie, nous considérerons la création d'énormes vagues d'ennemis et leur destruction. A très bientôt!