I. Introduction▲
Voici le deuxième épisode formation donnée au cours du Unite 2015 à Boston durant laquelle vous allez apprendre à faire un jeu où deux tanks s'affrontent.
Vous pouvez retrouver les autres épisodes de cette série dans le sommaire dédié.
II. Vidéo▲
Unity - Tanks ! - Création et contrôle du tank
III. Résumé▲
Dans cette deuxième vidéo, vous allez voir comment implémenter le tank et permettre au joueur de le déplacer.
III-A. Création du tank▲
Le tank a besoin de différents composants pour fonctionner :
- un Transform ;
- un Rigidbody ;
- un Box Collider ;
- deux Audio Source : une pour jouer le son du moteur, la seconde pour les effets additionnels comme le tir ;
- un script pour son déplacement.
III-A-1. Modèle▲
Prenez le modèle du tank (appelé « Tank ») contenu dans le dossier « Models » du projet et glissez-le dans la hiérarchie. Ensuite, définissez le layer du GameObject du tank à « Players ». Appliquez ce changement à cet objet uniquement (« No, this object only ») lorsqu'on vous le demande.
Lorsqu'un objet est sélectionné, vous pouvez zoomer et centrer la caméra de votre scène sur celui-ci avec la touche 'F'.
III-A-2. Collision▲
Pour que le tank puisse avoir une entité physique dans le monde dans lequel il évolue, il faut lui ajouter un composant « RigidBody ». Comme le tank ne peut pas se déplacer vers le haut ni le bas, gelez la position sur l'axe Y avec la propriété « Freeze Position » du composant. De la même manière, afin que le tank ne tente de commencer à tourner de manière étrange, gelez la rotation sur l'axe X et Z.
Pour déplacer le tank (à travers du script), il faudra utiliser le moteur physique et non pas déterminer sa position directement.
Ensuite, pour déterminer la forme physique du tank, il est nécessaire de rajouter une boîte de collision (composant « Box Collider »).
Toute la scène est configurée avec des primitives de base (cube, sphère) pour gérer les collisions.
Lorsque vous ajoutez la boîte de collision, celle-ci n'a pas la taille adéquate. Redimensionnez-la à (1.5, 1.7, 1.6) et placez-la en (0, 0.85, 0).
III-A-3. Effets sonores▲
Le tank possède deux sources audio (composant « Audio Source »), une pour le son du moteur et la seconde pour les sons additionnels (tirs). Configurez la première source afin qu'elle boucle continuellement en cochant la propriété « Loop ». Ensuite, définissez le son que la source jouera : « EngineIdle ».
La seconde source est gérée par le script. Toutefois, vous devez décocher « Play on awake » afin que le son ne soit pas joué dès le démarrage.
III-A-4. Créer un préfabriqué du tank▲
Le tank maintenant configuré peut servir comme préfabriqué pour tous les tanks que nous voudrions ajouter dans la scène. Pour ce faire, glisser-déposer le GameObject du tank dans le dossier « Prefabs ».
III-A-5. Poussière▲
Lorsque le tank roule, celui-ci remue la poussière. Pour réaliser cet effet, il est possible d'utiliser le système de particules « DustTrail » fourni avec le projet.
Les particules apparaissent uniquement lorsque vous déplacez le système de particules. Cela peut être réalisé simplement en définissant l'espace de simulation comme étant dans le monde (« Simulation Space » à « World ») et de définir le taux d'émission pour que celui-ci soit basé sur la distance.
Pour notre tank, nous avons besoin de deux systèmes de particules, un pour chaque chenille. Les positions sont : (-0.5, 0, -0.75) et (0.5, 0, -0.75). Vous pouvez renommer les systèmes de particules associés au tank pour un meilleur repérage.
III-B. Script du tank▲
Le script que nous allons utiliser est nommé « TankMovement ». Celui-ci doit être attaché au GameObject du tank :
using
UnityEngine;
public
class
TankMovement :
MonoBehaviour
{
public
int
m_PlayerNumber =
1
;
// Identifie à quel joueur le tank appartient. Cela est défini par le gestionnaire de tanks.
public
float
m_Speed =
12f
;
// Vitesse de déplacement avant/arrière du tank.
public
float
m_TurnSpeed =
180f
;
// Vitesse de rotation du tank en degrés par seconde.
public
AudioSource m_MovementAudio;
// Référence vers la source audio pour jouer le son du moteur. Note : source différente de celle pour jouer le tir.
public
AudioClip m_EngineIdling;
// Son à jouer lorsque le tank ne se déplace pas.
public
AudioClip m_EngineDriving;
// Son à jouer lorsque le tank se déplace.
public
float
m_PitchRange =
0
.
2f
;
// Variation du pitch des bruits du moteur.
private
string
m_MovementAxisName;
// Nom des axes utilisés pour le mouvement avant/arrière.
private
string
m_TurnAxisName;
// Nom des axes utilisés pour la rotation.
private
Rigidbody m_Rigidbody;
// Référence utilisée pour déplacer le tank.
private
float
m_MovementInputValue;
// Valeur actuelle du déplacement.
private
float
m_TurnInputValue;
// Valeur actuelle de rotation.
private
float
m_OriginalPitch;
// Le pitch de la source audio au début de la scène.
private
void
Awake (
)
{
m_Rigidbody =
GetComponent<
Rigidbody>
(
);
}
private
void
OnEnable (
)
{
// Lorsque le tank est activé, assurons-nous qu'il n'est pas cinématique.
m_Rigidbody.
isKinematic =
false
;
// Réinitialise les valeurs d'entrées.
m_MovementInputValue =
0f
;
m_TurnInputValue =
0f
;
}
private
void
OnDisable (
)
{
// Lorsque le tank est désactivé, réactivons le mouvement cinématique pour stopper son mouvement.
m_Rigidbody.
isKinematic =
true
;
}
private
void
Start (
)
{
// Les noms des axes dépendent du numéro du joueur.
m_MovementAxisName =
"Vertical"
+
m_PlayerNumber;
m_TurnAxisName =
"Horizontal"
+
m_PlayerNumber;
// Stocke le pitch d'origine de la source audio.
m_OriginalPitch =
m_MovementAudio.
pitch;
}
private
void
Update (
)
{
// Stocke la valeur des deux axes d'entrées.
m_MovementInputValue =
Input.
GetAxis (
m_MovementAxisName);
m_TurnInputValue =
Input.
GetAxis (
m_TurnAxisName);
EngineAudio (
);
}
private
void
EngineAudio (
)
{
// S'il n'y a pas d'entrée (le tank est immobile)...
if
(
Mathf.
Abs (
m_MovementInputValue) <
0
.
1f
&&
Mathf.
Abs (
m_TurnInputValue) <
0
.
1f
)
{
// ... et si la source audio joue actuellement le son lié au mouvement...
if
(
m_MovementAudio.
clip ==
m_EngineDriving)
{
// ... change le son pour jouer le son d'attente.
m_MovementAudio.
clip =
m_EngineIdling;
m_MovementAudio.
pitch =
Random.
Range (
m_OriginalPitch -
m_PitchRange,
m_OriginalPitch +
m_PitchRange);
m_MovementAudio.
Play (
);
}
}
else
{
// Sinon, si le tank se déplace et que la source audio joue le son d'attente...
if
(
m_MovementAudio.
clip ==
m_EngineIdling)
{
// ... change le son pour jouer le son lié au mouvement.
m_MovementAudio.
clip =
m_EngineDriving;
m_MovementAudio.
pitch =
Random.
Range
(
m_OriginalPitch -
m_PitchRange,
m_OriginalPitch +
m_PitchRange);
m_MovementAudio.
Play
(
);
}
}
}
private
void
FixedUpdate (
)
{
// Ajuste la position et rotation du RigidBody.
Move (
);
Turn (
);
}
private
void
Move (
)
{
// Crée un vecteur dans la direction du tank. Le tank se déplace avec une vitesse basée sur l'entrée, la vitesse et le temps entre chaque frame.
Vector3 movement =
transform.
forward *
m_MovementInputValue *
m_Speed *
Time.
deltaTime;
// Applique ce mouvement à la position du RigidBody.
m_Rigidbody.
MovePosition
(
m_Rigidbody.
position +
movement);
}
private
void
Turn (
)
{
// Détermine le nombre de degrés de rotation suivant l'entrée, la vitesse et le temps entre chaque frame.
float
turn =
m_TurnInputValue *
m_TurnSpeed *
Time.
deltaTime;
// Transforme l'angle en une rotation sur l'axe Y.
Quaternion turnRotation =
Quaternion.
Euler (
0f
,
turn,
0f
);
// Applique la rotation au RigidBody.
m_Rigidbody.
MoveRotation (
m_Rigidbody.
rotation *
turnRotation);
}
}
III-B-1. Visibilité des variables▲
Les variables marquées public, seront visibles dans l'inspecteur lorsque vous allez ajouter le script en tant que composant.
Les variables marquées private, ne seront pas visibles ni utilisables, à l'extérieur même du script où elles ont été créées.
Les variables créées dans une fonction ne sont visibles et utilisables uniquement que dans cette fonction.
Les tuteurs préfixent le nom de leurs variables avec m_, pour se rappeler à eux-mêmes (et au quelconque lecteur du script) que ces variables sont accessibles à travers tout le script. Cela ne change rien pour Unity et cette convention n'est que pour les humains.
III-B-2. Gestion des entrées▲
Plusieurs tanks joueront en même temps dans la scène. Chaque tank aura une instance du script. Il faut donc que le script soit assez générique, notamment pour faire en sorte que les deux joueurs contrôlent bien leur tank respectif. Pour ce faire, il est nécessaire de sauvegarder le nom des entrées qu'utilisera chaque joueur, dans le script composant le tank leur appartenant. Cela se fait à travers les variables m_MovementAxisName et m_TurnAxisName. Celles-ci contiennent le nom des axes utilisés pour contrôler le tank. Ce nom est renseigné automatiquement dans la méthode Start() et dépend du numéro du joueur auquel le tank appartient. Ainsi, pour chaque joueur, les noms seront différents et ils contrôleront bien chacun leur tank.
III-B-3. Gestion de l'audio▲
Chaque fois que le son du moteur est modifié (si le tank se déplace ou non), le pitch est choisi aléatoirement avec la méthode Random.Range().
Chaque fois que vous modifiez le pitch d'un son, vous devez appeler la méthode Play() pour que le nouveau pitch soit pris en compte.
III-B-4. Jouer▲
Pour que le script fonctionne, il est nécessaire de définir les variables publiques à travers l'inspecteur.
III-B-5. Préfabriqué▲
Nous souhaitons mettre à jour le préfabriqué afin que celui-ci soit composé du script. Pour ce faire, rien de plus simple, sélectionnez le GameObject du tank et cliquez sur le bouton « Apply » dans l'inspecteur. Le préfabriqué source sera ainsi mis à jour avec la nouvelle composition.
IV. Ressources▲
Vous pouvez télécharger le diaporama de la présentation.
Vous pouvez télécharger les ressources pour ce projet sur l'Asset Store de Unity.
V. Commenter▲
Vous pouvez commenter et donner vos avis dans la discussion associée sur le forum.