Ressources Magic Makers

 

Site en maintenance

 
Nous sommes actuellement entrain de mettre à jour les ressources de ce site.
Pendant la mise à jour vous pouvez retrouver tous les nouveaux contenus sur le site
 

https://lp-magicmakers.fr/

 
 

Dialogues et Quêtes

Cette page t’accompagne dans la mise en place d’un système emblématique des jeux de rpg: les dialogues. Rencontrer un personnage, lui parler, faire des choix, et même remplir des quêtes! Tu vas pouvoir apprendre toutes ces choses là en suivant cette fiche ressource!

Voici les quelques notions que tu vas utiliser dans ce guide:

    • Utiliser les ScriptableObjects pour créer des lignes de dialogues
    • Créer un UI pour afficher le dialogue et faire des choix 
    • Interroger l’inventaire pour accomplir des quêtes

 

A propos de ce guide

Ce guide a été créé avec la dernière version stable de Unity au moment de la rédaction (2021.3.19f)

Création du PNJ

Avant de se lancer dans la création d’un système de dialogue, il faut bien un personnage qui va te servir de cobaye! Il est donc temps de créer ton premier PNJ (personnage non jouable)! Ce sont tes PNJs qui vont guider ton joueur tout au long de l’aventure, en discutant avec lui ou en lui confiant des quêtes!

 

Prefab du PNJ

Comme tu sais que ce ne sera pas le seul PNJ que tu peux mettre dans ton jeu, le bon réflexe est de construire un prefab qui te servira de base pour tous tes PNJs! Tu pourras ensuite instancier ce prefab à plusieurs endroits tout en changeant son apparence et ses dialogues!

Construis un PNJ en glissant un sprite dans ta scène! 

Fais-en ensuite un prefab en glissant ce PNJ dans tes assets! Tu vas pouvoir l’ouvrir et travailler dessus pour le reste de l’activité!

Mise en place de l’UI du PNJ

Afin d’afficher une boîte de dialogue qui accompagne le personnage, chacun d’entre eux doit inclure un Canvas. Ce canvas servira de support pour afficher les dialogues, les choix, et même le nom du PNJ! Voici quelques étapes pour le mettre en place de manière à ce qu’il se positionne exactement là où se trouve le personnage: 

 

Mise en place du Canvas

En ouvrant le prefab du PNJ, tu vas pouvoir lui ajouter un canvas! Ce canvas a pour but de contenir tous les éléments d’UI associé à ce PNJ, comme les dialogues! Pour l’instant, essaie juste d’afficher un texte simple avec le nom du personnage! 

Voici comme la structure du prefab se présenterait avec le canvas attaché au PNJ:

Attention! Par défaut, un canvas occupe tout l’écran de ton jeu. Sauf que dans notre cas, nous voulons que le canvas s’affiche à l’endroit où se trouve le PNJ sur la scène! Il va donc falloir passer le render mode du Canvas sur World Space. Cela signifie que cet écran aura une position dans la scène comme n’importe quel autre objet! 

 

Assigne la caméra principale comme étant la Event Caméra, puis n’hésite pas à créer un calque (Sorting Layer) spécialement pour les dialogues pour éviter les superpositions étranges! 

Maintenant que ton canvas est en mode World Space, tu peux désormais placer le canvas de manière à ce qu’il englobe le PNJ en utilisant l’inspecteur et l’outil RectTransform

Observe comment le canvas englobe le PNJ! Prévois l’espace pour afficher la boîte de dialogue, les choix et le nom du PNJ! 

 

Création de la boîte de dialogue

Il est temps de créer la boîte de dialogue! Utilise ce que tu sais grâce au guide sur l’interface utilisateur pour créer dans le canvas du joueur une boîte de dialogue qui te convient! 

Voici quelques conseils:

Crée un objet vide qui va contenir ta boîte de dialogue et ajoutes-y les éléments d’UI (comme le panel pour la couleur de fond et le texte pour le message). Tu n’auras plus qu’à déplacer cet objet pour positionner ta boîte de dialogue et le désactiver pour cacher le dialogue!
Voici un exemple de la structure proposée:

    • Prévois assez d’espace pour contenir un long message qui peut s’étendre sur plusieurs lignes.
    • Expérimente avec les paramètres du texte pour le rendre joli et agréable à lire! Tu peux notamment le centrer horizontalement et verticalement!

Cela devrait te donner quelque chose comme ceci! Remarque que si tu déplaces le PNJ, tout l’UI qui lui est attaché en enfant devrait se déplacer avec! 

Masquer le dialogue quand le joueur s’éloigne

Pour que le dialogue ne s’affiche que lorsque le joueur s’approche du PNJ, il faut que ce dernier puisse détecter le joueur! 


Assigne lui le composant Circle Collider 2D! Augmente le radius du collider pour couvrir la distance que tu préfères pour afficher le dialogue, mais surtout n’oublie pas d’activer le IsTrigger!

Maintenant ajoute lui un nouveau Script! Tu peux l’appeler DialoguePNJ  par exemple!

Crée une variable publique qui référence la boîte de dialogue du PNJ!

Le principe du script est plutôt simple: 

    • Si le joueur entre dans la zone, la cible s’active!
    • Si le joueur sort de la zone, la cible se désactive!

using UnityEngine;


public class DialoguePNJ : MonoBehaviour
{
    public GameObject boiteDialogue; // référence à la boîte de dialogue


    private void Start(){
        boiteDialogue.SetActive(false); // le dialogue commence masqué
    }


    // quand le joueur entre dans la zone
    private void OnTriggerEnter2D(Collider2D other) {
        if (other.CompareTag(« Player »)) {
            boiteDialogue.SetActive(true); // affiche la boite de dialogue
        }
    }


    // quand le joueur sort de la zone
    private void OnTriggerExit2D(Collider2D other) {
        if (other.CompareTag(« Player »)) {
            boiteDialogue.SetActive(false); // masque la boite de dialogue
        }
    }
}

Il ne manque plus qu’à assigner les bonnes variables! La cible à masquer/cacher est le canvas attaché au PNJ!

Attention! Pour que cela fonctionne, pense bien à assigner le tag “Player” au joueur!

Quêtes

Maintenant, voici la partie intéressante: La quête! Tout bon RPG se doit d’avoir des missions à confier au joueur pour le faire explorer le monde! Les quêtes sont généralement confiées par les PNJs. Pour l’exemple, nous allons te guider pour mettre en place le type de quête le plus commun: la quête-livraison. C’est lorsqu’un PNJ te demande de lui trouver un certain objet en échange d’une récompense! 

Avec ceci, tu vas pouvoir créer plein de scénarios différents pour récupérer l’objet: 

  • Il faut explorer le monde pour ramasser les objets
  • Battre des ennemis spécifiques pour récupérer les objets
  • Arriver au bout d’un donjon pour retrouver l’objet

Bref! Il est temps d’intégrer la quête à ton PNJ! 

 

Script de la quête livraison

Il va falloir que tu crées un nouveau script à ton PNJ! Tu peux l’appeler Quete ou bien QueteLivraison si tu prévois de faire plusieurs types de quêtes. 

Ce script a un objectif: vérifier que le joueur possède une quantité suffisante de l’objet demandé. Si c’est le cas, il va accomplir deux choses: 

  • Retirer au joueur la quantité demandée (puisqu’il livre l’objet au PNJ)
  • Changer le texte du dialogue par un message de remerciement

Remarque importante: Tu peux sans doute remarquer une variable item de type ItemData. Si tu te demandes ce qu’est ItemData, c’est le nom du ScriptableObject qu’on a créé pour stocker les objets dans le guide sur l’inventaire. Il se peut que tu aies choisi un nom différent! Si ton jeu n’a pas de système d’inventaire, nous te recommandons très fortement de suivre le guide sur la création d’un inventaire avec les ScriptableObjects

using UnityEngine;
using TMPro; // obligatoire pour utiliser TMP_Text

public class QueteLivraison : MonoBehaviour
{
    public TMP_Text dialogue; // référence vers le texte du dialogue

    [Header(« Quete »)]
    public ItemData item; // référence vers l’objet demandé par le pnj
    public int requis; // quantité de cet objet nécessaire pour remplir la quête
    public string messageDeFin; // message qui s’affiche lorsque la quête est terminée!

    // booléen qui se souvient si la quête a déjà été terminée (→true) ou pas (→ false)
    private bool terminee;

    // lorsque le joueur entre en collision avec le trigger du PNJ
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag(« Player »))
        {
            // On vérifie d’abord si la quête n’a pas déjà été remplie
            if (terminee == false)
            {
                // On vérifie si le joueur possède une quantité suffisante de l’objet requis
                if (item.quantite >= requis)
                {
                    terminee = true; // Pour se souvenir que la quete est terminée
                    dialogue.SetText(messageDeFin); // Change le dialogue par le message de fin
                    item.quantite -= requis; // On retire la quantité qu’on donne au PNJ
                }
            }
        }
    }
}

Bien évidemment, il ne faut pas oublier d’assigner les bonnes variables dans l’inspecteur!

Tu peux désormais lancer ton jeu et constater que ton PNJ change de réplique une fois que tu lui as apporté les objets qu’il demandait! 

 

Récompense

C’est bien beau de faire le livreur mais sans récompense il n’y a pas grand intérêt! Toujours sur le même script de QueteLivraison, ajoute deux nouvelles variables publiques:

  • Une référence vers l’objet qui sera donné en récompense
  • Un entier pour indiquer la quantité de cet objet

public ItemData recompenseItem; // objet à donner en récompense de la quête
public int recompenseQuantite; // quantité de cet objet

Enfin, tu vas pouvoir écrire ce bout de code  l’intérieur des conditions, juste après les lignes qui permettent de changer le dialogue par le message de fin et de retirer l’objet de la quête:

recompenseItem.quantite += recompenseQuantite;

N’oublie pas d’assigner les bonnes variables dans l’inspecteur! Sur cet exemple, le PNJ offre 10 pièces en échange de 3 flèches:

Script final de la quête

Si tu as bien suivi les étapes, le script final de la quête devrait ressembler à ça! Tu peux l’assigner à tous les PNJs qui ont une requête d’objet auprès du joueur! 

using UnityEngine;
using TMPro;

public class QueteLivraison : MonoBehaviour
{
    public TMP_Text dialogue;
    private bool terminee;

    [Header(« Quete »)]
    public ItemData item;
    public int requis;
    public string messageDeFin;

    [Header(« Recompense »)]
    public ItemData recompenseItem; // objet à donner en récompense de la quête
    public int recompenseQuantite; // quantité de cet objet


    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag(« Player »))
        {
            if (terminee == false && item.quantite >= requis)
            {
                terminee = true;
                dialogue.SetText(messageDeFin);
                item.quantite -= requis;

 

                // On ajoute à l’objet de récompense la quantité offerte par le PNJ
                recompenseItem.quantite += recompenseQuantite;             }
        }
    }
}

Si tu te sens à l’aise, n’hésite pas à t’inspirer de ce script pour écrire d’autres types de quêtes! Tu peux par exemple, écrire une quête qui demande de battre un certain nombre d’ennemis, ou une autre qui demande d’aller parler à un personnage spécifique ou même d’arriver au bout d’un donjon! La principale différence sera la condition pour remplir la quête mais le principe est similaire!