Space Invaders - Créer son premier Jeu

Dans cette activité les makers créent un jeu de tir spatial en vue de dessus avec Unity, Fortement inspiré par le célèbre Space Invaders!

Objectifs pédagogiques

Le but de cette activité est de poursuivre la découverte du logiciel Unity, entamée par le projet de Bac à Sable en incluant cette fois des mécaniques de jeu! C’est un projet guidé simple à prendre en main pour permettre aux makers de créer et publier leur premier jeu vidéo 2D!

Compétences techniques

  • Ajout de comportements personnalisés via l’écriture de scripts C#
  • Contrôler le joueur en récupérant ses commandes par la manette ou les touches du clavier
  • Apprendre à combiner différents composants pour définir un comportement plus complexe
  • Prise en main des prefabs et leur utilisation pour créer des instances d’ennemis, d’obstacles, collectables…
  • Intégrer de l’aléatoire dans les mécaniques de jeu
  • Détecter les collisions entre objets 2D et déclencher des événements
  • Faire apparaître ou détruire un objet à travers le code

Compétences design

  • Importation des sprites dans la scène de jeu

Compétences projet

  • Création d’un projet 2D sur Unity
  • Exporter un jeu sur sa machine et le publier en ligne

La place dans le module

Cette activité vient après l’activité Bac à Sable et avant l’activité Jeu de tir spatial (Exploration). 

Vu que les makers ont déjà pris en main l’interface de Unity avec l’activité précédente, nous leur proposons de créer leur premier jeu vidéo 2D: Le Space Invaders. C’est un projet guidé, qui se concentre sur le fait d’introduire les notions importantes plutôt que de laisser libre la créativité du maker (ce qui sera le cas pour le second space shooter.)

Jour 1

Jour 2

Jour 3

Jour 4

Jour 5

1h

🤩

🤩

🤩

30 min

🤩

🤩

🤩

30 min

🤩

🤩

🤩

🤩

1h

🤩

🤩

🤩

🤩

Matériel

  • Un ordinateur suffisamment puissant/récent pour faire tourner les dernières versions de Unity. (Mac ou Windows)
  • Unity Hub avec une version récente de Unity

Déroulé de l'activité

Segment 1 (30 min) : Démonstration du projet, création du joueur et contrôles

1/ Démonstration du Space Invaders (15 minutes)

Le premier temps est dédié à la présentation du projet Space Invaders

Commence par leur faire faire un nouveau projet, cette fois de type Universal 2D (très important!!). Puis c’est le moment où tu montres aux makers des exemples de ce qu’ils vont produire dans cette activité. Commence par leur faire une démonstration du jeu d’exemple, et même des réalisations des makers précédents (à venir)

Après la séquence démo, définit ensuite une liste des mécaniques que vous allez reproduire ensemble:
  • Un joueur qui se déplace de gauche à droite à l’aide du clavier
  • Des obstacles aléatoires défilant de bas en haut, à détruire ou à éviter
  • Des objets à ramasser

Un space shooter est un jeu en vue du dessus où le joueur incarne un vaisseau et doit tirer sur des ennemis tout en évitant des obstacles! C’est un grand classique de l’histoire du jeu vidéo! 

Astuce: 

Même si le projet s’appelle Space Invaders, les makers ne sont pas dans l’obligation de faire un jeu de tir spatial! Le décor, le vaisseau et les obstacles peuvent être remplacés par n’importe quels autres assets disponibles tant que les mécaniques restent les mêmes!

2/ Création du personnage (15 minutes)

Faire créer au makers un sprite (forme n’importe) avec un rigidbody2D et un collider2D appropriée. Le renommer de façon appropriée aussi.
Son Rigidbody2D doit avoir une gravitée à 0 (sinon il va tomber dans le vide!)

Ce sera le personnage. On lui mettra une meilleur images plus tard. 

On commence par le script pour que la camera suive le joueur parce qu’il est plus court et permet de reviser les choses vuent avant.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BougeCamera : MonoBehaviour
{
     public Transform joueur;

    void Update()
    {
        transform.position = new Vector3(joueur.position.x,joueur.position.y,-10);
    }
}

On le met sur la camera, on met le joueur dans la case du script, et la camera nous suivra

Segment 2 (1 h) : Mouvement/Graphismes

1/ Mouvements du joueur (20 minutes)

Creer un nouveau script “BougePerso” (exemple de nom, a vous de voir) et le mettre sur le perso.

Accompagner les makers dans l’écriture du script avec nouvelles notions:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BougeJoueur : MonoBehaviour
{
    public float vitesse;

    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
       
        Vector3 movement = (Vector3.right * horizontal + Vector3.up * vertical) * vitesse * Time.deltaTime;
        GetComponent<Rigidbody2D>().velocity = movement;
    }
}
  • float horizontal : variable temporaire créée dans Update pour stocker des infos. Elle ne sert que à cet endroit du code et on ne peut pas y accéder ailleur
  • Input.GetAxis: récupère tous les boutons liés à un Axe (selon le nom de l’axe) et leur donne une valeur de 1 (droite) à -1 (gauche). 0 quand rien n’est appuyé
  • Vector3 mouvement: on bosse en 2D mais la zone de jeu est en 3D donc on créer un mouvement techniquement sur 3 axes.
  • transform.right (ou up) * horizontal (ou vertical) on combine les inputs avec les direction du joueur et on multiplie le tout par la vitesse
  • rigidbody.velocity = movement : on applique le mouvement calculé sur le rigidbody du joueur

 

Une fois débugger, on peut tester tout de suite si ça marche ne donnant juste une vitesse au joueur dans la case vitesse de son script

2/ Viser à la souris (15 minutes)

Ok, le perso bouge, la camera suit, maintenant on veut viser vers la souris. Donc nouveau script encore, avec nouvelle notion.

Ce script servira à viser, il va sur le joueur

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class VISER : MonoBehaviour
{
    public Camera maCamera;

    void Update()
    {
        Vector3 mousePosition = maCamera.ScreenToWorldPoint(Input.mousePosition);
        mousePosition.z = 0;

        transform.up = mousePosition - transform.position;
    }
}
  • ScreenToWorldPoint: la souris n’existe techniquement pas dans le jeu, donc on converti sa position dans la fenêtre de jeu, en position dans l’espace du jeu. ce calcul passe par la camera vu que c’est elle qui affiche le jeu
  • mousePosition.z = 0  vu qu’on est en 2D on doit aligner la position obtenue pour la souris, avec les autres objets 2d du jeu
  • la dernière ligne sert à faire tourner le joueur pour qu’il fixe le point de position de la souris

On retourne dans unity et on met la Camera dans la case Camera du script.

Debugger, tester, le personnage doit tourner pour suivre la souris.

3/ Graphismes et balle (25 minutes)

Avant de finir le tir on va rendre tous ça un peu joli:

Notion importante: dans les jeux vidéos il y a une séparation entre la partie physique et les graphisme. La hitbox et le dessin du personnage ne sont pas lié, et on peut donc ajuster l’un sans toucher l’autre. c’est super important pour les animations et une bonne habitude à prendre!

Jusqu’a maintenant on a tout mis sur le même objet, mais ça va changer.

Pour pouvoir facilement changer les graphismes (animation) du perso sans avoir à changer plein de trucs tout le temps, on va fabriquer un sprite 2D enfant de l’objet personnage.
C’est ce sprite a partir de maintenant qui aura le renderer.

Le personnage doit donc ressembler à ça:

Les makers peuvent ensuite choisir une image pour leur perso sur google ou sur le site ressource, et la tirer d’abord dans le dossier unity pour la mettre dans le projet, puis depuis ce dossier dans la case du renderer qui gère la texture du perso:

Une fois l’image choisie et mise, il faudra s’assurer d’avoir un polygon collider2D sur le joueur et ajuster sa forme avec le bouton du collider:

ce bouton permet de rendre le polygon collider malléable, on peut attraper les segments du collider et les bouger pour coller au personnage grosso modo.
exemple:

SI LA FORME DU PERSO EST VRAIMENT ULTRA SIMPLE ON PEUT RESTER SUR UN COLLIDER2D CUBE OU SPHERE!

Segment 3 (1 h) : Tir et Enemy

1/ Preparations (10 minutes)

On commence par créer un projectile que le joueur va tirer. On fait un nouveau sprite, on l’appelle “projectile” ou “balle”

On lui met pas d’image desuite, on fait juste un rond rouge pour l’instant, avec collider2D (dont on coche la case « Trigger » ce qui permet de detecter les collisions sans rendre la balle solide et donc de ne pas avoir de « recul » quand on tir) et rigidbody2D 

On sauvegarde cette balle dans un dossier du projet en la tirant dedans depuis la liste des objets (hiérarchie), pour l’avoir pour plus tard. ça s’appelle faire un “préfab”. C’est pratique pour stocker des objets qu’on doit generer pendant le jeu.

2/ Script (20 minutes)

On créer ensuite un nouveau script « Tir » pour ajouter le code qui va générer les balles et les envoyer.

Ce script n’ira pas sur le joueur comme les autres mais sur un nouvel objet (un sprite ou un empty) que l’on placera au point de départ du tir, la d’ou la balle doit sortir et tourné pour que la flèche verte (l’avant de l’objet) pointe dans la bonne direction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

 

public class TIR : MonoBehaviour
{
    public GameObject maBalle;
    public float puissance;

 

    void Update()
    {
        if(Input.GetButtonDown("Fire1")){
            GameObject balle = Instantiate(maBalle,transform.position,transform.rotation);
            balle.GetComponent<Rigidbody2D>().AddForce(transform.up * puissance, ForceMode2D.Impulse);
        }
    }
}
  • public GameObject maBalle: la balle qu’on a rangée dans les dossier ira dans cette case.
  • public float puissance: la force avec laquelle on envoi la balle
  • If Input GetButtonDown (“Fire1”): GetButtonDown est detecté une seule fois par clic. pour eviter le spam de tir. Fire1 c’est le nom du clic gauche dans unity.
  • GameObject balle: nom temporaire donné à la balle qu’on génère.
  • Instantiate: pour generer un truc. On met dans les () un objet qui sert de modèle pour la generation, la position de generation et l’angle de l’objet quand il est generé
  • AddForce: ajoute de la poussée à la balle au départ. La direction de la poussé est vers l’avant de l’objet

De retour dans unity, on met le prefab de la balle (la version de la balle qu’on a rangé dans nos dossier) dans la case « ma Balle » du script. On indique aussi la puissance du tir.

On commence à être pas mal!

Maintenant qu’on peut tirer on va vouloir des ennemis!

3/ Enemy (25 minutes)

Donc nouveau sprite, avec un collider 2D.

(Si on animes les ennemis il faudra faire comme pour le joueur et séparer le renderer en sous-objet)

L’enemis n’a pas besoin de rigidbody car lui ne sera pas soumis à la physique. Et le rigidbody necessaire aux collisions est déjà sur le joueur et sur la balle.

On ajoute sur ce sprite un premier script, pour des mouvements très simple: l’ennemis va traverser l’écran en ligne droite, en mode bélier

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Belier : MonoBehaviour
{
    public float vitesse;

    void Update()
    {
        transform.Translate(Vector3.up * vitesse * Time.deltaTime);
    }
}
  • transform.Translate: autre façon de faire un mouvement, n’utilise pas la physique donc n’est pas contraint par la physique (sauf collision). Donc pas de recul, pas de gravité etc.
  • Vector3.up permettra à l’enemi d’avancer vers son « haut ». Ce qui fait que si on tourne l’enemi il avancera dans une autre direction. Combiné avec le spawner juste après, l’enemi sera envoyé dans la direction choisie par le spawner.
Une fois que l’enemi est préparé on en fait un préfab pour la suite.

Segment 4 (30 min) : Spawner

1/ Scripter le spawner (20 minutes)

C’est pas tout d’avoir 1 ennemi, on en veut plein! qui apparaissent pendant le jeu, donc spawner!

On met un empty dans son niveau a l’endroit d’ou on voudra que les enemies apparaissent, puis on fait un nouveau script “Spawner”

La notion importante ici c’est le timer.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class spawner : MonoBehaviour
{
    public float chrono_initial;
    float chrono;
    public GameObject monEnemy;

    void Start()
    {
        chrono = chrono_initial;
    }

    void Update()
    {
        chrono -= Time.deltaTime;

        if(chrono<=0)
        {
            GameObject enemy = Instantiate(monEnemy,transform.position,transform.rotation);
            chrono = chrono_initial;
        }
       
    }
}
  • le timer à 2 valeures: 1 pour faire le calcul du compte à rebours et l’autre pour choisir facilement la durée et reset le timer quand il est fini
  • Dans start on reset le timer une première fois pour le lancer
  • dans Update on fait tourner le timer en retirant le Time.deltaTime au chrono
  • if chrono <= 0  : quand le chrono atteint ou passe sous 0 on lance le code:
    • instantiate: fait apparaitre l’enemi
    • on reset le chrono

On s’assure que le spawner à bien le script et que les paramètres du scripts sont indiqué (la case enemi remplie etc) et que le spawner est tourné dans la direction ou on veut envoyer l’ennemi (la flèche verte en mode local)

2/ Tests (10 minutes)

On laisse les makers experimenter, avec plusieurs spawner, qui envoi des enemis a plusieurs vitesse, plusieurs chrono, plusieurs directions différentes

Segment 5 (30 min) : Avancée libre

Maintenant que le jeu commence à marcher, laisser les makers du temps pour

  • debugger
  • tester les vitesse
  • changer les graphismes

30 minutes pour souffler, rattraper, ajuster etc.

Si votre groupe n’a rien a rattraper ou ajuster, ou si ils sont très rapide vous pouvez leur montrer ce script pour des enemies à tête chercheuse: (a mettre à la place du script belier).
Attention: cette ennemy cherchera un joueur qui s’appelle « Joueur ». Si un maker à nommé son joueur autre chose, il faudra utiliser cet autre nom dans le Find.

Attention bis: Ce script va sur le PREFAB de l’enemi (dans les dossiers) sinon un seul enemi sera à tête chercheuse! Ne pas oublier une fois le script mis, de bien indiquer une vitesse!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TeteChercheuse : MonoBehaviour
{
    public float vitesse;
    GameObject cible;
   
    void Start()
    {
        cible = GameObject.Find("Joueur");
    }

    void Update()
    {
         transform.position = Vector3.MoveTowards(transform.position, cible.transform.position, vitesse * Time.deltaTime);
    }
}

Segment 6 (1 h) : PVs

Maintenant qu’on a des ennemis, et des tirs, on va faire un peu de destruction.

1/ Nettoyage/Auto-destruction (10 minutes)

On commence par un script super court, pour auto-détruire les balles et enemis qui serait hors écran avec un timer:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class autodestruction : MonoBehaviour
{
    public float temps;

    void Start()
    {
        Destroy(this.gameObject,temps);
    }

}
  • Une variable pour gérer le delaie avant destruction
  • Destroy, qui a comme paramètre l’objet a détruire et le temps avant sa destruction

On met le script sur les prefabs (les versions des objets sauvées dans les dossiers) de l’ennemi et de la balle, avec un temps suffisant pour traverser l’écran mais être détruit après en être sorti. (environ 10 secondes)

2/ PV enemies (15 minutes)

On ajoute sur les enemies un script pour leur points de vie. On utilise un nouveau type de detection de collision qui fonctionne avec les colliders en mode « Trigger » (comme notre balle)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PVenemy : MonoBehaviour
{
    public int pv;

    public GameObject son_mort;


    private void OnTriggerEnter2D(Collider2D other) {
        if(other.transform.name.Contains("Projectile")){
        pv -= 1;
        Destroy(other.gameObject);
        }
        if(pv <= 0)
        {
            Destroy(this.gameObject);
        }

    }
}
  • Une variable pour compter les pv
  • OnTriggerEnter se déclenche 1 fois en début de collision, et other est l’objet qui nous a touché
  • on verifie si l’objet qui nous touche est une balle
  • pv -= 1    on enlève 1 pv (ou plus, selon choix)
  • on détruit la balle
  • Si on a 0 ou moins de pv, destruction de l’enemi
2/ PV joueurs (30 minutes)

Pour les pvs du joueurs on va faire un script très similaire, sauf que on ne va pas détruire le joueur (sinon le jeu va bugger)
A la place on va dire au jeu de charger un niveau.

Pour l’instant on en a qu’un, donc on re-chargera le niveau actuel mais après on pourra faire des écrans game over.

On va voir 2 nouvelles notions ici: les scènes, et les tags

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class PVjoueur : MonoBehaviour
{
    public int vie;
    public string niveau;

void OnCollisionEnter2D(Collision2D other)
{
    if (other.transform.tag == "enemy")
    {
        vie -= 1 ;
    }
    if(vie <= 0)
    {
        SceneManager.LoadScene(niveau);
    }

}

}
 
  • Tout en haut on a un nouvel using: SceneManagement, qui permet d’utiliser le gestionnaire de niveau
  • On identifie les enemies lors de la collision grace à un tag. Le tag c’est une étiquette qu’on va mettre sur nos enemis, et qui permet, même si on a des enemis très différents, de les identifier tous comme des enemis directement

Quand le joueur est touché il perd 1 pv (ou plus, choix libre), si il n’a plus de PV on utilise le gestionnaire pour charger un niveau.

Dans Unity on indiquera dans la case « Niveau » le nom du niveau à charger.
Encore une fois pour l’instant on n’a qu’un seul niveau: SampleScene

Pour ajouter un tag, on selectionne l’objet (pour nous l’enemi dans son dossier) et en haut on ouvre le menu de tag

si le tag voulu n’existe pas on le crée avec “add tag”

(attention: un tag qu’on vient de crée ne s’ajoute pas, il faut retourner sur l’objet pour l’ajouter pour de bon)

il ne reste plus qu’à choisir les pv initiaux du joueur et de l’enemi (sur les prefabs pour l’enemi)

Si il reste du temps laisser les makers tester, et arranger leurs enemis, PV etc.

Segment 7 (1 h) : Affichage des PVs et Score

On va creer une barre pour afficher les PVs

1/ Canvas (10 minutes)

On montre aux makers comment créer des elements d’UI, comme des boutons, des images etc.

On leur explique ce qu’est le canva (le support d’affichage de l’UI)

On leur montre comment régler le canvas pour que l’affichage se fasse correctement:

Le render mode est a choisir en fonction du jeu:

  • Screen space: singleplayer
  • Camera space: multiplayer
  • World space: elements spéciaux comme les marqueur de quete au dessus des têtes de personnage etc

Dans 99% des cas, pour nous à Magic, Screen Space est le bon.

Additional shader et Vertex color permettent d’enlever les warnings mais sont optionels

UI scale mode: pour que l’UI soit proportionnelle à l’écran, et en dessous si la proportion doit en priorité suivre la largeur, la hauteur, ou un mix des 2.

2/ Barre de vie (30 minutes)

La barre de vie va en fait être une barre de progression (slider) avec les elements interactif supprimé.

On ne garde que Background et Fill et on sort Fill de son parent pour qu’il soit directement dans slider

Les makers peuvent ensuite choisir une couleur de fond, et de barre, et ajuster la longer de Fill quand la barre est pleine pour ne pas depasser:

Le code est super simple, on va modifier un peu le script de PVs du joueur:

On va avoir une variable pour accéder à la barre et on dit a unity de la mettre a jour dans update:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class PVjoueur : MonoBehaviour
{
    public int vie;
    public string niveau;
    public Slider barre_vie;

    void Update(){
        barre_vie.value = vie;
    }

void OnCollisionEnter2D(Collision2D other)
{
    if (other.transform.tag == "enemy")
    {
        vie -= 1 ;
    }
    if(vie <= 0)
    {
        SceneManager.LoadScene(niveau);
    }

}

}
 
3/ Score (20 minutes)

On va ajouter maintenant un script pour compter les points et les afficher dans un Texte. Ce script ira sur le joueur, et il faudra créer un UI texte pour l’utiliser.

Même menu que les barres de vie, on choisi juste l’option TextMeshPro. Plus d’infos sur la page ressource

TMPro: le plugin en charge des textes. Si besoin, si unity le demande quand on créer un texte, il faut l’importer (c’est super rapide)

Ensuite on fait le script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Score : MonoBehaviour
{
    public static int points;
    public TMPro.TMP_Text affichage;

    void Start()
    {
        points = 0;
    }

    void Update()
    {
        affichage.text = points.ToString();
    }
}

Ici la nouvelle notion principale c’est « Static« 
Une valeur static est considérée par Unity comme unique, et peut être utilisée n’importe ou sans avoir besoin d’indiquer un objet auquel elle est liée. Par contre elle a comme inconvenient:

  • de ne pas apparaitre dans l’inspecteur. Jamais.
  • de bugger si on met le script de Score plusieurs fois dans le jeu.
Pour gagner des points il faut rajouter cette ligne:
Score.points += 1;

Dans le script de PV enemy, juste avant la ligne ou l’enemi est détruit quand il a 0 pv.

Ensuite si il reste du temps, laisser les makers ajuster leur barre de vie etc.

Segment 8 (30 min) : Menu

On va creer un menu et son script pour lancer le jeu et apprendre à utiliser des boutons. 

1/ Création du menu (10 minutes)

APRES S’ÊTRE ASSUREE QUE LES MAKERS ONT SAUVEES LEUR NIVEAU:

On montre aux makers comment creer une nouvelle scene, que l’on appelle Menu, et à l’interieur comment créer des boutons.

La décoration (image, texte de titre etc) serait faite plus tard, il y aura un temps pour ça juste après.

2/ Script du menu (10 minutes)

Le script en lui-même est simple: chaque bouton a une fonction, dans laquelle on code ce que le bouton doit faire. Il se place sur un élement unique de la scène, pour le retrouver facilement. (exemple: en général je le met sur le Canvas)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

 

public class Menu : MonoBehaviour
{
    public void RetourMenu(){
       
        SceneManager.LoadScene("menu");

 

    }

 

     public void LancerJeu(){
       
       SceneManager.LoadScene("niveau1");

 

    }
}
3/ Utiliser le script (10 minutes)

Sur le bouton, on va ajouter une action, et c’est par cette action que le bouton va utiliser le script:

  1. creer action
  2. mettre l’objet qui a le script de menu dans la case (ici le canvas)
  3. cliquer sur “No function” pour choisir le script, puis la fonction, que ce bouton va faire

Segment 9 (30 min) : Avancée Libre

Laisser les makers du temps pour

  • debugger
  • tester
  • ajuster
  • decorer etc

30 minutes pour souffler, rattrapper, etc.

Segment 10 (60 min) : Juiciness, Sons

Dans ce segments et ceux à venir, vous pourrez adapter selon le niveau du groupe en montrant plus ou moins de choses. Je noterais en début de segment à quel point il est optionel. Si votre groupe est en retard, remplacer par de l’avancée de projet.

On va commencer à s’intéresser aux sons! Les sons peuvent ajouter pas mal de peps à un jeu donc je déconseille de les zapper, mais par contre vous pouvez limiter le nombre de sons que les makers vont chercher à avoir pour l’instant.

1/ Audio Source (5 minutes)

Pour avoir un son dans Unity on doit avoir:

  • une source sonore (un objet qui lance le son)
  • un objet capable d’entendre (par défaut la caméra le peut donc rien à changer ici)
  • un fichier de son à jouer

Il existe 2 façon de jouer un son: automatique (musique d’ambiance etc), et scriptée (son de tir, de mort etc)
Dans les 2 cas, on a besoin d’un objet avec un component: Audio Source.
J’explique ici les propriétés qu’on va utiliser et quelques une qui sont intéressantes mais optionnelles

  • AudioClip: le son a jouer
  • Mute: couper le son
  • Play On Awake: le son démarre dès que l’objet est en jeu
  • Loop: le son se répète quand il se termine
  • Priority: quand plusieurs sons jouent en même temps, lequel s’entend mieux. Utile pour dialogue par exemple
  • Volume: 😛
  • Pitch: effet chipmunk
  • Stereo: si casque, entend mieux a gauche ou droite
  • Spatial: on entend le son de partout (2D) ou seulement dans une zone (3D). Si zone: on peut changer sa taille, symbolisé par 2 sphere autour de la source du son. Le son s’entend entre les 2 sphères, pas ailleurs.
2/ Recherches de sons (15 minutes)

Donner aux makers des sites de références de sons, les aider à télécharger si besoin (YT2MP3), puis les laisser mettre en place leurs sons.

Il faut, a minima:

  • une ambiance (musique ou non)
  • un son de tir (pew pew)
  • un son de dégats (ugh)
  • un son de mort (aaarrrg)

sites:

  • Freesound
    utilisateur: MagicMakersM
    mdp: magicson
3/ Musique de fond (5 minutes)

Pour une musique de fond, on va juste cocher “Loop” ainsi que « Play on Awake » (si il ne l’est pas déjà) et mettre le fichier de musique dans la case AudioClip.

4/ Effets sonore (15 minutes)

Pour les effest sonores, si c’est un son à joueur une seule fois sur un objet qui spawn, on peut le traiter comme une musique.
Exemple: le tir, on met sur la balle un Audio Source, le son dans la case Clip, « Play on Awake » coché, par contre « Loop » décoché.
Quand la balle spawn, elle joue le son de tir.

Si c’est un son qui est déclenché par autre chose, on doit utiliser le script, pour jouer le son au bon moment. Cela se résume à 2 ligne, qu’il faut juste bien placer:

public AudioSource mon_son; //a mettre en haut du script pour choisir le son

mon_son.Play(); //a mettre dans le script quand on veut declencher le son

Exemple à droite: si un ennemi est touché, il fait « ugh »

On a modifier le script de pv ennemi pour que ça marche:

5/ Spécial: le son de mort (15 minutes)

Attention! Un objet détruit ne peut pas jouer de son!
Pour un ennemi par exemple, si on veut un son de mort, il va falloir faire un système spécial.

On va créer un prefab, un objet Empty qui n’aura que 2 component: l’audio source et le script d’auto destruction
Sur l’audio source on aura « Loop » décoché, et « Play on Awake » coché

Au moment de la mort ennemi on spawnera cet objet spécial, qui jouera le son puis s’auto détruira:

if(pv <= 0)
        {
            Score.points += points;
            Instantiate(son_mort,transform.position,transform.rotation);
            Destroy(this.gameObject);
        }

Segment 11 (60 min) : Juiciness, Particules

On va s’attaquer au particules! Les particules sont des effets visuels. Elles peuvent être interessantes pour donner du peps au jeux, mais on peut s’en passer si le groupe est très en retard.

1/ Création des particules (10 minutes)

Montrer aux makers comment créer des particules avec le composant.

Expliquer les paramètres principaux, référer à la fiche maker sur le sujet:

https://lp-magicmakers.fr/accueil/ressources-makers/menu-unity/effets-waouh/particules/

La 2D et 3D fonctionnent à l’identique pour ce sujet

ATTENTION: l’objet porteur de particule doit être tourné à -90 en X, pour que les particules soit dans le bon axe en 2D

2/ Code des particules (10 minutes)

Le code des particules pour les lancer pendant le jeu est super simple, et très similaire aux sons.

Il faut référencer l’objet porteur de particules dans le script puis simplement dire Play ou Stop:

public ParticleSystem mes_particules;//a mettre en debut du code pour declarer les particules
mes_particules.Play();// a mettre dans le code la ou l'on déclenche les particules
mes_particules.Stop();// a mettre dans le code la ou l'on arrête les particules
3/ Exemples des particules (10 minutes)

Afficher à l’écran quelques exemples de paramètres de particules (pour faire des flammes, ou de la pluie par exemple.)

Les makers qui veulent les utiliser le peuvent, ceux qui veulent experimenter le peuvent aussi.

Paramètres pour des flammes

Paramètres pour de la pluie

3/ Experimentation (30 minutes)

Laisser les makers ajouter des particules, tester des choses, et améliorer leur jeux en général

Segment 12 (30 min) : Juiciness, Lumières

Maintenant lumières! Les lumières en 2D sont interessantes mais gerer les ombres peut être un peu compliqué. Je conseille de montrer au moins les bases (types de lumières etc).

1/ Les bases (10 minutes)

Montrer aux makers les types de lumières 2D (attention à bien sélectionner 2D!):

https://lp-magicmakers.fr/accueil/ressources-makers/menu-unity/effets-waouh/lumieres-2d/

Leur paramètres principaux, et comment faire des ombres porté avec le component de Shadow Caster

2/ Experimentation (20 minutes)


Laisser les makers expérimenter avec les lumières

Segment 13 (30 min) : Juiciness, Post Processing

On va s’attaquer au Post-Process! Ici c’est purement du Bonus visuel, pour rendre le jeu plus joli et lui donner du style.

Pour utiliser le post process le projet doit être de type  Universal 2D. Si certains makers ne l’avait pas fait en créant le projet, on peut rattrapper ça maintenant:

https://lp-magicmakers.fr/accueil/ressources-makers/menu-unity/effets-waouh/installer-urp/

1/ Activer le post process (10 minutes)

Montrer aux makers comment s’assurer que le post-processing fonctionne:

https://lp-magicmakers.fr/accueil/ressources-makers/menu-unity/effets-waouh/post-processing/

Et leur montrer les effets les plus courants:

https://lp-magicmakers.fr/accueil/ressources-makers/menu-unity/effets-waouh/post-processing/#base

2/ Experimentation (20 minutes)

Laisser les makers expérimenter avec le post-processing.

Segment 14 (60 min) Build et mise en ligne

1/ Finitions (20 minutes)

Laisser les makers ajouter le plus de finitions possibles sur le jeu

2/ Build (10-5 min)

Montrer aux makers comment faire un build, attention à bien ajouter toutes les scenes

Faire son build

3/ Mise en ligne (20 minutes)

mise en ligne: montrer aux makers comment mettre leur jeux en ligne sur Itchio

Mettre en ligne le projet

Retour en haut