Unity - Tanks

Création et contrôle du tank

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

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 :

 
Sélectionnez
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.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2016 Unity Technologies. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.