Développer un jeu en 2D avec Unity 3D
Après vous avoir présenté le mois dernier la plateforme de développement de jeux vidéo Unity 3D, nous allons voir dans cet article comment concevoir un petit jeu en 2D.
Les joueurs pourront ramasser des objets susceptibles de leur donner de nouvelles compétences. Il faudra proposer des objectifs au joueur, comme par exemple effectuer un parcours ou finir un niveau sans dépasser une durée maximale, ou encore éliminer un maximum d’ennemis. Les niveaux seront composés de tiles, c’est- à- dire de blocs pouvant être assemblés entre eux afin de former un décor. Ces fonctionnalités pourront être enrichies par d’autres par la suite, mais cela fera déjà une bonne base.
Création du projet
Nous allons, pour commencer, créer un nouveau projet 2D dans Unity. Après avoir téléchargé l’environnement de développement depuis le site d’Unity ( https:// unity3d. com/ fr/ get- unity/ download), installez- le sur votre machine. Si vous ne l’avez pas déjà, le programme d’installation de Unity vous proposera d’installer Visual Studio Community 2017. Vous devez accepter car les deux ( bibliothèque Unity et Visual Studio) sont indissociables. Lancez Unity et créez un nouveau projet en cliquant sur File / New Project. Nommez votre projet ( test2D, par exemple), sélectionnez un emplacement sur le disque pour l’enregistrer et saisissez éventuellement le nom de la société, sinon mettez votre nom ou ce que vous voulez. Laissez sélectionné ( à On) la ligne Enable Unity Analytics, cela ne peut pas faire de mal ( cf. article précédent). Choisissez 2D ( par défaut, c’est 3D qui est présélectionné) et cliquez sur Create project. Rendez- vous ensuite sur l’Asset Store ( https:// assetstore. unity. com) et téléchargez un projet
2D complet proposé gratuitement par Unity, 2D Roguelike. Importez le projet dans Unity 3D. Nous allons utiliser les prefabs fournis avec ce jeu afin de créer le niveau en 2D en vue de côté.
Conception du niveau
Pour concevoir le niveau, glissez/ déposez un prefab ( celui de votre choix) depuis la fenêtre de projet vers la scène. Vous pouvez, par exemple, utiliser les prefabs Wall6 et Floor7 pour construire les zones sur lesquelles les joueurs pourront marcher. Pour bien organiser le projet, nous allons créer des scènes en les nommant, par exemple, Niveau1, Niveau2, Niveau3 et ainsi de suite. Commencez par placer les prefabs au centre de la scène en les positionnant en 0,0,0. Sélectionnez ensuite un prefab et, à l’aide de la combinaison de touches Ctrl+ D, dupliquez- le. Pour déplacer les blocs d’une unité, servez- vous des flèches de déplacement du clavier tout en gardant la touche Ctrl enfoncée. Nous obtenons un niveau simple à plusieurs étages, donnant la possibilité aux joueurs de se déplacer facilement sur la scène. Pour organiser votre hiérarchie, vous allez créer un GameObject vide et placer tous vos blocs à l’intérieur. Sélectionnez pour cela GameObject puis Create Empty depuis le menu général. Les prefabs wall ont, par défaut, un Box Collider 2D et un script attaché. Dans notre cas, supprimez ce script, dont nous n’aurons pas besoin. Conservez le Box Collider qui permet de rendre le niveau « solide » . Il faut maintenant faire un peu de décoration si vous ne voulez pas que votre jeu soit trop sobre. Vous pouvez pour cela utiliser vos propres ressources, créées ou non par vos soins, ou télécharger des ressources supplémentaires sur l’Asset Store, bien entendu, ou un site comme OpenGameArt. org, sharecg ( http:// www. sharecg. com/) ou d’autres comme 3DTotal ( https:// www. 3dtotal. com/). Faites- vous plaisir : arbres, lianes, montagnes, arrière- plans divers, ce n’est pas le choix qui manque. Ne chargez pas trop non plus vos scènes : trop de déco tue la déco, dans les jeux comme dans les maisons. Téléchargez toutes les ressources qui vous intéressent et importez- les dans votre projet. Sélectionnez les textures et changez leur type en Sprite dans la fenêtre de l’inspector. Il est plus que préférable d’utiliser des sprites pour les jeux 2D plutôt que des textures. Le type sprite est apparu dès la version 4 de Unity, toujours dans l’esprit de faciliter le développement de jeux en 2D. Les sprites sont clairement mieux adaptés que les textures. Il est bien plus aisé de les animer et de les éditer ( via le Sprite Editor). Ils sont tout simplement parfaits pour faire des
jeux en 2D. La technique consiste donc à importer les textures qui vous plaisent puis de les transformer en sprite en changeant leur type ( via l’Inspector ou inspecteur d’objets). Une fois vos textures transformées en sprite, vous pouvez les placer sur la scène en les faisant glisser par drag and drop. Ces éléments décoratifs doivent être placés en arrière- plan. Vous pouvez pour cela utiliser les calques Sorting Layer et Order in Layer depuis la partie Sprite Renderer de l’inspector. Le terme et la fenêtre de l’inspector Sprite renderer désigne la texture représentant un objet. Plus simplement, il s’agit du rendu visuel de l’élément. Le Sorting Layer est utilisé afin de déterminer quel sprite doit être à l’avant ou à l’arrière- plan en cas de superposition. Le calque Order in Layer permet quant à lui de définir la priorité d’affichage des sprites se trouvant sur un même Sorting Layer. Dit autrement, vous pouvez définir quel sprite doit être placé au- dessus de l’autre en attribuant au Order in Layer une valeur plus élevée. Le Sorting Layer permet donc de créer des calques et de les ordonner. Vous pouvez ainsi spécifier que, par exemple, le calque arrière- plan se trouve devant le calque objets. L’ordre d’affichage des sprites à l’écran dépend aussi de leur propre calque. Les éléments décoratifs étant ce qu’ils sont, ils ne doivent avoir ni Collider ni d’autres composants. Si vous êtes satisfait de votre première scène, enregistrez- la en la nommant Niveau1 comme évoqué dans l’analyse. Passez ensuite à la création d’une nouvelle scène que vous appellerez Niveau2 et créez un autre niveau. Laissez libre cours à votre imagination pour ajouter quelques trous, pièges et autres chausse- trappes. Ajoutez maintenant un personnage qui sera contrôlé par le joueur. Vous configurerez ensuite ce personnage avec des scripts et des composants et vous ferez un prefab. Dans un premier temps, nous ajouterons simplement le personnage à la scène et le doterons des composants de base indispensables. Utilisez le personnage qui se trouve dans le dossier prefabs du projet d’exemple téléchargé au début ( 2D Roguelike). Si la texture du personnage n’est pas appliquée automatiquement au prefab, faites- la glisser dans la variable Sprite du Sprite Renderer. Vérifiez que votre GameObject comporte les composants suivants : un Animator, un Collider 2D, un Rigidbody 2D et un Sprite Renderer. Dans le cas contraire, rajoutez- les. Supprimez le script par défaut du prefab si ce n’est pas déjà fait. Il va falloir développer notre propre script. Vous devez impérativement utiliser un Collider 2D et un Rigidbody 2D. Sinon, si vous choisissez d’autres types de composants, vous aurez très certainement des problèmes de collisions dans
un décor 2D. Une fois le personnage créé, ajouté et prêt à l’emploi, faites en un prefab pour pouvoir le réutiliser facilement. Les Rigidbody 2D et Collider 2D fonctionnent de la même façon que leurs homonymes standard, ils différent néanmoins sur quelques propriétés et surtout ils sont particulièrement adaptés aux calculs physiques et donc aux jeux 2D. Vous pouvez, si vous le souhaitez, diminuer légèrement la taille du Collider 2D de votre personnage afin, notamment, de lui permettre de passer sans frottement entre deux blocs séparés d’une unité. Si votre Collider a une taille de 1 unité et que l’espace entre deux cubes est de 1 unité, vous risquez de bloquer le personnage. Vous devez donc ( ou non, selon votre scénario) donner une taille inférieure à 1 ( 0,94 par exemple) au Collider du personnage pour éviter cela. Le design des deux niveaux est normalement terminé. Il vous reste encore à écrire quelques scripts, enrichir les fonctionnalités de votre jeu, ajouter des niveaux, des personnages et tutti quanti. Voyons quelques exemples.
Instancier des objets interactifs avec les prefabs
Il faut commencer par créer une fonction qui instancie de manière aléatoire un prefab sur la scène lorsque l’utilisateur appuie sur la touche Espace. Les prefabs à instancier ( à créer) doivent être placés dans un tableau de type GameObject[]. Ils devront changer de couleur lorsque le joueur clique dessus. Si le prefab est bleu, il doit passer au rouge et vice- versa. Au bout de huit clics consécutifs sur le même objet, il doit devenir noir. Si l’utilisateur clique une fois de plus, l’objet concerné doit disparaître. Créez en premier lieu des objets « cliquables » . Ceux- ci devront contenir le script gérant ces clics tels que nous venons de le décrire. Il vous faudra aussi un autre script permettant d’instancier les objets sur la scène. Voici le script gérant les créations de prefabs : using UnityEngine; using System. Collections; public class ExoPrefab : MonoBehaviour { public GameObject[] objets; void Update () { if( Input. GetKeyUp( KeyCode. Space)) { Instantiate( objets[ Random. Range( 0, objets. Length)], new Vector3( 0,0,0), Quaternion. identity); } // fin de déclaration de la classe ExoPrefab Et, enfin, le script gérant les clics sur les objets : using UnityEngine; using System. Collections; public class ExoPrefab2 : MonoBehaviour { private bool isBlue = true; private int nbClics = 0; void OnMouseUp() { nbClics++; if( nbClics > 8){ Destroy( this. gameObject);} if( isBlue) { GetComponent< Renderer>(). material. color = Color. red; isBlue = false; if( nbClics == 8) { GetComponent< Renderer>(). material. color = Color. black; else { GetComponent< Renderer>(). material. color = Color. blue; isBlue = true; if( nbClics == 8) { GetComponent< Renderer>(). material. color = Color. black;} Vous pouvez maintenant faire apparaître des objets en appuyant sur la touche Espace et changer leur couleur en cliquant dessus. Au bout de huit clics, l’objet devient noir. Un clic de plus et il s’autodétruit.
Création d’un piano à huit touches
Le but recherché est ici de créer un piano à huit touches ( une petite gamme : do, ré, mi, fa, sol, la, si et do) en 2D ou 3D. Comme de bien entendu, lorsque le joueur appuie sur une touche de son clavier, le son associé doit sortir. Les sons seront stockés dans une variable de type AudioClip. Tout d’abord, il faut associer les touches du piano à huit touches du clavier, si possible consécutives. Commencez, par exemple, à associer la touche A au son Do, la touche Z au son Ré, E au son Mi, R à Fa et ainsi de suite jusqu’à la touche I et au deuxième Do. Créez ensuite un texte en cliquant sur GameObject / UI / Text. Il sera modifié à chaque fois qu’une touche du piano sera touchée. C’est le nom de la touche jouée qui sera bien entendu affichée ( sauf si vous voulez perturber l’utilisateur…). Pour construire le piano, vous pouvez utiliser des cubes pour créer les notes. Reste ensuite à ajouter un AudioSource sur chacun des cubes afin qu’ils puissent produire un son. Vous devez ensuite créer un script qui sera associé à chaque touche, mais avec des valeurs de variables
uniques pour chacune. Le code nécessaire ressemblera à cela : using UnityEngine; // les using de circonstance using UnityEngine. UI; using System. Collections; // déclaration de la classe Piano que vous devez impérativement // faire hériter de la classe MonoBehaviour public class Piano : MonoBehaviour { public AudioClip note; public Text texte; public string touche = "Do"; public KeyCode toucheClavier = KeyCode. A; void Update() f( Input. GetKeyUp( toucheClavier)) { jouerNote(); void jouerNote() { GetComponent< AudioSource>(). PlayOneShot( note); texte. text = touche; } } // fin de déclaration de la classe Piano La touche A est associée au son Do. Les variables sont définies en publiques ( mot- clef public). Vous pouvez donc en modifier les valeurs depuis l’inspector et ainsi définir quelle touche est reliée à quel son. La méthode statique GetKeyUp de la classe Input permet de savoir si l’utilisateur a relâché la touche du clavier. La méthode GetKeyDown pourrait ( presque) fonctionner, sauf que si c’est elle que vous utilisez, le son risquerait de se déclencher plusieurs fois quasi- simultanément si le joueur maintient la touche appuyée, créant ainsi une belle cacophonie. La méthode PlayOneShot() de la classe générique GetComponent, employée ici en lui passant le type AudioSource, permet de jouer un son. AudioSource, comme son nom l’indique si bien, désigne une source audio. ❍