Catégories
Tutoriel Unity

Tutoriel Unity 3d – Utilisation des Raycast

Dans ce tutoriel, nous allons appréhender l’utilisation des Raycast sous Unity3D.

Définition d’un Raycast

Tout d’abord, vous pouvez vous demander ce qu’est un Raycast. Pour faire simple, on pourrait comparer le Raycast à un faisceau lumineux allant en ligne droite sur une distance donnée.

Ce faisceau va nous permettre de vérifier s’il rentre en contact avec un autre objet, un tag ou des calques. Vous aurez la possibilité de filtrer très finement la collision du Raycast. En effet, il fait parti des fonctionnalités liées à la physique de Unity3D.

Avec les Raycast, vous allez pouvoir gérer un grand nombre de chose.
Je vous donne quelques exemples :

 

  • Vérifier une distance entre le joueur et un objet/sol
  • Créer un système de visé pour vos armes
  • Système de vision à la Metal Gear Solid, pour détecter le joueur

 

  • Améliorer les collisions. Il n’est pas nécessaire de savoir les utiliser, mais je trouve que cela aide au développement de vos jeux. Les raycasts peuvent être utilisés autant pour les jeux en 3D qu’en 2D.

Présentation du tutoriel

Dans cet exemple, nous allons faire en sorte de détecter si notre joueur est sur le sol ou non. S’il se trouve sur le sol, il peut sauter.
Nous utiliserons les raycasts dans un projet en 3D, mais la procédure est la même en 2D. La seule chose qui change est le nom des classes utilisées, il faut ajouter 2D à la fin et gérer la Physic 2D.

Je ne vous montrerai pas comment faire un système de saut poussé, mais nous en verrons un simple, en utilisant la physique liée aux RigidBody.

Pour cela, commencez par créer ou ouvrir votre projet Unity3D.

Création de la Scene

Pour ce tutoriel, nous allons avoir besoin de beaucoup de choses: une scène, un sol et un joueur.
Pour le sol, un Plane fera l’affaire.

Création du joueur

Nous allons créer une capsule qui fera office de joueur et lui ajouter un composant RigidBody. Ce composant permet de gérer la physique de l’objet.
Pour éviter d’avoir un résultat un peu bizarre lors de notre test, il faudra cocher dans Constraints, Freeze Rotation X, Y et Z.

Vous devriez donc avoir une scène ressemblant à ça :

Tutoriel Raycast - étape 1

Le script

Maintenant que nous avons tous les éléments nécessaires à notre exemple, il est temps d’écrire quelques lignes de code pour faire fonctionner tout ça.

Je reprends la problématique: nous voulons faire sauter notre joueur, mais uniquement si celui-ci n’est pas déjà en train de sauter.

Pour commencer nous allons donc mettre en place le système de saut en créant un scriptPlayerController. Pour cela, il suffit de faire clique droit, Create > C# Script et de saisir le nom du fichier. Faites le glisser sur le joueur puis double cliquez dessus pour l’ouvrir dans l’éditeur.

(Petite parenthèse, pour l’éditeur, je vous conseille d’installer Visual Studio qui plus agréable pour développer (selon moi) que MonoDevelop.)

using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
[SerializeField]
private float jumpPower;
private Rigidbody rb;

void Start()
{
rb = GetComponent<Rigidbody>();
}

void Update()
{
if (Input.GetButtonDown("Jump"))
{
rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
}
}
}

Alors à votre avis, quelle est l’utilité de ce bout de code ?
Eh bien, RequireComponent(typeof(Rigidbody)) est simplement une contrainte pour forcer le joueur à toujours avoir un RigidBody.
Cette ligne n’est pas obligatoire, mais quand on développe, elle peut être utile car cela évite les erreurs si vous oubliez un composant sur un objet.

[SerializeField] private float jumpPower; cette ligne sert à respecter la programmation orientée objet.SerializeField permet d’afficher la valeur jumpPower dans l’éditeur même si celle-ci est privée.jumpPower nous détermine la puissance du saut réalisé par le joueur.

On aurait pu écrire : public float jumpPower;

rb = GetComponent<Rigidbody>(); on récupère le composant RigidBody du joueur.

Pour ce qui est de la partie Update, on détecte si le bouton saut est appuyé (Jump est configuré dansProject Settings > Input). rb.AddForce fait sauter vers le haut en fonction de la variable jumpPower et le type de force appliqué est une impulsion.

Implémenter le Raycast

Waou c’est super, on a un personnage qui saute!!!!!  Mais le problème … c’est qu’il peut sauter indéfiniment ! Avec le code ci-dessous, on va pouvoir détecter le sol et corriger cela.


using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
    [SerializeField]
    private float jumpPower;
    [SerializeField]
    private float rayDistance;
    [SerializeField]
    private LayerMask layers;
    private Rigidbody rb;
    private bool grounded;

    void Start()
    {
        rb = GetComponent();
    }

    void Update()
    {
        RaycastHit hit;
        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, rayDistance, layers))
        {
            grounded = true;
        }
        else
        {
            grounded = false;
        }

        if (grounded && Input.GetButtonDown("Jump"))
        {
            rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
        }
    }
}

rayDistance correspond à la distance max du Raycast, la longueur du faisceau.
layers est la liste des calques liés à la physique, pour l’exemple, nous utiliserons le layer Default.
grounded est la variable qui détermine si on touche le sol ou non.
Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, rayDistance, layers)) est le test de collision. On va commencé par récupèrer la position du joueur, avant de déterminer, dans quelle direction le Raycast va être projeté. Puis, on va stocker les données dans la variable hit pour la traiter plus tard, sans oublier d’appliquer la distance et de donner la liste des layers.

Dans l’éditeur, sur le joueur vous pourrez sélectionner les layers utilisés.

Voici les valeurs que j’ai renseignées dans l’éditeur :

Raycast

Débugger les Raycast

Après avoir mis en place le système de Raycast, nous allons regarder s’ils sont projetés correctement. Pour cela nous allons ajouter cette ligne dans Update() :
Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.down) * rayDistance, Color.red);

Vous pouvez remarquer que les paramètres sont les mêmes que pour le Raycast.

Si on lance le jeu et que l’on saute puis que l’on regarde le jeu dans l’onglet Scene, on peut voir notre Raycast sous forme de ligne rouge :

Raycast

Voici le code complet pour le joueur :


using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class PlayerController : MonoBehaviour
{
    [SerializeField]
    private float jumpPower;
    [SerializeField]
    private float rayDistance;
    [SerializeField]
    private LayerMask layers;
    private Rigidbody rb;
    private bool grounded;

    void Start()
    {
        rb = GetComponent();
    }

    void Update()
    {
        RaycastHit hit;
         Debug.DrawRay(transform.position, transform.TransformDirection(Vector3.down) * rayDistance, Color.red);
        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.down), out hit, rayDistance, layers))
        {
            grounded = true;
        }
        else
        {
            grounded = false;
        }

        if (grounded && Input.GetButtonDown("Jump"))
        {
            rb.AddForce(Vector3.up * jumpPower, ForceMode.Impulse);
        }
    }
}

Conclusion

Comme je vous le disais plus haut, les possibilités d’utilisations sont variées.

Le code source du tutoriel se trouve ici. Si vous avez besoin de précisions, n’hésitez pas à me le faire remonter que je complète le tutoriel pour plus de clarté.

Par Shinochi

Développeur Web Fullstack expert Drupal 8, et otaku par la même occasion.

Passionné par le japon, je partage quelques critiques sur les animes et mangas que j'ai regardé.
Je développe des jeux sur Unity3D à mes heures perdue.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.