Vous êtes sur la page 1sur 140

PROGRAMMATION

DES JEUX
VIDEOS EN
C# AVEC UNITY 3D

MARS 2020

Prof. Dr. Patrick MUKALA


Ass. Ir. Caleb BATATA

1
A propos
Les jeux attirent un public de plus en plus large, et séduisent les
développeurs. Cependant les jeux vidéo demandent beaucoup plus
d’investissement en termes de connaissances théoriques et pratiques
accès avancer que la plupart des codeurs n’ont pas.
Toutefois, pour ceux qui sont bien conscients de tout cela, coder un
jeu vidéo ne se révèle tout de même pas une partie de plaisir, et beaucoup
se perdent dans la jungle du développement de jeux.

Ce cours est donc une introduction à la programmation de jeux avec


l’outil Unity 3D, et a pour but d'orienter et de conseiller les débutants, afin
de leur fournir de bonnes bases pour démarrer et continuer sereinement le
développement de jeux.

L’esprit de ce support est de vous accompagner au maximum afin que


vous compreniez à quoi correspond chaque notion, quand utiliser telle
technique plutôt que telle autre, comment s’imbriquent les différents
éléments de cette bibliothèque pour qu’à la fin du cours vous soyez
totalement autonomes et sachiez résoudre des problématiques relativement
complexes.
Combinant soubassement théorique et exercices pratiques, chaque
module est succinctement organisé pour permettre surtout un apprentissage
autonome pour les étudiants.

2
PLAN DU COURS
A propos ....................................................................................................................................2
PLAN DU COURS.......................................................................................................................3
0. INTRODUCTION ................................................................................................................5
0.1. Organigramme des métiers du jeu vidéo .......................................................................6
0.2. Le processus de développement d’un jeu vidéo .............................................................6
0.3. Les différentes étapes du développement d’un jeu vidéo ...............................................6
0.3.1.La validation du projet ..............................................................................................7
0.3.2. L’élaboration de la bible de production du jeu .......................................................7
0.3.3.La réalisation d’une maquette ...................................................................................7
0.3.4. La production du jeu ..............................................................................................7
0.3.5.La phase de tests et de debug ....................................................................................7
0.3.6. La localisation du jeu ..............................................................................................8
0.3.7. La préparation de la version Gold ..........................................................................8
0.3.8. La fabrication du jeu ...............................................................................................8
0.3.9. La distribution .........................................................................................................8
0.4. Choix de la modèle économique ...................................................................................8
CHAPITRE 1 : NOTION DE BASES SUR LE LANGAGE C# ........................................................ 10
1.1. Présentation de langage de programmation c# ................................................................ 10
1.2. Avantages de .NET par rapport aux autres plateformes .................................................... 11
1.3. Programmation en console de type élémentaire .............................................................. 12
1.4. Programmation orientée objet (C#) .................................................................................24
1.4.1. Classes et objets ...........................................................................................................24
Membres de classe .......................................................................................................25
1.4.2. Méthodes ....................................................................................................................26
1.4.3. Constructeurs ..............................................................................................................26
1.4.4. Finaliseurs ................................................................................................................27
1.4.5. Événements .................................................................................................................27
1.4.6. Classes imbriquées ....................................................................................................27
1.4.7. Modificateurs d’accès et niveaux d’accès .....................................................................28
1.4.8. Instanciation de classes .............................................................................................28
1.4.9. Classes et membres statiques ........................................................................................29
1.4.10. Types anonymes ......................................................................................................29
1.4.11. Héritage .................................................................................................................. 30
1.4.12. Interfaces.................................................................................................................. 31
1.4.13. Génériques ............................................................................................................... 31
1.4.14. Délégués ..................................................................................................................32
1.4.15. Afficher votre programme avec la méthode principale .............................................33
Les énumérations..............................................................................................................43

3
Sauf que ce n'est pas une classe (mot clé "class") que nous voulons, mais une énumération
(mot clé "enum"), nous enlevons donc "class" que nous remplaçons par "enum", ce qui nous
donnera l'extrait de code suivant : .......................................................................................44
1.5. Premier Exercice ...............................................................................................................45
1.6. Deuxième Exercice ........................................................................................................... 51
1.7. Travail Pratique ...........................................................................................................53
CHAPITRE 2 : PRESENTATION DE L’UNITY............................................................................54
2.1. Présentation .......................................................................................................................54
2.2. Historique .........................................................................................................................55
2.3. Plateformes supportées......................................................................................................55
2.3. Fonctionnement ................................................................................................................57
2.4. Installation de Unity ..........................................................................................................57
2.5. Exemple sur le 2D ............................................................................................................58
Etape 6 : Le script pour contrôler le robot .......................................................................72
1.8. Travaux Pratique ............................................................................................................. 118
CHAPITRE 3 : INTRODUCTION A LA TROSIEME DIMENSION (3D) .................................... 119
3.1. Les concepts de base ....................................................................................................... 119
Norme d'un vecteur ........................................................................................................... 125
3.2. Travaux Pratique ....................................................................................................... 128
CHAPITRE 4 : EN ROUTE VERS LA BASE D’UNITY 3D .......................................................... 130
4.1. Lancer Unity 3D et créer un nouveau projet ................................................................ 130
Sauvegarder votre travail : projet et scenes. ....................................................................... 130
4.2. L’éditeur d’Unity 3D ................................................................................................... 130
4.3. Créer une scène simple ................................................................................................ 132
4.4. Animer un objet de la scène ........................................................................................ 133
4.5. Gestion des interactions .............................................................................................. 134
4.6. Programmation d’interaction simple avec la souris ...................................................... 135
6.7. Navigation en ré-utilisant des scripts d’interaction clavier/souris ................................. 136
4.8. Création dynamique d’objets ...................................................................................... 136
4.9. Charger une géométrie ................................................................................................ 137
4.10. Créer un exécutable pour la scène ............................................................................. 138
4.11. TP................................................................................................................................... 139
Conclusion ............................................................................................................................. 139
Bibliographie .......................................................................................................................... 140

4
0. INTRODUCTION

La création d’un jeu vidéo exige plusieurs tâches et plusieurs disciplines, Que
ça soit sur console de salon, PC, console portable, ou téléphone, de nos jours, tout
le monde joue à des jeux vidéo et beaucoup ont déjà rêvé de créer le leur. Nous
allons voir comment réaliser notre jeu étape par étape. Sans paraître pessimiste,
les jeux ne sont pas conçus par une seule personne, car il faut définir les rôles de
chaque personne à savoir :

 Producteur : il est le chef du projet, il dirige et ordonne les tâches, à chaque


avancement, il doit faire l’état de lieu ou l’évaluation pour cerner si le projet
évolue ou pas
 Directeur créatif : c’est le créateur de l’univers du jeu et de son contexte, il doit
être un artiste, un préparateur de l’environnement d’exécution exemple préparer
le style de l’environnement.
 Scénaristes : Créateur du scénario il se base sur l’univers du jeu pour décrire les
différentes scènes du jeu
 Graphistes : Ils mêlent technique et art en modélisant personnages, décors, objets,
textures, la figure etc
 Animateurs : animer la course, chute d’un personnage avec potentiellement l’aide
de la motion capture mais aussi créer la physique des vêtements et de chaque
objet, ...),
 Ingénieurs : programmeurs, développeurs, administrateurs système
 Level designer : intègre des assets des différents acteurs en charge du
développement du jeu, dans une map ou différents niveaux
 Métiers du son : Sound designer, compositeur, ingénieurs son, ...),
 Testeurs : vérifie chaque partie du jeu,

S’il y a une vingtaine ou une trentaine d’année il était possible de développer un


jeu vidéo avec seulement deux ou trois personnes dans un petit local et avec un budget
limité, de nos jours, les choses sont bien différentes. Les technologies ont évolué, les
exigences en termes de qualité sont de plus en plus prononcées et les coûts demandés
sont de plus en plus importants. Par conséquent, développer un jeu vidéo ne peut pas
se faire sans moyens financiers, matériels et humains. Il faut du temps, de l’argent.
Lorsqu’un nouveau jeu vidéo fait son apparition en boutique,

Cette liste évolue avec le temps, mais dicte les actions de l’équipe en charge
du projet sans risquer de fausses routes.

5
0.1. Organigramme des métiers du jeu vidéo

Directeur de Directeur marketing


production

Chef de projet Chef de produit

Directeur de Création Directeur Artistique Directeur Technique

Lecteur Designer Lecteur Concepteur Lecteur Programmeur


Graphiste Graphiste
Graphiste

Game Level
Designer Designer Animateur Prgm Prgm Prgm
moteur GamePlay Spécialisé

Ing. Son Ergonome Scénariste Graphiste 3D Envir.

0.2. Le processus de développement d’un jeu vidéo

S’il y a une vingtaine ou une trentaine d’année il était possible de développer un


jeu vidéo avec seulement deux ou trois personnes dans un petit local et avec un budget
limité, de nos jours, les choses sont bien différentes. Les technologies ont évolué, les
exigences en termes de qualité sont de plus en plus prononcées et les coûts demandés
sont de plus en plus importants. Par conséquent, développer un jeu vidéo ne peut pas
se faire sans moyens financiers, matériels et humains.

Il faut du temps, de l’argent. Lorsqu’un nouveau jeu vidéo fait son apparition en
boutique, il faut savoir que pour être arrivé jusque-là, il est passé par un certain nombre
d’étapes dont voici le détail ci-dessous.

0.3. Les différentes étapes du développement d’un jeu vidéo

6
Le développement d’un jeu est parfois long et fastidieux, voici les étapes de
développement, de la naissance de l’idée à la vente en magasin :

0.3.1. La validation du projet

Cette étape consiste à définir si le projet est réalisable. Il faut prendre en compte
le budget financier, les ressources humaines, les points forts et les points faibles du
projet, les contraintes et les limites technologiques… Toute l’équipe travaille main dans
la main durant cette étape. Tout le monde donne son avis et lorsqu’un accord est trouvé,
l’étape suivante débute.

0.3.2. L’élaboration de la bible de production du jeu

Il s’agit de mettre en place un document qui servira pendant toute la durée de


développement. Dedans, il faut consigner tous les points clés du projet, les différentes
contraintes, faire des choix… Une fois ce document rédigé, il faut comment la partie
Game design du projet (charte graphique, charte sonore…). À ce stade, le projet est bien
défini, les choses sont claires concernant l’univers graphique, sonore, etc.

0.3.3. La réalisation d’une maquette

Cette étape consiste à vérifier le projet est réellement réalisable. Une petite
équipe réalise donc une partie du jeu (un circuit, un niveau…) et vérifie les mécaniques
de jeu, la cohérence de l’univers… Cette étape est décisive car elle permet de savoir s’il
faut poursuivre le projet ou non, de plus, grâce à cette maquette il sera possible de
chercher des moyens de financements et des éditeurs.

0.3.4. La production du jeu

Une fois le financement débloqué et un éditeur près à vous faire confiance, vous
passez à la phase de production qui consiste à produire le jeu dans ses moindres détails.
Plus la bible de production est détaillée et plus le travail en sera facilité. Il faut qu’à ce
stade la bible de production soit parfaite car l’équipe en charge du projet n’a plus le
temps de la corriger ou la modifier. Le moindre écart et les conséquences peuvent être
lourds surtout au niveau du budget financier. Il faut également savoir que s’il y a des
financeurs au projet, ils voudront très certainement surveiller la progression du projet.
Il faut beaucoup communiquer avec l’éditeur dans cette étape car sans sa validation, le
projet peut finir mort-né.

0.3.5. La phase de tests et de debug

Voici l’une des phases les plus difficiles de la production. Une fois le projet terminé, il
faut effectuer différents tests et debug afin de corriger les bugs et de peaufiner au
maximum le jeu. Ces bêtas tests sont réalisés chez les développeurs, chez les éditeurs
et parfois même par le public.

7
0.3.6. La localisation du jeu

Un jeu congolais qui ne sortira que sur le sol congolais n’a pas besoin de cette
étape mais si le jeu sort à l’international, alors il faut le traduire dans les différentes
langues visées. Dans cette étape il faut également prendre en compte les restrictions au
niveau des pays. Par exemple la violence doit être censurée en Australie ou en
Allemagne dans certains cas.

0.3.7. La préparation de la version Gold

Lorsqu’un jeu passe « Gold », cela veut tout simplement dire qu’il est
entièrement fini et qu’il peut passer à la phase suivante.

0.3.8. La fabrication du jeu

Durant cette étape le jeu est fabriqué, c’est-à-dire qu’il est réalisé pour être vendu
en magasin. Il faut donc graver les DVD (ou Blu-Ray), imprimer les jaquettes,
fabriquer les boîtes…

0.3.9. La distribution

L’éditeur va distribuer le jeu dans les chaînes de magasins afin qu’il soit mis en
vente. Quand le jeu est prêt, il faut le dévoiler au public en s’appuyant sur la
communication pour qu’un maximum de personnes soit au courant de l’existence et de
la sortie du jeu vidéo.
Il y a différents canaux de distribution possibles. Je ne parlerais ici que de la
distribution dématérialisée qui est de plus en plus utilisée par un choix collectif des
joueurs. Des plateformes dédiées existent afin de faire connaitre le jeu aux utilisateurs
de celle-ci mais, distribuer son propre produit par le biais de son propre site est aussi un
bon moyen.

0.4. Choix de la modèle économique

Le choix d’un modèle économique est important. Il influencera l’intérêt du


joueur à y jouer puisque l’on connaît tous la réputation des jeux P2W (Pay To Win, jeu
en principe gratuit mais auquel il est difficile de gagner sans payer pour obtenir un
avantage significatif).

 Ventes lors du téléchargement.


 Micro-transaction : permet au joueur d’obtenir des avantages plus ou moins
significatifs (compétences, graphismes, skins, objets, customisations diverses,
...). Attention de ne pas tomber dans le P2W.
 DLC : développer des « Downloadable Content » payant, qui permettraient de
générer des revenus afin de rentabiliser le développement.

8
 Abonnement.
 Publicité : placement de produits par le biais d’objets en jeu (voiture,
consommables, ...), panneaux publicitaires intégrés dans le décor ou dans le
menu du jeu, mais aussi des pubs visibles sur le site web du jeu.

Cette liste est non exhaustive puisque ce n’est pas le but de ce cours, mais il en
reste (le financement participatif, la vente de produits dérivés, démo de jeu payant à
partir d’un certain niveau).

9
CHAPITRE 1 : NOTION DE BASES SUR LE LANGAGE C#

Dans ce chapitre nous tenterons d’expliquer les notions fondamentales sur le


langage c# qui nous mettra en lumière pour la programmation de nos jeux vidéo. Il faut
tout d'abord savoir que pour développer en .net, nous pouvons faire avec plusieurs
langages dont : C#, VB.Net, C++ adapté au .net, F#, Et bien d'autres
1.1. Présentation de langage de programmation c#
Tous ces langages sont en quelques sortes à mi-chemins entre des langages
compilés et interprétés : ils ne sont pas directement compilé en langage machine, mais
il ne sont pas non plus interprétés.
En réalité, ils vont être compilés en un langage intermédiaire (appelé IL pour
"Intermediate Language"). Lors de l'exécution ce langage intermédiaire va être compilé
en langage machine et exécuté par le CLR (Common Language Runtime), ce "runtime"
va en quelque sorte faire l'intermédiaire entre notre code et le système d'exploitation
en apportant une importante abstraction vis à vis de fonctions systèmes de bases
(entrés/sorties, gestion de la mémoire, etc...).

10
1.2. Avantages de .NET par rapport aux autres plateformes

Cette architecture apporte plusieurs avantages dans le développement des


applications notamment :
 Il exécute plus rapidement un langage interprété puisqu'il aura été au préalable
pré-compilé en un langage déjà proche de la machine.
 Ensuite, ce CLR (le "Common Language Runtime") permet au développeur de
ne pas se préoccuper de certaines choses, surtout concernant la mémoire. Un
"garbage collector" (traduire par "ramasse miette" et non "collectionneur de
poubelle" :p ) va s'occuper de libérer les ressources mémoires inutilisées; les
fuites de mémoires vont être automatiquement détectées et corrigées.
 Peu importe le langage (C#, VB.net, F#, etc...) que l'on utilise, le langage
intermédiaire sera exactement le même, c'est à dire que vous p b ouvez très bien
travailler sur un même projet avec plusieurs langages différents, par exemple
vous créez la logique et le visuel de votre jeu en C#, puis vous utilisez du F#
pour l'intelligence artificielle. Cette "unité" dans ces langages pourtant différent
est permise par la CLI (pour "Common Language Infrastructure") qui fournis
les spécifications pour qu'un langage puisse être compilé en IL.
 Et enfin, peut importe la plateforme Windows que vous avez (XP, Vista,
Windows Server, etc..), il vous suffit d'avoir la CLR (en gros d'avoir le
framework .net d'installé) pour que votre programme fonctionne. Une partie du
framework fonctionne même sous Unix, une simple copie d'un programme peut
suffire pour le faire fonctionner d'un système à l'autre. C'est donc le CLR, qui
lui sera compilé en langage machine, qui s'occupera de recompiler à l'exécution
l'IL de notre programme
C# a été créé pour .net. C'est le langage qui exploite le mieux le framework.
D'autres avantages liés au C# combiné au framework .net sont entre autres (tout ces
éléments vont vous paraitre inconnus, mais en lisant ce cours vous allez peu à peu
comprendre chacun d'eux) :
 Système puissant d'exceptions.
 Les delegate, des sortes de variables/fonctions.
 Il n'y a que des références.
 Les propriétés évitent de devoir écrire autant d'accesseurs.
 .net permet de presque tout faire en programmation.
 Les événements qui évitent d'alourdir le code avec la déclaration et l'utilisation
d'actions.
 Typage très fort (dans notre cas, c'est un avantage)
 Langage tout objet (de même dans notre cas, ceci va apporter certains avantages)
11
 Utilisation de XAML, un dérivé du XML pour créer nos interfaces graphiques.
 XNA, une bibliothèque facile à utiliser qui permet la création de jeux.
Cependant, il faut néanmoins rester conscient que le .net n'a pas que des
avantages, les inconvénients sont entre autres:
 Même si un portage de .net est en cours sous Unix, seul Windows supporte
correctement tout le .net.
 Les applications peuvent être désassemblées pour retrouver une approximation
de la source initiale. Un outil permet néanmoins de rendre illisible ce code
désassemblé.
 Même si l'IDE de Microsoft est très puissant, il est assez lourd (~600Mo pour la
version Express, plusieurs Go pour les versions professionnelles, ce qui même
aujourd'hui peut paraitre important)
Néanmoins, si vous êtes sous Windows, que vous voulez faire de jolis programmes de
manière simple, et que vous avez un peu d'espace disque, le C# et .net sont faits pour
vous.
1.3. Programmation en console de type élémentaire

Avant d'utiliser les possibilités offertes par les classes et les objets en C#,
apprenons à utiliser et exécuter des applications simples C# ne nécessitant pas la
construction de nouveaux objets. Comme C# est un langage entièrement orienté objet,
un programme C# est composé de une ou plusieurs classes, nous nous limiterons ici à
une seule classe mais la notion des classes sera exploités dans le point 1.4 ci-dessous.

1.3.1. Le type primitif


Pour comprendre un type primitif nous devons d’abord comprendre c’est qu’une
notion très élémentaires que vous avez étudié dans les promotions précédentes, dans
d’autres langages, qui se nomme sur les variables.
1.3.1.1. Les variables
Tout d'abord, nous allons définir ce qu'est une variable. Comme son nom
l'indique, cela va être quelque chose dont la valeur va être ... variable. Cela pourra être
un nombre, une lettre, un mot, une phrase, une valeur de vérité, n'importe quoi... En
bref, c'est une valeur temporaire que l'on mettra dans la mémoire vive de l'ordinateur
(la mémoire vive est un composant de l'ordinateur qui sert à stocker temporairement
des informations, dès que l'ordinateur s'éteint, cette mémoire est vidée).
Cette valeur va servir à certains traitements. Puisqu'un petit exemple vaut
mieux qu'un long discours : imaginons que nous voulons calculer un prix d'un objet
soumis à une taxe, pour ce calcul, il nous faut deux informations, un prix hors taxe et
le montant de la taxe, et nous obtiendrons une troisième information, le prix toute taxe
12
comprise. Chacune de ces information va être une variable, en effet, on pourra calculer
un prix toute taxe compris à partir de n'importe quel prix hors taxe et de n'importe quel
taux de taxe, ce qui nous donnera un prix toute taxe comprise variable.
En gros, un programme informatique va fonctionner comme cela : des variables
données en entrée et une valeur de retour. Nous donnerons au programme le calcul à
faire à partir des variables sans leur donner des valeurs, et c'est lors de l'exécution que
ce programme va se débrouiller pour calculer.
Dans notre cas, nos variables sont des nombres, mais comme nous avons pu le
voir plus haut, il peut y en avoir de types de variables différents : des entiers, des
nombres décimaux, des chaines de caractères. En .net et en C#, ça va être la même
chose, on aura plusieurs types différents : différents types d'entier, différents types de
nombre décimaux, un type "lettre" (nous disons plutôt "caractère"), etc. Les types que
nous verrons ici sont dits types "primitifs".

1.3.1.2. Les types primitifs


Un type primitif c'est un type qui ne nécessite pas une initialisation avant d'être
utilisé. Ce sont des types valeur (attention retenez bien ce type, il nous sera très
important dans la partie concernant la programmation orientée objet). Voici la liste des
types primitifs de .NET :

Nom Description

Bool Un type qui peut prendre deux valeurs: true ou false (vrai ou faux)

Un type qui prend un octet de mémoire. La valeur ne peut être que


positive (ou zéro) et a un maximum de 255 (un nombre codé sur un octet
Byte
prend, comme son nom l'indique 8 bits en mémoire et a donc 256
"possibilités" ce qui donne de 0 à 255).

Char Un type codé sur 2 octets, qui prend un caractère Unicode.

decimal Un type codé sur 16 octets qui peut contenir des nombres décimaux

Deux fois plus petit que decimal (8 octets). Peut contenir des nombres
Double
décimaux.

Deux fois plus petite que double (4 octets). Peut contenir des nombres
Float
décimaux mais avec une précision moindre que celle d'un double

Un nombre entier. Peut contenir des valeurs positives ou négatives. Les


Int
int sont codés sur 4 octets. Est équivalent à Int32.

13
Nom Description

Deux fois plus grand que int (8 octets). Contient des nombres entiers
Long
positifs ainsi que des entiers négatifs. Est équivalant à Int64.

Short Un type signée de 2 octets. Est équivalent à Int16.

Un byte signé. Cela veut dire que le valeur de la variable peut être
Sbyte
positive ou négative.

String Un type d'une taille indéfinie. Il contient une chaîne de caractères

Un int non-signée. Cela signifie que la valeur ne peut être que positive.
Uint
En revanche, des nombres deux fois plus grand sont disponibles.

Ulong Un long non-signé.

Ushort Un short non-signé

Les noms énoncés au-dessus sont en fait les alias vers des types ayant des noms
plus complexes, par exemple "int" va être la même chose que "Int32", short va être la
même chose que "Int16", l'utilisation du "vrai" type ou de son alias revient au même,
mais il faut savoir que ça existe car il arrive qu'on croise le "vrai" type au lieu de l'alias.
J'y venais justement. Tout d'abord pour taper du code, il faut bien entendu
entrer dans un fichier de code. Dans l'immédiat nous allons écrire dans le fichier
"Program.cs" créé automatiquement par Visual Studio lors de la création de notre
projet. Chaque fichier de notre solution (un genre de conteneur pour rassembler un ou
plusieurs projets), se trouve dans ... l'explorateur de solution (Solution Explorer pour
les versions anglophones).
Celui se trouve généralement sur la partie droite de Visual Studio (il peut bien
sur être déplacé où vous voulez, même en dehors de la fenêtre de Visual Studio), si
vous ne le voyez pas, allez dans le menu "Affichage" ("View") puis "Explorateur de
solution" ("Solution explorer") ou faites les combinaisons de touches "Ctrl+W,
S". Une fois que vous voyez bien votre explorateur de solution, double-cliquez sur
"Program.cs" pour ouvrir le fichier dans la partie centrale de Visual Studio. A ce
niveau-là, vous devriez vous trouver en face de ce code si vous avez gardé le même
fichier que tout à l'heure :

14
using System;
namespace PremierProgramme
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello Word");
}
}
}
Ou de celui-là si vous avez créé un nouveau projet :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace PremierProgramme
{
class Program
{
static void Main(string[] args)
{

}
}
}

Expliquons la signification de chaque ligne de code


 Ligne 1 à 5 : les directives "using", elles permettent d'importer des classes
d'ailleurs, je vous expliquerais plus en détail le concept de classes un peu plus
loin. Sachez que nos types énumérés un peu plus haut sont contenus dans
l'espace de nom "System" (la première ligne du fichier), les quatre suivantes
sont utilisées assez fréquemment, mais ici nous n'en aurons pas besoin.
Si le nombre de "using" vous fait peur et que vous voulez seulement utiliser
ceux dont vous avez besoin, effectuez un clic droit n'importe où dans le code, et
dans le menu contextuel allez à "Organiser les usings/Supprimer et trier"
("Organize usings/Remove and Sort" pour les versions anglaises de Visual
Studio). Nous pourrons par la suite en ajouter de manière simple (Visual Studio
le ferras pour nous :p )
 Ligne 7 : le "namespace" ("espace de nom" pour ceux qui veulent franciser ;) )
de notre projet, si vous ne l'avez pas modifié, cela prend le même nom que le
projet que vous avez créé ("PremierProgramme" dans mon cas). Un namespace
va être en quelque sorte un conteneur pour toutes les classes que vous créez. Les
directives using en haut sont suivies d'un namespace à inclure, ceux-ci peuvent
15
être "contenus" les uns dans les autres, par exemple "System.Linq" est inclus
dans "System". Repérez l'accolade ouvrante à la ligne 8 et l'accolade fermante à
la ligne 16, ce sont nos délimiteurs de notre espace de nom, tout ce qui seras dans
ces accolades appartiendra à notre espace de nom.
 Ligne 9 : déclaration de la classe, comme je vous l'ai dit un peu plus haut, nous
verrons dans le chapitre suivant le concept de classe. Sachez juste qu'ici, notre
classe "Program" va être la première classe de notre programme.
Les accolades à la ligne 10 et 15 sont les délimiteurs de notre classe, tout ce qui
est entre ces accolades appartient à cette classe
 Ligne 11 : le point d'entrée de notre programme, la méthode Main. Lorsque notre
programme sera exécuté, ce sera cette méthode qui sera exécutée en premier.
Comme pour les classes je reviendrais dans le chapitre suivant sur les méthodes
de manière plus détaillée. Notre méthode commence après l'accolade ligne 12 et
se termine juste avant l'accolade ligne 14.
 Ligne 13 : rien ... et c'est normal, c'est à nous d'écrire du code ici. Tout les extraits
de code suivant sont à écrire ici. Vous pouvez écrire autant de lignes que vous
voulez tant que vous restez entre les accolades de la méthode Main.
 Syntaxe
Par souci de faire un code compréhensible, nous pouvons mettre des
commentaires dans ce code, les commentaires se mettent en fin de ligne et ont la
syntaxe suivante:
//Commentaire sur une fin de ligne
Donc si vous voyez un double slash quelque part, lisez bien ce qui suit, ça risque
de vous donner beaucoup d'indications ;)
Pour créer (le mot "déclarer" est plus correct) une variable on utilise la syntaxe
suivante : type nom;
La déclaration est une instruction. Une instruction va être une quelque sorte
une étape insécable dans notre code, et pour avoir une instruction syntaxiquement
correcte en C# on doit OBLIGATOIREMENT la finir par un point virgule (' ; ').
Pour déclarer un int (code à taper à la ligne 13):
int monEntier;
 Affectation
On peut donner une valeur (ou plutôt affecter une valeur) à une variable déjà
déclarée comme ceci :
monEntier = 32;
L'affectation est aussi une instruction. Cependant, nous savons tous que les
programmeurs ce sont une bande de paresseux. Pour cette raison, les concepteurs de C#
16
se sont dits que ça serait très pratique de pouvoir déclarer et affecter en même temps.
Voici la syntaxe
int monEntier = 32;

Nous pouvons faire ainsi avec n'importe-quel type. La seule différences résidera
dans les caractères (char) dont la valeur sera placée entre simple quotes ( ' ) et les
chaines de caractères (string) dont la valeur sera placée entre doubles quotes ( " )
comme dans l'exemple suivant :
char caractere = 'c';//une variable de type caractère (char) dont on affecte
la valeur grâce à un caractère placé entre simples quotes
string chaine = "une chaine"; //une chaine de caractère délimitée par des do
ubles quotes

 Ecrire autant en moins de lignes


Lorsque que nous avons plusieurs variables du même type, il nous est
possible de toutes les déclarer sans répéter le type, il suffira alors de les séparer par des
virgules lors de la déclaration. Le premier code qui suit est le code "de base", le suivant
est le code raccourci
int entier1 = 3;
int entier2 = 5;
int entier3 = 17;
int entier1 = 3, entier2 = 5, entier3 = 17;

En général, il ne pas sacrifier la lisibilité du code au dépend de la longueur du


fichier, ici nous ne perdons pas en lisibilité, car en lisant la ligne on voit facilement de
quel type sont nos variables.
 Conversions
Parfois, il est utile de pouvoir convertir un type primitif en un autre, aussi bien
d'entiers à décimaux, de décimaux à entiers, de chaine de caractère en booléen, d'entier
en chaines de caractère... En bref, tout est possibles (ou presque)
 Conversion en chaine de caractère : méthode ToString()
C'est la conversion la plus simple, pour tout les types de données (sans
exception) nous avons ToString(). Pour ceux qui ne parlent pas trop anglais, nous
pourrions traduire par "EnChaineDeCaractere". La syntaxe est simple
: maVariable.ToString() et ce avec n'importe quel type de donnée :
int entier = 1;
double flottant = 3.5;
bool booleen = true;
char caractere = 'c';

17
string chaine = "salut";
string entierEnChaine = entier.ToString();//1 devient "1"
string flottantEnChaine = flottant.ToString();// 3.5 devient "3.5"
string boolEnChaine = booleen.ToString();// true devient "True"
string caractereEnChaine = caractere.ToString(); // 'c' devient "c"
string chaineEnChaine = chaine.ToString(); // "salut" devient... "salut"

Rien de plus compliqué : vous voulez une chaine de caractère, ajoutez


".ToString()" derrière votre variable, vous pouvez le faire avec n'importe quoi, même
avec une chaine de caractère :p (bon là l'intérêt est pas immédiat, mais avec quelques
options que nous verrons plus tard, cela peut devenir plus intéressant).
 Conversion de types numériques en d'autres types numériques
Cela devient un tout petit peu plus délicat, car il faut prendre en compte que les
différents types ne sont pas codés sur le même nombre d'octets donc par exemple pour
convertir un byte vers un short, il n'y aura aucun problème, mais par contre l'inverse
peut révéler quelques surprises.
Pour comprendre plongeons nous un peu dans du binaire : les nombres au sein
d'un ordinateur sont codés en binaires, ce sont donc des suites de 0 et de 1 (digits), nos
variables étant codées sur des nombres d'octets différents, ces suites de digits vont avoir
différentes longueurs, ce qui donne pour un même nombre dans différents types de
données (par exemple 14) :
 0000 1110 pour un byte
 0000 0000 0000 1110 pour un short
 0000 0000 0000 0000 0000 0000 0000 1110 pour un int
 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
1110

Pour un long Vous voyez que pour un même nombre, la place occupée peut aller
du simple au double (et même du simple à l'octuple). Donc gardez bien à l'esprit que
même si aujourd'hui ces tailles de variables sont insignifiantes par rapport aux tailles
de mémoires vives disponibles (en comparaison, un ordinateur neuf aujourd'hui
"milieu/haut de gamme" avec 4 Go de RAM peut théoriquement contenir à peu près
500 millions de "long" simultanément), il est important de rester conscient de la taille
prise pas nos variables en mémoire et de pourvoir l'optimiser.
En effet, des tas de développeurs utilisent systématiquement des int (4 octets)
pour des entiers et des doubles (8 octets) pour des flottants, alors qu'honnêtement on
n’a pas souvent besoin d'avoir une variable pouvant aller de -2 147 483 648 à 2 147 483
647, vous pouvez généralement très bien vous en sortir avec un short (2 octets) et même
un byte (1 octet) parfois.
L'optimisation maximale de votre mémoire vive, car en effet, l'optimisation ne
concerne pas seulement la mémoire vive ! Il faut que vous sachiez que, globalement,
un int se modifie en mémoire plus rapidement que les autres types d'entiers, donc pour

18
un entier qui doit changer souvent de valeur, nous préférons un int et nous nous
attachons à l'optimisation de nos types seulement lorsqu'un très grand nombre de
variable est utilisé (par exemple dans le cas de la génération d'image ).
D'où l'intérêt d'effectuer des conversions entre certains types numériques. Si la
conversion se fait sans perte de donnée, c'est à dire vers un type "petit" vers un grand
type, tout ce fait automatiquement comme pour le code suivant:
byte unByte = 4;
short unShort = unByte;

Nous voyons ici que nous assignons un short à partir d'un byte, les types ne
sont pas les mêmes et pourtant cet extrait de code fonctionne parfaitement. La raison
est simple, du côté binaire il n'y a qu'à "compléter" avec des 0 pour passer d'un byte en
short. Par contre, le code suivant ne fonctionnera pas (enfin, pas directement):
short unShort = 4;
byte unByte = unShort;

En effet, même si, dans notre cas, il n'y a pas de perte de donnée lors de la
conversion (un byte a une taille suffisante pour stocker 4), il pourrait y en avoir une
avec un short ayant une valeur supérieur à 255, donc Visual Studio nous signale qu'on
ne peut pas implicitement convertir un short en byte.
Si on analyse un peu ce message d'erreur, on peut deviner que, puisqu'on ne peut
pas le faire implicitement, on doit pouvoir le faire explicitement (logique :p ). En C#,
pour convertir explicitement une variable d'un type en un autre type, il nous suffit de
préciser le type entre parenthèses juste devant notre variable, le code précédant corrigé
donnera donc :
short unShort = 4;

byte unByte = (byte)unShort; // On converti explicitement un short en byte

Ici, il n'y aura pas de problème particulier, par contre, si votre short était plus
grand que 255, notre byte aurait valu à la sortie la valeur du short modulo 256 (par
exemple si le short valait 260, le byte aurait valu 4) car le compilateur vas juste se
contenter de prendre les bits de poids faibles jusqu'à remplir l'espace alloué à un byte
puis "oubliera" le reste (les bits de poids fort).
Gardez donc bien à l'esprit qu'il peut y avoir de la perte d'information lorsque
vous effectuez des conversions d'un type vers un type "plus petit". Conversions de
string vers autres types de données : méthodes Parse() et TryParse()
Parfois, nous allons avoir besoin de convertir des chaînes de caractères en
d'autres types de données. Par exemple convertir "123" (chaine de caractère) en 123
(entier), ou convertir "false" en un booléen valant false. Pour chacune de ces
conversions, nous allons avoir deux manières de procéder, l'une étant légèrement plus

19
complexe que l'autre, mais permet de voir plus facilement s'il y a eu une erreur de
conversion.
Mais tout d'abord voyons la plus simple : Parse. "Parser" va signifier parcourir
tout les éléments d'une chaine de caractère pour un obtenir autre chose, dans notre cas
on va parcourir chaque caractère de la chaine, voir si c'est un chiffre, et si on n'a vu que
des chiffres, on retourne le nombre correspondant. Cela peut paraitre bien compliqué
mais, ne vous en faites pas, la méthode Parse le fait pour nous. Voyons son utilisation:
string nombreEnString = "123";//On a un nombre en chaine de caractère
int nombreEntier = int.Parse(nombreEnString);//Grace à int.Parse(...) on en
fait un entier

La syntaxe de int.Parse(..) nous importe peu pour l'instant. Retenez juste que
int.Parse(...) va permettre de convertir en entier une chaine de caractères passée en
paramètres (entre les parenthèses de "Parse(...)"). Dans notre
exemple, nombreEntier vaudra 123 comme vous pouvez le deviner.
Pour convertir une chaine de caractère en nombre décimal ou en booléen, cela
va être identique, on remplacera juste "int" par le type que l'on veut. Par exemple :
bool booleen = bool.Parse("true");//Booleen vaudra true
double unDecimal = double.Parse("123.4");//unDecimal vaudra 123,4

C'est bien, mais essayer de donner à Parse quelque chose de "imparsable" et


votre programme plantera lamentablement. Essayez donc ça :
int unEntier = int.Parse("&23");//Un belle faute de frappe qui va tout faire
planter

Heureusement, nous avons aussi une méthode qui ne fait pas tout crasher : la
méthode TryParse ! Pour les non-anglophones, "try" signifie "essayer" ; cette méthode
va donc essayer de parser ce que nous lui donnons en paramètre et renverra un booléen
si le parsage n'a pas réussi. La syntaxe va être légèrement différente, par exemple avec
le même exemple que tout à l'heure:
string nombreEnString = "123";
int unEntier;
int.TryParse(nombreEnString, out unEntier);

L'entier ne va pas être renvoyé directement, il nous faudra créer une variable de
type int au préalable et la passer en second paramètre à la méthode. Vous pouvez
remarquer le mot-clé "out", celui-ci est obligatoire pour l'utilisation de cette méthode,
nous expliquerons l'utilité de mot clé dans un chapitre suivant, pour l'instant retenez
juste qu'il nous faut absolument le mettre (le programme ne compile pas sinon).
Pour l'instant, rien de fabuleux par rapport au simple "Parse", ceci est dû au fait
qu'ici j'utilise TryParse de la manière dont j'utiliserais Parse. Et oui, ces deux méthodes

20
ne s'utilisent pas vraiment pareil, pour bien utiliser TryParse, je préfèrerais le code
suivant:
string nombreEnString = "123";
int unEntier;
bool aReussi = int.TryParse(nombreEnString, out unEntier);//TryParse renvoie
un booléen valant vrai en cas de succès, sinon il renvoie faux

Voyons l'ajout de la variable booléenne récupérant le résultat de TryParse, si le


parsage a réussi, "aReussi" vaudra true, si ça échoue, cela ne vas pas planter et fermer le
programme comme avec Parse, mais cela va renvoyer false. Ainsi, nous pourrions
vérifier si le parsage a réussi au lieu de croiser bêtement les doigts pour que cela ne
plante pas.

1.3.1.3. Gérer les entrées/sorties de bases


Avant d'attaquer pleinement la programmation orientée objet, nous allons
apprendre comment gérer les entrées et sorties de bases : écrire quelque chose à l'écran
et lire une entrée utilisateur. Utiliser Console.WriteLine(...)
Comme le titre l'indique, nous allons utiliser Console.WriteLine(); pour écrire
quelque chose sur la console. Pour les observateurs bilingues, vous devinerez facilement
que cette instruction demande à la console d'écrire quelque chose à l'écran. Les concepts
sous-jacents à la syntaxe de cette instruction seront vues dans le chapitre juste après (et
oui, vous en saurez des choses dans le chapitres suivants).
Si vous écrivez simplement Console.WriteLine(); et que vous exécutez (bouton
vert en forme de triangle sous le menu, ou dans le menu "Debug/Start Debugging"
("Débogage/Démarrer le débogage") ou en appuyant sur la touche F5 de votre clavier),
rien ne semblera se passer. En réalité, une ligne sera sautée dans la console et cette
dernière se fermera d'elle-même.
Pour éviter cette fermeture automatique, plusieurs choix s'offrent à vous, le plus
simple est d'exécuter sans débogage, pour cela, allez au menu "Debug/Start Without
Debugging" ("Débogage/Exécuter sans Débogage") ou pressez la combinaison de
touche Ctrl + F5 ; ainsi, vous verrez qu'une ligne a été sautée sur la console par votre
code avant qu'il vous soit demandé de presser une touche pour que la console se ferme.
Certes cette manière de sauter une ligne dans la console vous paraitra pratique,
mais je vous déconseille fortement de l'utiliser, car il y a mieux pour cela, comme les
caractères " " et " " que j'utiliserais brièvement dans un des chapitres suivants, mais j'y
reviendrais dessus à ce moment là, promis ;) . Pour une seule chaine comme ceci:
Console.WriteLine("mon nom est !");
Qui donnera le résultat suivant:
Mon nom est :

21
On peut aussi afficher en une seule fois plusieurs chaînes de caractères
concaténées, c'est à dire mises les unes à la suite des autres. Pour concaténer plusieurs
chaînes, nous allons simplement utiliser l'opérateur "+". Nous pourrons donc écrire
l'instruction suivante:
Console.WriteLine("Je suis une chaine. " + "Moi aussi!! " + "Et moi alors!!"
);

Vous pouvez aussi très bien écrire des nombres:


Console.WriteLine(3.5);
Attention toute fois si vous voulez concaténer des nombres (l'idée est assez bête mais
bon peut être que certain y ont pensés), ceux-ci vont s'additionner:
Console.WriteLine(3.5 + 2);

Si vous n'avez vraiment pas le choix et que vous devez absolument concaténer des
nombres, convertissez simplement chacun des nombres en chaine de caractères.
Console.WriteLine((3.5).ToString() + (2).ToString());
Un grand intérêt qui réside est que vous n'êtes pas obligés de taper directement la
chaîne à afficher, vous pouvez passer par des variables intermédiaires :
string chaine1 = "Bonjour ";
string chaine2 = "les ";
string chaine3 = "zéros ";
Console.WriteLine(chaine1 + chaine2 + chaine3);

Remarquez qu'il existe aussi la méthode Write qui produira exactement le


même résultat, mais sans sauter de ligne. WriteLine reste néanmoins plus utilisée, si
bien que Visual Studio intègre un raccourci clavier pour écrire Console.WriteLine();,
pour l'utiliser, tapez à l'endroit adéquat "cw" (comme Console et WriteLine) puis
pressez deux fois la touche tabulation, l'extrait de code est ainsi automatiquement
ajouté.
 Utiliser Console.ReadLine()
A présent, nous allons voir comment demander à l'utilisateur de rentrer une
chaîne de caractère (puis par extension un nombre). Pour les heureux bilingues qui
lisent ce cours, la logique est de mise ici, en effet on écrit avec Console.WriteLine(...)
donc nous lirons avec... Console.ReadLine(). La syntaxe est beaucoup plus simple pour
les entrées standards:
string uneChaineDeCaractere;

uneChaineDeCaractere = Console.ReadLine();

22
Lorsque le programme arrivera à cette instruction dans le code, l'utilisateur devra
écrire une ligne de texte dans la console et finir en appuyant sur la touche 'entrée'.
Toute la ligne écrite sera stockée dans la variable uneChaineDeCaractere.
Si nous combinons ReadLine() avec les conversions vues dans un chapitre précédent,
pour récupérer un entier entré par l'utilisateur nous ferrons:
int unEntier;
Console.WriteLine("Entrez un nombre");
bool aReussi = int.TryParse(Console.ReadLine(), out unEntier);
Console.WriteLine("aReussi vaut " + aReussi.ToString() + " et l'entier vaut
" + unEntier.ToString());
Ainsi, si nous entrons un nombre, cela affichera:
Entrez un nombre
3
aReussi vaut True et l'entier vaut 3
Et en cas de faute de frappe, cela affichera:
Entrez un nombre
"
aReussi vaut False et l'entier vaut 0

Nous verrons plus tard comment faire pour demander à l'utilisateur d'entrer un
nombre tant qu'il n'a effectivement pas tapé un nombre correct (sans aucun autre
caractère qu'un chiffre)
Ceux qui auront commencé à explorer les propositions de l'auto-complétion
(appelée "intellisense" sous Visual Studio) auront remarqué une méthode "Read()" et
auront fait le rapprochement avec la méthode "Write()", c'est à dire une méthode
"capable de lire une chaine de caractère entrée à l'écran sans sauter de ligne".
Or ce n'est pas le cas !! La méthode "Read()" va seulement récupérer le dernier caractère
du flux d'entrée standard, son utilisation ne nous intéresse pas encore, nous utiliserons
donc pour le moment exclusivement la méthode "ReadLine()".
A cela, s'ajoutera aussi Console.ReadKey() qui se contentera elle de lire un seul
caractère, nous ne verrons pas tout de suite comment l'utiliser pour stocker un seul
caractère, nous l'utilisons généralement en fin de programme pour éviter que la console
ne se ferme toute seule, de la manière suivante:
//Contenu du Main()...
Console.WriteLine("Appuyez sur une touche pour continuer...");
Console.ReadKey();

23
Grâce à ce code, vous pouvez lancer votre programme en mode debeug sans que
la console se ferme toute seule à la fin
Il peut être intéressant de noter que, par défaut, Console.ReadKey() affiche le
caractère tapé. Pour ne pas l'afficher, préférez le code suivant:
//Contenu du Main()...
Console.WriteLine("Appuyez sur une touche pour continuer...");
Console.ReadKey(true);

Sachez qu'en programmation, si on n'avait que des types primitifs, on n'irait pas très
loin. Néanmoins, ils sont à la base de tout.

1.4. Programmation orientée objet (C#)

C# offre une prise en charge complète de la programmation orientée objet, y


compris l’encapsulation, l’héritage et le polymorphisme.

 L’encapsulation signifie qu’un groupe de propriétés, méthodes et autres membres


corrélés est traité comme une unité ou un objet unique.
 L’héritage décrit la possibilité de créer des classes à partir d’une classe existante.
 Le polymorphisme signifie que plusieurs classes peuvent être utilisées de manière
interchangeable, même si chacune des classes implémente les mêmes propriétés
ou méthodes de manière différente.

1.4.1. Classes et objets

Les termes classe et objet décrivent respectivement le type des objets et


les instances des classes. Cela explique pourquoi l’opération de création d’un objet est
appelée instanciation. Si l'on reprend l'analogie avec un plan de construction, une classe
est un plan, et un objet est un bâtiment construit à partir de ce plan.

Pour définir une classe :

class SampleClass
{
}

C# fournit également des types appelés structures qui sont utiles lorsque vous
n’avez pas besoin de prise en charge de l’héritage ou du polymorphisme.

Pour définir une structure :

struct SampleStruct
{
}

24
 Membres de classe

Chaque classe peut avoir différents membres de classe : des propriétés qui
décrivent les données de classe, des méthodes qui définissent le comportement de classe
et des événements qui permettent la communication entre les différents objets et
classes.

 Propriétés et champs

Les propriétés et les champs sont des informations contenues dans un objet. Les
champs sont similaires aux variables, car ils peuvent être lus ou définis directement,
sous réserve de modificateurs d’accès applicables. Pour définir un champ accessible à
partir d’instances de la classe :

public class SampleClass


{
string sampleField;
}

Les propriétés get ont set des accesseurs et, qui fournissent davantage de
contrôle sur la façon dont les valeurs sont définies ou retournées.

C# vous permet de créer un champ privé pour stocker la valeur de la propriété


ou d’utiliser des propriétés implémentées automatiquement qui créent ce champ
automatiquement en arrière-plan et fournissent la logique de base pour les procédures
de propriété. Pour définir une propriété implémentée automatiquement :

class SampleClass
{
public int SampleProperty { get; set; }
}

Si vous devez exécuter des opérations supplémentaires pour la lecture et


l'écriture de la valeur de propriété, définissez un champ pour le stockage de la valeur de
propriété et fournissez la logique de base pour son stockage et son extraction :

class SampleClass
{
private int _sample;
public int Sample
{
// retourne une valeur après la lecture
get => _sample;
// Lu une valeur pour la retourne
set => _sample = value;
}
}
25
La plupart des propriétés disposent de méthodes ou de procédures destinées à la
fois à définir et à obtenir la valeur de propriété. Toutefois, vous pouvez créer des
propriétés en lecture seule ou en écriture seule pour empêcher qu'elles soient modifiées
ou lues. En C#, vous pouvez omettre la méthode de propriété get ou set. Toutefois, les
propriétés implémentées automatiquement ne peuvent pas être en écriture seule. Les
propriétés implémentées automatiquement en lecture seule peuvent être définies dans
les constructeurs de la classe conteneur.

1.4.2. Méthodes

Une méthode est une action que peut effectuer un objet. Pour définir une
méthode de classe :

class SampleClass
{
public int sampleMethod(string sampleParam)
{
// insérer les codes ici
}
}

Une classe peut avoir plusieurs implémentations, ou surcharges, de la même


méthode qui diffèrent du point de vue du nombre de paramètres ou des types de
paramètres. Pour surcharger une méthode :

public int sampleMethod(string sampleParam) {}


public int sampleMethod(int sampleParam) {}

Dans la plupart des cas, vous déclarez une méthode dans une définition de
classe. Toutefois, C# prend également en charge des méthodes d’extension, qui vous
permettent d’ajouter des méthodes à une classe existante hors de la définition réelle de
la classe.

1.4.3. Constructeurs

Les constructeurs sont des méthodes de classe qui s'exécutent automatiquement


lorsqu'un objet d'un type donné est créé. Les constructeurs initialisent habituellement
les données membres du nouvel objet. Un constructeur ne peut s'exécuter qu'une seule
fois lorsqu'une classe est créée.

En outre, le code figurant dans le constructeur s'exécute toujours avant tout


autre code dans une classe. Toutefois, vous pouvez créer plusieurs surcharges de
constructeur de la même façon que vous le faites pour toute autre méthode. Pour définir
un constructeur pour une classe :

public class SampleClass

26
{
public SampleClass()
{
// Add code here
}
}
1.4.4. Finaliseurs

Un finaliseur est utilisé pour détruire des instances de classes. Dans le .NET
Framework, le garbage collector gère automatiquement l'allocation et la libération de
mémoire pour les objets managés figurant dans votre application. Toutefois, vous
pouvez avoir besoin de finaliseurs pour nettoyer toutes les ressources non managées
créées par votre application. Il ne peut y avoir qu’un seul finaliseur pour une classe.
Pour déclarer un finaliseur :

Public class Etudiant


{
//vos codes
…………………
// methode de finaliseur
~Etudiant()
{
}
}

1.4.5. Événements

Les événements permettent à une classe ou un objet de notifier d'autres classes


ou objets lorsqu'une situation intéressante se produit. La classe qui envoie (ou
déclenche) l’événement est appelée éditeur et les classes qui reçoivent (ou gèrent)
l’événement sont appelées abonnés.
Pour déclarer un événement dans une classe, utilisez le mot clé event. Pour
déclencher un événement, appelez le délégué d'événement. Pour vous abonner à un
événement, utilisez l'opérateur += ; pour annuler un abonnement à un événement,
utilisez l'opérateur -=.

1.4.6. Classes imbriquées

Une classe définie à l’intérieur d’une autre classe est dite imbriquée. Par défaut,
une classe imbriquée est privée.

class Container
27
{
class Nested
{
// ajouter tes codes ici.
}
}
Pour créer une instance de la classe imbriquée, utilisez le nom de la classe de
conteneur suivi d'un point, puis du nom de la classe imbriquée :

Container.Nested nestedInstance = new Container.Nested()

1.4.7. Modificateurs d’accès et niveaux d’accès

Toutes les classes et tous les membres de classe peuvent spécifier le niveau
d’accès qu’ils fournissent aux autres classes à l’aide des modificateurs d’accès. Les
modificateurs d’accès suivants sont disponibles :
Modificateur C# Définition
publique Tout autre code du même assembly ou d'un autre assembly qui y fait
référence peut accéder au type ou au membre.
priv Seul le code de la même classe peut accéder au type ou au membre.
Protect Seul le code de la même classe ou d'une classe dérivée peut accéder au
type ou au membre.
internal Tout code du même assembly, mais pas d'un autre assembly, peut
accéder au type ou au membre.
protected internal Tout code du même assembly ou toute classe dérivée dans un autre
assembly peut accéder au type ou au membre.
protégé privé Le code de la même classe ou d'une classe dérivée peut accéder au type
ou au membre dans l’assembly de la classe de base.

1.4.8. Instanciation de classes

Pour créer un objet, vous devez instancier une classe ou créer une instance de
classe.
SampleClass sampleObject = new SampleClass();

28
Après avoir instancié une classe, vous pouvez assigner des valeurs aux
propriétés et champs de l'instance et appeler des méthodes de classe.

sampleObject.sampleProperty = "Sample String";

sampleObject.sampleMethod();

Pour assigner des valeurs aux propriétés pendant le processus d'instanciation de la


classe, utilisez des initialiseurs d'objets :

SampleClass sampleObject = new SampleClass


{ FirstProperty = "A", SecondProperty = "B" };
1.4.9. Classes et membres statiques

Un membre statique de la classe est une propriété, une procédure ou un champ


que toutes les instances d’une classe partagent. Pour définir un membre statique :

static class SampleClass


{
public static string SampleString = "Sample String";
}

Pour accéder au membre statique, utilisez le nom de la classe sans créer d’objet
de cette classe :
Console.WriteLine(SampleClass.SampleString);

Les classes statiques dans C# ont uniquement des membres statiques et ne


peuvent pas être instanciées. Les membres statiques ne peuvent pas non plus accéder
aux propriétés, champs ou méthodes non statiques.

1.4.10. Types anonymes

Les types anonymes vous permettent de créer des objets sans écrire de définition
de classe pour le type de données. À la place, le compilateur se charge de générer une
classe. La classe ne possède pas de nom utilisable et contient les propriétés que vous
spécifiez lors de la déclaration de l'objet.
Pour créer une instance de type anonyme :

// sampleObject est une instance de type simple anonymous.


var sampleObject =
29
new { FirstProperty = "A", SecondProperty = "B" };

1.4.11. Héritage

Il vous permet de créer une nouvelle classe qui réutilise, étend et modifie le
comportement défini dans une autre classe. La classe dont les membres sont hérités
porte le nom de classe de base et la classe qui hérite de ces membres porte le nom de classe
dérivée.
Toutefois, toutes les classes dans C# héritent implicitement de la
classe Object qui prend en charge la hiérarchie de classes .NET et fournit des services
de bas niveau à toutes les classes.

Remarque
C# ne prend pas en charge l’héritage multiple. Vous pouvez donc spécifier une
seule classe de base pour une classe dérivée. Pour hériter d'une classe de base :

class DerivedClass:BaseClass {}

Par défaut, toutes les classes peuvent être héritées. Toutefois, vous pouvez
spécifier si une classe ne doit pas être utilisée comme classe de base ou créer une classe
qui peut être utilisée uniquement comme classe de base. Pour spécifier qu'une classe ne
peut pas être utilisée comme classe de base :

public sealed class A { }

Pour spécifier qu'une classe peut être utilisée uniquement comme classe de base
et ne peut pas être instanciée :

public abstract class B { }

 Remplacement de membres

Par défaut, une classe dérivée hérite de tous les membres de sa classe de base. Si
vous souhaitez modifier le comportement du membre hérité, vous devez le
substituer. Autrement dit, vous pouvez définir une nouvelle implémentation de la
méthode, de la propriété ou de l'événement dans la classe dérivée. Les modificateurs
suivants sont utilisés pour contrôler la façon dont les propriétés et les méthodes sont
substituées :

30
Modificateur C# Définition
virtual Autorise la substitution d'un membre de classe dans une classe dérivée.
override Substitue un membre virtuel (substituable) défini dans la classe de base.
abstraction Requiert qu'un membre de classe soit substitué dans la classe dérivée.
Modificateur new Masque un membre hérité d'une classe de base.

1.4.12. Interfaces

Tout comme les classes, les interfaces définissent un ensemble de propriétés,


méthodes et événements. Cependant, contrairement aux classes, les interfaces
n'assurent pas l'implémentation.
Elles sont implémentées par les classes et définies en tant qu'entités distinctes
des classes. Une interface représente un contrat, dans le sens où une classe qui
implémente une interface doit implémenter tous les aspects de cette interface
exactement telle qu'elle a été définie. Pour définir une interface :

interface ISampleInterface
{
void doSomething();
}

Pour implémenter une interface dans une classe :

class SampleClass : ISampleInterface


{
void ISampleInterface.doSomething()
{
// Method implementation.
}
}

1.4.13. Génériques

31
Les classes, les structs, les interfaces et les méthodes dans le .NET Framework
peuvent inclure des paramètres de type, qui définissent les types d’objets qu’ils peuvent
stocker ou utiliser. L’exemple le plus commun de génériques est une collection dans
laquelle vous pouvez spécifier le type d’objets à stocker dans une collection. Pour définir
une classe générique :

public class SampleGeneric<T>


{
public T Field;
}

Pour créer une instance de classe générique :


SampleGeneric<string> sampleObject = new SampleGeneric<string>();
sampleObject.Field = "Sample string";

1.4.14. Délégués

Un délégué est un type qui définit une signature de méthode et peut fournir une
référence à toute méthode avec une signature compatible. Vous pouvez appeler la
méthode par le biais du délégué.Les délégués sont utilisés pour passer des méthodes
comme arguments à d'autres méthodes.

Remarque
Les gestionnaires d'événements sont tout simplement des méthodes appelées
par le biais de délégués. Pour plus d’informations sur l’utilisation de délégués dans la
gestion des événements.
Pour créer un délégué :

public delegate void SampleDelegate(string str);

Pour créer une référence à une méthode qui correspond à la signature spécifiée
par le délégué :
class SampleClass
{
// Method that matches the SampleDelegate signature.
public static void sampleMethod(string message)
{
// Add code here.
}
// Method that instantiates the delegate.
void SampleDelegate()
{
SampleDelegate sd = sampleMethod;
32
sd("Sample string");
}
}

1.4.15. Afficher votre programme avec la méthode principale

1.4.16. Syntaxe d'une classe exécutable

Exemple1 de classe minimale :

class Exemple1 { }

Cette classe ne fait rien et ne produit rien. En fait, une classe quelconque peut
s'exécuter toute seule à condition qu'elle possède dans ces déclarations internes la
méthode Main qui sert à lancer l'exécution de la classe (fonctionnement semblable au
lancement d'un programme principal).

Exemple2 de squelette d'une classe minimale exécutable :

class Exemple2
{
static void Main(string[ ] args)
{ // c'est ici que vous écrivez votre programme principal
}
}

Exemple3 trivial d'une classe minimale exécutable :

class Exemple3
{
static void Main(string[ ] args)
{
System.Console.WriteLine("Bonjour !");
}
}

1.4.17. Exemples d'applications à une classe

class Application1
{
static void Main(string[ ] args)
{ /* inverse d'une suite de caractère dans un tableau par
permutation des deux extrêmes */
char [ ] Tablecar ={'a','b','c','d','e','f'} ;
int i, j ;
System.Console.WriteLine("tableau avant : "
+ new string(Tablecar));
for ( i = 0 , j = 5 ; i<j ; i++ , j-- )
33
{ char car ;
car = Tablecar[i];
Tablecar[i ]= Tablecar[j];
Tablecar[j] = car;
}
System.Console.WriteLine("tableau après : "
+ new string(Tablecar));
}
}

L'instruction "new string(Tablecar)" sert uniquement pour l'affichage, elle crée


une string à partir du tableau de char.

Contrairement à java il n'est pas nécessaire de sauvegarder la classe dans un


fichier qui porte le même nom, tout nom de fichier est accepté à condition que le suffixe
soit cs, ici "AppliExo1.cs". Lorsque l'on demande la compilation (production du
bytecode) de ce fichier source "AppliExo1.cs" le fichier cible produit en bytecode
MSIL se dénomme "AppliExo1.exe", il est alors prêt à être exécuté par la machine
virtuelle du CLR.

Le résultat de l'exécution de ce programme est le suivant :

tableau avant : abcdef


tableau après : fedcba

Exemple2

class Application2
{
static void Main(string[ ] args)
{ // recherche séquentielle dans un tableau
int [ ] table= {12,-5,7,8,-6,6,4,78,2};
int elt = 4, i ;
for ( i = 0 ; i<8 ; i++ )
if (elt= =table[i]) break ;
if (i = = 8) System.Console.WriteLine("valeur : "+elt+" pas
trouvée.");
else System.Console.WriteLine("valeur : "+elt+" trouvée au rang :"+i);
}
}

Après avoir sauvegardé la classe dans un fichier xxx.cs, ici "AppliExo2.cs", la


compilation de ce fichier "AppliExo2.cs" produit le fichier "AppliExo2.exe" prêt à être
exécuté par la machine virtuelle du CLR.

Le résultat de l'exécution de ce programme est le suivant :

34
valeur : 4 trouvée au
rang : 6

1.4.18. Les méthodes sont des fonctions

Les méthodes ou bien fonctions représentent une encapsulation des instructions


qui déterminent le fonctionnement d'une classe. Sans méthodes pour agir une classe ne
fait rien de particulier, dans ce cas elle ne fait que contenir des attributs.

a. Méthode élémentaire de classe

Bien que C# distingue deux sortes de méthodes : les méthodes de classe et


les méthodes d'instance, pour l'instant dans cette première partie nous décidons à titre
pédagogique et simplificateur de n'utiliser que les méthodes de classe, le chapitre sur
C# et la programmation orientée objet apportera les compléments adéquats.

 Déclaration d'une méthode

La notion de fonction en C# est semblable à celle de Java, elle comporte un en-


tête avec des paramètres formels et un corps de fonction ou de méthode qui contient les
instructions de la méthode qui seront exécutés lors de son appel. La déclaration et
l'implémentation doivent être consécutives comme l'indique la syntaxe ci-dessous :

Syntaxe :

Corps de fonction :

Nous dénommons en-tête de fonction la partie suivante :


<qualificateurs><type du résultat><nom de fonction> (<liste paramètres formels>)
35
Sémantique :

 Les qualificateurs sont des mots clef permettant de modifier la visibilité ou


le fonctionnement d'une méthode, nous n'en utiliseront pour l'instant
qu'un seul : le mot clef static permettant de désigner la méthode qu'il
qualifie comme une méthode de classe dans la classe où elle est déclarée.
Une méthode n'est pas nécessairement qualifiée donc ce mot clef peut être
omis.
 Une méthode peut renvoyer un résultat d'un type C# quelconque en
particulier d'un des types élémentaires
(int, byte, short, long, bool, double, float, char...) et nous verrons plus loin
qu'elle peut renvoyer un résultat de type objet comme en Delphi. Ce mot
clef ne doit pas être omis.

 Il existe en C# comme en C une écriture fonctionnelle correspondant aux


procédures des langages procéduraux : on utilise une fonction qui ne
renvoie aucun résultat. L'approche est inverse à celle du pascal où la
procédure est le bloc fonctionnel de base et la fonction n'en est qu'un cas
particulier. En C# la fonction (ou méthode) est le seul bloc fonctionnel de
base et la procédure n'est qu'un cas particulier de fonction dont le retour
est de type void.

 La liste des paramètres formels est semblable à la partie déclaration de


variables en C# (sans initialisation automatique). La liste peut être vide.

 Le corps de fonction est identique au bloc instruction C# déjà défini


auparavant. Le corps de fonction peut être vide (la méthode ne représente
alors aucun intérêt).

Exemples d'en-tête de méthodes sans paramètres en C#

int calculer( ){.....} renvoie un entier de type int


bool tester( ){.....} renvoie un entier de type boolean
void uncalcul( ){.....} procédure ne renvoyant rien

Exemples d'en-tête de méthodes avec paramètres en C#

int calculer(byte a, byte b, int x ) {.....} fonction à 3 paramètres


bool tester( int k) {.....} fonction à 1 paramètre
void uncalcul(int x, int y, int z ) {.....} procédure à 3 paramètres

 Appel d'une méthode

36
L'appel de méthode en C# s'effectue très classiquement avec des paramètres
effectifs dont le nombre doit obligatoirement être le même que celui des
paramètres formels et le type doit être soit le même, soit un type compatible ne
nécessitant pas de transtypage.

Exemple d'appel de méthode-procédure sans paramètres en C#


class Application3
{
static void Main(string[ ] args)
{
afficher( );
Appel de la
}
static void afficher( ) méthode afficher
{
System.Console.WriteLine("Bonjour");
}
}

Exemple d'appel de méthode-procédure avec paramètres de même type en C#

class Application4
{ static void Main(string[ ] args)
{ // recherche séquentielle dans un
tableau
int [ ] table= {12,-5,7,8,-
6,6,4,78,2}; Appel de la méthode afficher
long elt = 4; afficher(i,elt);
int i ; Les deux paramètres
for ( i = 0 ; i<=8 ; i++ )
effectifs "i" et "elt" sont du
if (elt= =table[i]) break ;
afficher(i,elt); même type que le paramètre
} formel associé.
static void afficher
(int rang , long val) - Le paramètre effectif "i" est
associé au paramètre formel rang.
{ if (rang == 8)
System.Console.WriteLine("valeur - Le paramètre effectif "elt" est
: "+val+" pas trouvée."); associé au paramètre formel val.
else
System.Console.WriteLine("valeur
: "+val+" trouvée au rang :"+ rang);
}
}

1.4.19. Transmission des paramètres en C#

37
Rappelons tout d'abord quelques principes de base : Dans tous les langages
possédant la notion de sous-programme (ou fonction ou procédure), il se pose une
question à savoir : à quoi servent les paramètres formels ? Les
paramètres formels décrits lors de la déclaration d'un sous-programme ne sont que des
variables muettes servant à expliquer le fonctionnement du sous-programme sur des
futures variables lorsque le sous-programme s'exécutera effectivement.

La démarche en informatique est semblable à celle qui, en mathématiques,


consiste à écrire la fonction f(x) = 3*x - 7, dans laquelle x est une variable muette
indiquant comment f est calculée : en informatique elle joue le rôle du paramètre
formel. Lorsque l'on veut obtenir une valeur effective de la fonction mathématique f,
par exemple pour x=2, on écrit f(2) et l'on calcule f(2)=3*2 - 7 = -1. En informatique on
"passera" un paramètre effectif dont la valeur vaut 2 à la fonction. D'une manière
générale, en informatique, il y a un sous-programme appelant et un sous-programme
appelé par le sous-programme appelant.

 Compatibilité des types des paramètres

Resituons la compatibilité des types entier et réel en C#. Un moyen


mnémotechnique pour retenir cette compatibilité est indiqué dans les figures ci-
dessous, par la taille en nombre décroissant de bits de chaque type que l'on peut
mémoriser sous la forme "qui peut le plus peut le moins" ou bien un type à n bits
acceuillera un sous-type à p bits, si p est inférieur à n.

Compatibilité ascendante des types de variables en C# (conversion implicite sans


transtypage obligatoire)

Les types entiers signés : Les types entiers non signés :

38
Les réels :

Exemple d'appel de la même méthode-procédure avec paramètres de type


compatibles en C#

class Application5
{ static void Main(string[ ] args) Appel de la méthode
{ // recherche séquentielle dans un afficher
tableau afficher(i,elt);
int [ ] table= {12,-5,7,8,- Les deux paramètres
6,6,4,78,2};
effectifs "i" et "elt" sont
sbyte elt = 4;
short i ; d'un type compatible avec
for ( i = 0 ; i<8 ; i++ ) celui du paramètre formel
if (elt= =table[i]) break ; associé.
afficher(i,elt);
} - Le paramètre effectif "i" est
static void afficher associé au paramètre
formel rang.(short = entier
(int rang , long val)
signé sur 16 bits et int = entier
{ if (rang == 8) signé sur 32 bits)
System.Console.WriteLine("valeur
: "+val+" pas trouvée."); - Le paramètre effectif "elt" est
else associé au paramètre
System.Console.WriteLine("valeur formel val.(sbyte = entier signé
: "+val+" trouvée au rang :"+ rang); sur 8 bits et long = entier signé
sur 64 bits)
}
}

Les trois modes principaux de transmission des paramètres

 passage par valeur


 passage par référence
 passage par résultat

39
Un paramètre effectif transmis au sous-programme appelé est en fait un moyen
d’utiliser ou d’accéder à une information appartenant au bloc appelant (le bloc appelé
peut être le même que le bloc appelant, il s’agit alors de récursivité).

La question technique qui se pose en C# comme dans tout langage de programmation


est de connaître le fonctionnement du passage des paramètres :

En C#, ces trois modes de transmission (ou de passage) des paramètres (très
semblables à Delphi) sont implantés.

40
a) Les paramètres C# passés par valeur

Le passage par valeur est valable pour tous les types élémentaires
(int, byte, short, long, boolean, double, float, char) et les objets.

En C# tous les paramètres sont passés par défaut par valeur (lorsque le
paramètre est un objet, c'est en fait la référence de l'objet qui est passée par valeur). Pour ce
qui est de la vision algorithmique de C#, le passage par valeur permet à une variable
d'être passée comme paramètre d'entrée .

static int methode1(int a , char b) {


//.......
return a+b;
}

Cette méthode possède 2 paramètres a et b en entrée passés par valeur et


renvoie un résultat de type int.

b) Les paramètres C# passés par référence

Le passage par référence est valable pour tous les types de C#.

En C# pour indiquer un passage par référence on précède la déclaration du


paramètre formel du mot clef ref :

41
static int methode1(int a , ref char b) {
//.......
return a+b;
}

Lors de l'appel d'un paramètre passé par référence, le mot


clef ref doit obligatoirement précéder le paramètre effectif qui doit
obligatoirement avoir été initialisé auparavant :

int x = 10, y = '$', z = 30;


z = methode1(x, ref y) ;

c) Les paramètres C# passés par résultat

Le passage par résultat est valable pour tous les types de C#.

En C# pour indiquer un passage par résultat on précède la déclaration du


paramètre formel du mot out :

static int methode1(int a , out char b) {


//.......
return a+b;
}

Lors de l'appel d'un paramètre passé par résultat, le mot


clef out doit obligatoirement précéder le paramètre effectif qui n'a pas besoin
d'avoir été initialisé :
int x = 10, y , z = 30;
z = methode1(x, out y) ;

Remarque :

Le choix de passage selon les types élimine les inconvénients dus à


l'encombrement mémoire et à la lenteur de recopie de la valeur du paramètre par

42
exemple dans un passage par valeur, car nous verrons plus loin que les tableaux en
C# sont des objets et que leur structure est passée par référence.

1.4.20. Les énumérations et structure

En plus des classes, d'autres types de données existent, notamment les


structures et les énumérations. Ces premières vont parfois êtres utilisées à la place de
classes, leur comportement est quasiment semblable, seules quelques notions
changeront. Quant aux énumérations, comme leur nom l'indique elles permettront
d'avoir une variable qui ne peut avoir qu'une des valeurs définies au préalable.

 Les énumérations
Une énumération va être une variable qui ne pourra avoir que certaines valeurs
prédéfinies. Imaginons par exemple un doigt, un doigt ne pourrait avoir que cinq
valeurs différentes (pouce, index, majeur, annulaire et auriculaire).
Bien entendu, ce sera à nous de créer nos énumérations, ceux qui ont créé .net
ne se sont pas amusés à fabriquer toutes les énumérations possibles et inimaginables .
- Création
La manière de créer une énumération va être simple : généralement, pour plus
de clarté, nous créons un fichier pour chaque énumération, classe et structure, nous
allons donc ajouter un nouveau fichier à notre projet. Pour cela, faite un clic droit sur
votre projet "Ajouter" ("Add") puis "Classe" ("Class"), là une fenêtre avec différents
types de fichier proposés va s'ouvrir, le fichier "classe" va être présélectionnée, nous
n'aurons donc qu'à lui donner un nom dans le champ de texte en bas (nous l'appelons
"Doigt" dans notre cas) et valider. Un code de base sera généré:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExempleConsole
{
class Doigt
{
}
}

43
Sauf que ce n'est pas une classe (mot clé "class") que nous voulons, mais une
énumération (mot clé "enum"), nous enlevons donc "class" que nous remplaçons par
"enum", ce qui nous donnera l'extrait de code suivant :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ExempleConsole
{
enum Doigt
{

}
}

Voilà notre énumération créée, il ne nous reste plus qu'a lui donner les
différents valeurs qu'elle peut avoir, nous plaçons ces valeurs entre les accolades ( " { "
et "" } ") juste en dessous de "enum Doigt", chacune séparée par une virgule et,
optionnellement, un espace. Attention les valeurs ne peuvent contenir que des lettres
minuscules, majuscules et des underscores ( " _ " ).
Dans notre cas nous aurons cinq valeurs :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MenuConsole
{
enum Doigt
{
Pouce,
Index,
Majeur,
Annulaire,
Auriculaire
}
}
Notre énumération est prête à être utilisée
- Déclaration
Pour cela, nous faisons comme pour un entier ou une chaine de caractère : (code
à taper entre les accolades de Main comme dans la partie sur les types primitifs)
static void Main(string[] args)
{
Doigt monDoigt;
44
}
- Assignation
Pour assigner un enum, la syntaxe sera la suivante: monEnum =
TypeEnum.Valeur;.
Si nous voulons par exemple que "monDoigt" soit un index nous ferrons:
static void Main(string[] args)
{
Doigt monDoigt;
monDoigt = Doigt.Index;
}
- Conversion enum vers entier
Un avantage de l'enum est que nous pouvons lui donner une valeur entière et,
vice versa, nous pouvons à partir d'un entier obtenir un type énumératif. Par exemple:
Doigt monDoigt;
monDoigt = Doigt.Index;
int valeurDeMonDoigt = (int)monDoigt;//valeurDeMonDoigt vaudra 1 (les énumér
ation commencent à 0)
Doigt autreDoigt = (Doigt)3;//autreDoigt vaudra Doigt.Annulaire

1.5. Premier Exercice


1.5.1. Enoncé
Pour ce premier exercice, nous allons créer le modèle de données d'un petit jeu
de rôle. Celui-ci ne révolutionnera pas le monde du jeu vidéo, mais vous fourniras un
premier entrainement pratique en C#.
 Qu'est-ce qu'un modèle de données ?
Pour connaitre un modèle de donné, expliquons d’abord de patron de conception
et d'architecture logicielle. Plus généralement, chaque programme est souvent divisé en
plusieurs parties, et l'architecture logicielle est l'interaction entre ces différentes parties.
On parle alors d'architectures n-tiers où "n" est un nombre représentant le nombre de
"parties".
De manière courante on utilise une architecture 3-tiers, c'est à dire, que lors de
sa conception, notre programme va être créée en trois parties bien distinctes.
Généralement il y aura une partie "vue" qui s'occupera seulement de l'affichage, une
partie structure de données et une partie traitement. L'avantage c'est qu'entre les
différentes parties il y a des interactions mais très peu de dépendances, c'est à dire que
si par exemple nous modifions l'apparence de l'application nous devrons seulement
modifier la partie "vue", ou si nous traitons différemment les données, la partie "vue"
et la partie structure de données ne seront pas impactées.

45
Le modèle de données (ou "Model" en anglais) en architecture 3-tiers va être la
partie structure de données citée un peu plus haut, c'est ce que nous allons créer dès à
présent ;)
 Énoncé
Pour votre premier modèle, on va faire bien, mais pas trop complexe. Il nous
faudra créer deux types de personnages:
Un héros qui aura
Un nom

 Des points de vie
 Une position
 Une épée
Celui-ci pourra
Attaquer un adversaire

 Recevoir des dégâts
 Faire une bonne action
 Se déplacer
Nous créerons aussi un monstre qui aura
 Un nom
 Des points de vie
 Une position
 Un gourdin
Et celui-ci pourra
 Attaquer un adversaire
 Recevoir des dégâts
 Se nourrir
 Se déplacer

Ensuite nous aurons deux types d'armes, l'épée et le gourdin.


 L'épée aura
 Un nom
 Des dégâts
 Une longueur

 Le gourdin aura
 Un nom
 Des dégâts
 Une masse

A la fin nous aurons besoin d'une classe Jeu qui fera par la suite combattre nos
deux joueurs. Elle devra donc avoir un héros et un ennemi.
46
1.5.2. Résolution
 La classe Arme
Nous pouvons commencer par représenter l'épée et le gourdin, elles ont toute
deux des champs communs : le nom et les dégâts. Nous allons donc commencer à créer
une classe abstraite que nous nommerons par exemple "arme" avec un constructeur
initialisant les deux champs :

public abstract class Arme


{
#region Propriétés
public string Nom { get; private set; }
public int Degats { get; private set; }
#endregion

#region Constructeur
public Arme(string nom, int degats)
{
this.Nom = nom;
this.Degats = degats;
}
#endregion
}

Ensuite nous faisons hériter cette classe dans deux autres classes : Epee et Gourdin :
 La classe Epee
public class Epee : Arme
{
#region Propriétés
public double Longueur { get; private set; }
#endregion

#region Constructeur
public Epee(string nom, int degats, double longueur)
: base(nom, degats)
{
this.Longueur = longueur;
}
#endregion
}
 La classe Gourdin

47
public class Gourdin : Arme
{
#region Propriétés
public double Poids { get; private set; }
#endregion

#region Constructeur
public Gourdin(string nom, int degats, double poids):base(nom, degats)
{
this.Poids = poids;
}
#endregion
}
Remarquez ici que nous réutilisons même le constructeur de base que nous
enrichissons en lui faisait prendre un paramètre de plus (longueur pour Epee et poids
pour Gourdin).
 Les personnages
Ici ce n'est pas moins de quatre champs et trois méthodes qui peuvent être
abstraites entre le héros et le monstre. Pour la démonstration, une méthode est
"normale", une méthode est virtuelle et une méthode est abstraite :
abstract class EtreVivant
{
#region Propriétés
public int PositionY { get; private set; }

public int PositionX { get; private set; }

public string Nom { get; private set; }

public int PointsDeVie { get; private set; }


#endregion

#region Constructeur
public EtreVivant(string nom, int pointsDeVie)
{
this.Nom = nom;
this.PointsDeVie = pointsDeVie;
}
#endregion

#region Methodes
public void SePositionner(int positionX, int positionY)
{
this.PositionX = positionX;
this.PositionY = positionY;
}
public virtual void Attaquer(EtreVivant cible)
{
48
cible.RecevoirDegats(this);
}
public abstract void RecevoirDegats(EtreVivant source);
#endregion
}
Vous allez remarquer que ici, nous n’avons pas mis de corps à la méthode
"RecevoirDegats" étant donné que nous serons obligé de lui fournir dans les classes
héritières. Pour une méthodes sans corps, nous sommes obligés de remplacer les
accolades par un point-virgule pour que le fichier de code passe la compilation.
Concernant la méthode "Attaquer", nous lui passons ici en paramètre un objet de type
EtreVivant duquel nous appelons la méthode "RecevoirDegats", si vous n'avez pas fait
pareil ce n'est pas grave ce TP est fait pour s'entrainer à créer nos classes, les divers
traitement que nous faisons ont pour l'instant peu d'importance ;)
 Heros
Les seuls ajouts à faire ici sont l'Epee et la méthode "FaireUneBonneAction".
Pour les autres méthodes, nous utilisons le mot-clé override pour les ré-implémenter.
class Heros : EtreVivant
{
#region Proprietes
public Epee Epee { get; private set; }
#endregion

#region Constructeur
public Heros(string nom, int pointsDevie, Epee epee)
: base(nom, pointsDevie)
{
Epee = epee;
}
#endregion

#region Methodes
public override void Attaquer(EtreVivant cible)
{
base.Attaquer(cible);
Console.WriteLine("Le héros " + Nom + " attaque " + cible.Nom);
}
public override void RecevoirDegats(EtreVivant source)
{
Console.WriteLine(Nom + " s'est fait attaqué par " + source.Nom);
}
public void FaireUneBonneAction()
{
Console.WriteLine(Nom + " a fait une bonne action et en récompense,
sa vie remonte ! ");
}
#endregion
}

49
Comme les implémentations de Arme, nous enrichissons le constructeur de
base, mais cette fois-ci avec trois paramètres supplémentaires (nomArme, degatsArme
et longueurEpee) et ensuite nous instancions la propriété "Epee" grâce aux paramètres
précédemment récupérés.
 Monstre
Pour la classe Monstre, il n'y pas de difficultés supplémentaires par rapport à
Heros, on ajoute juste le champ et la méthode spécifique à Monstre :
class Monstre : EtreVivant
{
#region Attributs
public Gourdin Gourdin { get; private set; }
#endregion

#region Constructeur
public Monstre(string nom, int pointDevie, Gourdin gourdin):base(nom, po
intDevie)
{
Gourdin = gourdin;
}
#endregion

#region Methodes
public override void Attaquer(EtreVivant cible)
{
Console.WriteLine(Nom + " le gros monstre a attaqué " + cible.Nom);
}
public override void RecevoirDegats(EtreVivant source)
{
Console.WriteLine(Nom + " a reçu des dégâts de " + source.Nom);
}
public void SeNourrir()
{
Console.WriteLine(Nom + " se nourri et regagne de la santé");
}
#endregion
}

 Classe Jeu
Pour finir, nous aurions pu éviter de créer cette classe et tout faire dans la classe
Program. Mais en général, nous mettons le moins de code possible dans la classe
Program et nous préférons créer une classe "de démarrage" à part. Cette classe est
surtout utile pour des traitements, mais étant donné que nous ne savons pas encore en
faire, nous créerons juste deux champs et propriétés de type Monstre et Heros :
public class Jeu
{
#region Attributs
50
public Heros Gentil { get; private set; }
public Monstre Ennemi { get; private set; }
#endregion

#region Constructeur
public Jeu(Heros gentil, Monstre ennemi)
{
this.Gentil = gentil;
this.Ennemi = ennemi;
}
#endregion
}

Même si lors de la compilation ce programme ne fait rien, nous avons déjà fait
beaucoup : en effet comme je vous l'ai dit précédemment, dans tout programme vous
aurez un modèle de données (plus ou moins important, certes) et la création de ce
modèle de donnée est primordiale avant de réaliser les traitements.

1.6. Deuxième Exercice


1.6.1. Enoncé
Pour cela nous allons enrichir le TP sur le jeu de rôle en ajoutant des
énumérations.
Une utilisation courante des énumérations est la représentation d'états. Nous
allons donc ajouter une énumération pour l'état des être vivants et une pour l'état des
armes. Par exemple pour l'état des êtres vivants, nous allons en définir trois : Normal,
Blesse et Mort. Ce qui nous donnera :
enum EtreVivantEtat
{
Normal,
Blesse,
Mort
}
Et pour le code de EtreVivant (je ne remet ici que les champs et les propriétés) :
abstract class EtreVivant
{
#region Champs
protected int _pointDeVie;
protected string _nom;
private int _positionX;
private int _positionY;
private EtreVivantEtat _etat;
#endregion

#region Attributs
public EtreVivantEtat Etat
{

51
get { return _etat; }
set { _etat = value; }
}
public int PositionY
{
get { return _positionY; }
set { _positionY = value; }
}
public int PositionX
{
get { return _positionX; }
set { _positionX = value; }
}
public string Nom
{
get { return _nom; }
set { _nom = value; }
}
public int PointsDeVie
{
get { return _pointDeVie; }
set { _pointDeVie = value; }
}
#endregion
}

Quant à l'état des armes, nous en définissons aussi trois : Neuf, Usee et
Inutilisable:
enum EtatArme
{
Neuf,
Use,
Inutilisable
}

Et nous ajoutons un champ et sa propriété de type EtatArme dans la classe


Abstraite Arme:
abstract class Arme
{
private EtatArme _etat;

public EtatArme Etat


{
get { return _etat; }
set { _etat = value; }
}
protected string nom;
public string Nom
{
52
get { return nom; }
set { nom = value; }
}
private int degats;
public int Degats
{
get { return degats; }
set { degats = value; }
}
public Arme(string nom, int degats)
{
this.Nom = nom;
this.Degats = degats;
}
}
Vous pouvez ajouter des énumérations un peu partout et servies à toute les
sauces, pour achever cela).

1.7. Travail Pratique

a. Écrivez un programme C # Sharp pour trier une liste d'éléments à l'aide du tri
par bulles. Selon Wikipedia, «le tri à bulles, parfois appelé tri par affaissement,
est un algorithme de tri simple qui parcourt à plusieurs reprises la liste à trier,
compare chaque paire d'éléments adjacents et les échange s'ils sont dans le
mauvais ordre. La liste est répétée jusqu'à ce qu'aucun échange ne soit nécessaire,
ce qui indique que la liste est triée. L'algorithme, qui est un tri par comparaison,
est nommé en fonction de la façon dont les éléments plus petits "remontent" en
haut de la liste. Bien que l'algorithme soit simple, il est trop lent et peu pratique
pour la plupart des problèmes, même par rapport au tri par insertion. Cela peut
être pratique si l'entrée est généralement dans l'ordre de tri, mais peut parfois
avoir des éléments dans le désordre presque en position.
b. Concevoir un jeu qui permet à notre cochon d’inde de chercher sa nourriture
mais dans cette ville où il vit, il y a des dégâts causé par des chats qui ont aussi
faim. Le cochons d’inde n’as pas d’arme seul le déplacement qui lui permet de
fuir son adversaire.

53
CHAPITRE 2 : PRESENTATION DE L’UNITY

2.1. Présentation

Unity est un moteur 3D de création de


jeux/d'applications, qui intègre le PhysX de Nvidia. Il
n'est pas un modeliseur, mais fonctionne avec une scène
3D gérant lumières, shaders, caméras etc.
Il permet l'insertion de code dans différents langages, allant du Javascript au C-
sharp, séparément ou même simultanément. Des plug-ins d'aide à la création sont
intégrés au soft, tel un générateur de terrain, de végétation, ou encore des packs préfaits
facilitant le contrôle du joueur, des caméras etc...
Unity utilise un système de « drag and drop » dans son interface, ainsi qu'un
système d'Assets, sortes de « clips » pour ceux qui ont déjà utilisés Flash.
Intuitif et puissant donc, il présente l'énorme avantage d'autoriser une
publication multi-plateformes (Playstation3,Xbox, Wii, PC/MAC, WebPlayer,
iOS,Android).
Unity est un outil de création 3D pour Mac OS et Windows. Les moteurs de
jeux sont les mécanismes qui fonctionnent en coulisse de tous les jeux vidéo. Ce
"moteur" prend les décisions, qu’il s’agisse des graphismes ou des mathématiques qui
régissent chaque image à l’écran. À partir du rendu – l’affichage des graphismes à
l’écran, l’intégration d’une méthode de contrôle et d’un ensemble de règles à suivre pour
le jeu –, les développeurs s’appuient sur le moteur pour "construire" le jeu. Les moteurs
de jeu 3D actuels reposent sur une quantité impressionnante de code méticuleusement
écrit. C’est pourquoi ils sont souvent revendus, modifiés et réutilisés, une fois que le
jeu pour lequel ils ont été créés est terminé. Le moteur Unreal Engine d’Epic Games en
est un bon exemple. Développé à l’origine, à la fin des années 90 pour Unreal – un jeu
de tir à la première personne (FPS) –, il a ensuite été réutilisé sous licence par d’autres
développeurs et a connu un énorme succès dans des centaines de simulations et de jeux
commerciaux plus récents.
Les développeurs de moteurs de jeux construisent également des outils pour
commander les fonctions de code qu’ils ont créées. Par exemple, un ensemble
d’instructions définit la forme (ou topographie) d'un terrain, son aspect visuel, et même
la façon dont sont gérées ses déformations dans le jeu. Mais cet ensemble d’instructions
serait inefficace en tant qu’élément du moteur de jeu s’il n’était pas relié à un outil
visuel permettant de contrôler ces propriétés. Souvent, les développeurs de moteur de
jeu créent donc une interface graphique (GUI, Graphical User Interface) afin que les

54
membres de l’équipe de développement du jeu puissent plus facilement manipuler les
éléments du moteur.
Ces outils facilitent non seulement le processus de création du jeu mais rendent
également le moteur accessible aux acheteurs potentiels et aux équipes de
postproduction. Cela est également vrai pour Unity, et une très importante
communauté d’utilisateurs partage ses outils sous forme de plugins.
2.2. Historique
Unity est un moteur de jeu multiplateforme (smartphone, ordinateur, consoles
de jeux vidéo et Web) développé par Unity Technologies. Il est l'un des plus répandus
dans l'industrie du jeu vidéo, aussi bien pour les grands studios que pour
les indépendants du fait de sa rapidité aux prototypages et qu'il permet de sortir les jeux
sur tous les supports.
Il a la particularité de proposer une licence gratuite dite « Personal » avec
quelques limitations de technologie avancée au niveau de l'éditeur, mais sans limitation
au niveau du moteur.
Le logiciel a la particularité d'utiliser du code (C#) sur la plateforme « .NET »
avec l'implémentation Mono. Son éditeur était auparavant basé sur MonoDevelop, via
MonoDevelop-Unity, mais à partir de la version 2018.1, il est basé sur Visual Studio
Community. Il permet toujours de sortir du code Mono, ayant l'avantage d'être
multiplateforme et multi-architecture, mais permet également, via son backend
« IL2CPP », de générer du code intermédiaire C++ afin de pouvoir générer des binaires
natifs (.exe, APK…). Ce backend permet également de générer des applications
pour iOS et WebGL.
UnityScript (un langage proche du JavaScript et inspiré d'ECMAScript et
arrêté depuis la version 2017.2) et Boo2 (arrêté à la version 5.0) au lieu de Lua très utilisé
dans les jeux vidéo. Son approche est orientée asset, par le biais d'un EDI dédié, à la
différence des moteurs comme le Quake engine dont les éléments centraux sont les
codes sources. Il est l'équivalent du logiciel de création Director pour la 2D qui
utilise Lingo. Il se rapproche plus pour la 3D des logiciels tels que Shiva, Virtools,
Cheetah3D. Parmi les logiciels d'animations, il ne permet pas la modélisation (sauf
depuis la version 2018.1) mais permet de créer des scènes supportant des éclairages,
des terrains, des caméras, des textures, la musique et les vidéos. Il est par ces
fonctionnalités un mélange de VRML et de QuickTime.
2.3. Plateformes supportées
Le logiciel de conception développé d'abord pour la plate-forme Mac a été porté
sous Windows et permet d'obtenir des applications compatibles Windows, Mac OS
X, iOS, Android, TV OS, PlayStation 3, PlayStation Vita, PlayStation 4, Xbox
360, Xbox One, Xbox One X, Windows Phone 8, Windows 10 Mobile , PlayStation
Mobile, Tizen, Oculus Rift, Wii U, Nintendo 3DS, Nintendo
Switch, WebGL, Samsung TV, dans une page web grâce à un plugin, ou depuis la
55
version 3.5 le format Flash d'Adobe, bien que cette dernière option ait été retirée fin
avril 20133.
La version 4.0, sortie en novembre 2012, intègre le développement de jeux
compatibles avec Linux4,5. Les jeux développés pourront ainsi fonctionner sous Linux.
Depuis le 25 août 2015, Unity lui-même est disponible sous Linux avec des restrictions
d'exports (pas d'export Windows par exemple). Le support de jeux compatibles avec
Linux s'appuie dans un premier temps sur la distribution Ubuntu et sur les pilotes
propriétaires fournis par les fabricants de cartes graphiques. Unity 3D collabore
avec Canonical au sein d'une équipe dédiée aux jeux vidéo.
Le support Linux est cependant limité aux systèmes d'exploitation mobiles
(Android et iOS) et aux processeurs x86 sur ordinateur de bureau.
Il est capable d'importer de nombreux formats 3D (Blender, Maya, Cinema
4D, Cheetah3D (en), FBX), des ressources variées : (des
textures Photoshop, PNG, TIFF, audios, vidéos) qu'il optimise par l'utilisation de
filtres.
Unity possède une large palette de déploiement :
 il est compatible avecles API graphiques Direct3D4, OpenGL4 , Vulkan11, VR.
 les navigateurs web peuvent, grâce au plugin Unity Web Player, afficher les
productions du moteur ;
 il est compatible avec QuickTime et utilise en interne le format Ogg Vorbis.

Depuis la création d'Unity, une chaîne officielle a vu le jour sur YouTube et


recensait en novembre 2019 environ 677 000 abonnés et plus de 500 mentions « J'aime
» sur chaque vidéo. Très active, la chaîne propose environ tous les mois la rediffusion
des Unity Awards, là où les meilleurs jeux de toutes les catégories produits avec le
moteur Unity sont récompensés, cela accompagné de tutoriels, d'explications, de
compilations des meilleurs jeux et des démonstrations de la performance et des
capacités offertes par Unity. La chaîne permet ainsi aux développeurs expérimentés
d'en apprendre plus et aux novices de visualiser une large palette de créations de la
communauté Unity.
Unity met aussi à la disposition des débutants des projets de jeux pré-faits, ainsi
qu'un site internet avec des tutoriels gratuits, ou encore différents forums pour les
aider.
En date du 2 août 2013, le logiciel n'était disponible que dans une version payante
et une version gratuite :
 la licence payante est facturée à l'achat un système de paiement par mois ou en
une fois, une licence pour deux postes de travail sans royalties ;
 la licence gratuite est disponible en gratuiciel (freeware), elle ne présente pas de
coût d'acquisition et pas de royalties, mais toutes les fonctionnalités ne sont pas
56
disponibles et les jeux ou animations produits incluent un écran de démarrage
ou un tatouage numérique (watermark) Unity.
2.3. Fonctionnement
Un moteur de jeu est le logiciel qui fournit aux créateurs de jeux l'ensemble de
fonctionnalités nécessaires pour concevoir des jeux rapidement et efficacement.
Un moteur de jeu est un environnement de développement de jeux qui prend
en charge et réunit plusieurs domaines majeurs. Vous pouvez importer des ressources,
des éléments artistiques, 2D et 3D, depuis d'autres logiciels comme Maya, 3s Max ou
Photoshop ; assembler ces ressources en scènes et en environnements ; ajouter des
éclairages, de l'audio, des effets spéciaux, des physiques, des animations, de
l'interactivité et une logique de gamplay ; et éditer, corriger et optimiser le contenu pour
vos plateformes cibles.
2.4. Installation de Unity
Double-cliquez sur le fichier d’installation précédemment téléchargé. Vous
pouvez conserver les réglages d’installation par défaut et attendre que l’installation soit
complète, faites preuve de patience, cela prend un peu de temps.

Au terme de cette procédure d’installation, vous aurez à disposition sur votre


machine : l’environnement de développement de Jeux Vidéo Unity, la documentation
d’Unity (en anglais), une version modifiée de la suite de développement logiciel
MonoDevelop (que nous n’aborderons pas), ainsi qu’un projet de démonstration que
vous aurez le loisir de découvrir à la fin de cette partie.
En cliquant sur Finish(Terminer), Unity se lancera pour la première fois sur
votre machine.

57
Procédure d'activation
Si tout se passe comme prévu, il est maintenant temps d’activer votre logiciel.
Je vous propose ici de choisir la deuxième option, à savoir l’activation d’une license
gratuite d’Unity qui nous sera largement suffisante. Il est toutefois nécessaire de
disposer d’un compte Unity, si vous n’en avez pas, cliquez sur Create Account et
renseignez les informations demandées. Comme souvent maintenant, il vous sera
nécessaire de cliquer sur un lien de confirmation qui vous sera envoyé par mail.
Une fois cela fait, vous n’avez plus qu’à rentrer vos informations de connexion
sur la fenêtre d’activation. Vous pourrez prendre quelques minutes également pour
renseigner quelques informations personnelles à usage statistique pour Unity. À la
suite de cela, deux options sont possibles, soit une fenêtre vous propose d’ouvrir un
projet existant ou de créer un nouveau projet, soit l’éditeur s’ouvre automatiquement
avec le projet de démonstration pré-chargé.
Quel que soit le cas, vous pouvez fermer cette fenêtre, nous en avons
maintenant terminé avec ce premier chapitre, et avant de commencer à nous servir de
ce fantastique outil, il est nécessaire de faire un état des lieux de ce qu’est Unity et à
quoi ce dernier va nous servir.

2.5. Exemple sur le 2D

Tout d'abord, vous aurez besoin du fichier compressé appelé "Sprites". Cliquez sur
l'onglet "Project". Déposez ce fichier compressé dans la zone grise à droite. Tous les
éléments dont vous aurez besoin pour reproduire mon projet sont dans ce fichier .

58
Trouvez l'élément appelé "navbar". Cliquez dessus et déposez-le en bas de la fenêtre
"Scène" comme sur la capture d'écran.

Si vous cliquez ensuite sur "Main Camera" dans la fenêtre "Hierarchy", vous verrez déjà à
quoi cet élément ressemble dans votre jeu.

59
Vous aurez besoin d'ajouter d'autres composants pour rendre votre boîte solide.

Sélectionnez "navbar" dans "Hierarchy" et cliquez sur "Add Component" dans la fenêtre
"Inspector" puis sur "Physics 2D" et enfin sur "Box Collider 2D".

60
Refaites l'opération une seconde fois. Cela évitera au robot de tomber
accidentellement de la barre de navigation dès le début du jeu.

J'ai voulu que notre robot commence le jeu là où il se trouve sur la page du site des
Instructables et c'est pour cette raison que j'ai diminué un peu la taille de la Box
Collider 2D. Comme la seconde Box Collider 2D est en fait dans un espace ouvert,
cela avertira notre robot qu'il faut aller vers la droite lorsque le jeu commence.
Dans l'onglet "Transform", pour le "Scale", indiquez 1,5 pour X et Y. Voyez les
changements que cela produit sur la barre de navigation.
Maintenant que nous avons une plateforme sur laquelle notre personnage peut se
tenir debout, nous avon/s besoin d'un personnage.
Cliquez sur "GameObject" dans la barre de menus supérieurs et sélectionnez "Create
empty".

61
Faites un clic-droit sur votre nouveau "GameObject" puis cliquez sur "Rename" pour changer
son nom en "Player".

Dans la fenêtre "Inspector", cliquez sur "Add component">"Rendering">"Sprite Renderer


Component".

62
Dans Project>Assets>Sprites, trouvez le "Idle_Sprite, cliquez sur le petit triangle et déposez
une des images dans le "Sprite value" du "Sprite Renderer Component".

Nous avons encore besoin d'ajouter des éléments pour étoffer notre personnage. Cliquez
"Add component">"Physics2D">"Rigidbody2D".

63
Si vous cliquez alors sur le bouton "Play", notre joueur tombera de la barre de navigation.
Essayez !

Nous allons ajouter quelques éléments pour le consolider : un élément circulaire à ses pieds
et son corps tout entier et un élément en forme de boîte à sa tête.

64
A présent, si vous cliquez sur "Play", le robot roulera et tombera sur le côté. Vous pouvez le
régler en cliquant sur "Edit Collider". Maintenant, le joueur tombe sur la barre de navigation et
il y reste.
Je le trouve un peu gros à mon goût donc je change sa taille de la façon suivante : dans
"Transform", j'indique 0,75 pour X et Y.

Ensuite, je peaufine la position de la barre de navigation et du robot jusqu'à ce que cela me


convienne.
Sauvegardez votre travail en lui donnant le nom que vous souhaitez.

Maintenant que nous avons un personnage pour jouer, nous allons lui permettre de faire
quelques actions en créant des animations.

Sélectionnez le joueur et ajoutez un "Animator Component


"(Component>Miscellaneous>Animator). Décochez "Apply Root Motion" et pour "Update
Mode", choisissez "Animate Physics".

65
66
Ouvrez ensuite la fenêtre "Animator". Pour plus de confort, j'ai mis cette fenêtre à côté de
"Project".

Toujours avec "Player" sélectionné dans "Hierarchy", ouvrez la fenêtre "Animation".

Dans la fenêtre "Animation", cliquez sur les deux petits triangles dont les bases se font face
puis sur "Create New Clip". Nommez-le "Idle".

67
Juste en-dessous, ouvrez le dossier "Sprites". Prenez l'ensemble des "Idle_sprite" et déposez-
les dans la fenêtre "Animation".

68
Pour le "Sample", indiquez 10.

Jetez un coup d'œil à votre fenêtre "Animator". Vous avez normalement deux états : l'un "Any
state" et l'autre "Idle". Sa couleur orange indique qu'il s'agit d'un état dont les paramètres sont
des paramètres par défaut.

Normalement si vous avez suivi ces étapes correctement, votre robot doit s'animer si vous
pressez "Play".

69
Créez une autre animation que vous appellerez "Drive". Glissez-déposez la feuille
"Drive_sheet". Pour "Sample", indiquez 20. Vous pourrez modifier ce paramètre plus tard si
vous le souhaitez.

Vous verrez dans la fenêtre un autre état appelé "Drive". Cliquez sur la croix dans l'onglet
"Parameters" (en bas à gauche) et sélectionnez "Float". Nommez ce paramètre "Speed".

70
Faites un clic-droit sur l'état "Idle" et sélectionnez "Make Transition".

Pointez votre flèche sur

71
"Drive".

Double-cliquez sur la flèche. Dans la fenêtre "Inspector", pour "Conditions", sélectionnez


"Speed" et indiquez 0,01 en valeur.

Désormais, nous devons faire un script pour contrôler le robot.

Etape 6 : Le script pour contrôler le robot


Maintenant que nous avons un personnage pour jouer, nous avons besoin d'un script pour le
contrôler. Pour cela, nous allons donc ajouter un script en C# très
72
simple.

Dans la fenêtre "Project", créez un nouveau dossier et appelez-le "Scripts".

Ouvrez ce dossier pour y créer un nouveau script en C# et appelez-le "RobotController".

Double-cliquez sur le script pour lancer MonoDevelop.

73
Cela peut prendre un peu de temps pour qu'il s'ouvre donc soyez patient.
Copiez-collez le code suivant pour commencer :
using UnityEngine; using System.Collections;
public class RobotController : MonoBehaviour { //This will be our maximum speed as
we will always be multiplying by 1 public float maxSpeed = 2f; //a boolean value
to represent whether we are facing left or not bool facingLeft = true; //a value
to represent our Animator Animator anim; // Use this for initialization void Start
() {
//set anim to our animator
anim = GetComponent<Animator>();
}
// Update is called once per frame void FixedUpdate () {
float move = Input.GetAxis ("Horizontal");//Gives us of one if we are moving via
the arrow keys
//move our Players rigidbody
rigidbody2D.velocity = new Vector3 (move * maxSpeed, rigidbody2D.velocity.y);
//set our speed
anim.SetFloat ("Speed",Mathf.Abs (move));
//if we are moving left but not facing left flip, and vice versa
if (move < 0 && !facingLeft) {

Flip ();
} else if (move > 0 && facingLeft) {
Flip ();
}
}
//flip if needed void Flip(){

74
facingLeft = !facingLeft;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
} }

Sauvegardez le script et retournez dans Unity. Déposez ce nouveau script dans "Player" dans
la fenêtre "Hierarchy".

75
Cliquez sur le bouton "Play". Vous pouvez à présent contrôler le robot avec les flèches de
gauche et de droite de votre pavé numérique. Si vous ouvrez la fenêtre "Animator", vous le
verrez changer d'état (de "idle" à "drive") selon qu'il bouge ou non.

Nous allons donner à notre personnage la capacité de sauter. Nous aurons besoin pour cela
d'un état d'animation pour sauter et tomber et quelques lignes de code en plus pour mieux
contrôler ses mouvements.

Commençons par ajouter deux autres paramètres à notre "Player Animator". Ajoutez un
"Float" que vous appellerez "vSpeed" et un "Bool" que vous appellerez "Ground". Nous
utiliserons vSpeed pour contrôler la vitesse verticale et "Ground" permettra de détecter quand
le personnage a touché le sol. Il réalisera ainsi des sauts plus réalistes car sauter sans
toucher le sol c'est en fait voler.
Dans la fenêtre "Scene", créez un nouveau "Game Object".

Nommez-le "groundcheck" et ajoutez-lui un "2D Circle Collider".

76
Glissez-déposez le nouveau "Collider" dans "Player" (fenêtre "Hierarchy").

Dans le radius du groundcheck collider indiquez 0,1 en valeur. Cela doit changer la position
en -1. Vous devez voir apparaître un petit cercle autour des pieds de votre robot. Indiquez
ensuite pour "Tag" et "Layer" la mention "Player".

77
Ajoutez ces lignes de code à notre script afin que le robot saute lorsque vous appuierez sur la
touche "Espace".

Copiez-collez toutes ces lignes de code dans le script "RobotController".

using UnityEngine; using System.Collections;


public class RobotController : MonoBehaviour { //This will be our maximum speed as
we will always be multiplying by 1 public float maxSpeed = 2f; //a boolean value
to represent whether we are facing left or not bool facingLeft = true; //a value
to represent our Animator Animator anim;
//to check ground and to have a jumpforce we can change in the editor
bool grounded = false; public Transform groundCheck; float groundRadius = 0.2f;
public LayerMask whatIsGround; public float jumpForce = 700f;
// Use this for initialization void Start () { //set anim to our animator anim =
GetComponent <Animator>();
}

void FixedUpdate () {
//set our vSpeed
anim.SetFloat ("vSpeed", rigidbody2D.velocity.y);
//set our grounded bool
grounded = Physics2D.OverlapCircle (groundCheck.position, groundRadius,
whatIsGround); //set ground in our Animator to match grounded anim.SetBool
("Ground", grounded);

float move = Input.GetAxis ("Horizontal");//Gives us of one if we are moving via


the arrow keys //move our Players rigidbody rigidbody2D.velocity = new Vector3
(move * maxSpeed, rigidbody2D.velocity.y); //set our speed anim.SetFloat
78
("Speed",Mathf.Abs (move)); //if we are moving left but not facing left flip, and
vice versa if (move < 0 && !facingLeft) {
Flip (); } else if (move > 0 && facingLeft) { Flip (); } }
void Update(){
//if we are on the ground and the space bar was pressed, change our
ground state and add an upward force
if(grounded && Input.GetKeyDown (KeyCode.Space)){ anim.SetBool("Ground",false);
rigidbody2D.AddForce (new Vector2(0,jumpForce)); }

}
//flip if needed void Flip(){ facingLeft = !facingLeft; Vector3 theScale =
transform.localScale; theScale.x *= -1; transform.localScale = theScale; } }

Pour régler le paramètre "Ground Check", cliquez sur le cercle qui a un point au centre et
sélectionnez "groundcheck" dans la fenêtre qui apparaîtra. Fermez ensuite cette fenêtre.

79
Pour le paramètre "What Is Ground", cliquez pour vérifier que "Player" n'est pas
sélectionné.

Créons un "blend tree" pour avoir nos différents états (tomber et sauter). Nous devons réaliser
deux animations différentes car cela sera plus efficace et requière moins de mémoire pour
notre petit jeu.
Retournez dans la fenêtre "Animation" avec "Player" sélectionné et créez cinq nouvelles
animations que vous appellerez "jump1", "jump2", etc.

80
Dans "Project", ouvrez le dossier "Sprites". Pour chaque "jump", glissez-déposez le modèle de
la série "jumpsheet" en faisant attention de déposer le premier dans "jump1", le second dans
"jump2", etc.

Ouvrez à nouveau la fenêtre "Animator", faites un clic-droit et sélectionnez "Create


State">"From new blend tree". Appelez-le "JumpFall".

81
Double-cliquez dessus pour l'ouvrir dans la fenêtre "Inspector".

Cliquez sur le signe + en-dessous de "List is Empty" et cliquez sur "Add Motion Field".
Répétez l'opération cinq fois.

Pour "Parameter", sélectionnez "vSpeed". Modifiez "Threshold" en indiquant -13 pour le


premier et 10 pour le second. Renommez toutes les cases "Motion" : jump1, jump2, etc.

82
Si vous n'êtes pas satisfait de l'animation, vous pouvez apporter une petite modification en
décochant "Automate Threshold".

83
Retournez dans la fenêtre "Animator", vous verrez le "blend tree" ouvert. Cliquez sur "Base
Layer" dans le coin supérieur gauche pour retrouver toutes vos animations.
Vous devez alors supprimer tous les états "jump" qui ont été générés automatiquement.

Créez une transition entre "Any state" et "JumpFall", puis entre "JumpFall" et "Idle".

Cliquez sur la transition entre "Any state" et "JumpFall" et dans "Conditions", sélectionnez
"Ground" et "false".

84
Cliquez sur la transition entre "JumpFall" et "Idle" et dans "Conditions", sélectionnez "Ground"
et "true".

Cliquez à nouveau sur "Play" et vous verrez que vous pouvez faire faire un saut au robot.
Problèmes avec les animations !
Dans cette étape, nous allons créer des objets qui vont donner naissance à d'autres objets
dont il faudra se débarrasser si l'on ne veut pas que notre jeu soit alourdi.
85
Commencez par créer un rectangle. Cliquez sur "GameObject">"3D Object">"Quad".

Dans "Transform", pour "Position", inscrivez -25 pour X et 0 pour Y. Pour "Scale", indiquez 1
pour X et 25 pour Y.

Nommez-le "Destroyer".

86
Enlevez l'élément "Mesh Collider" et ajoutez une "box collider 2D". Vérifiez que "Is Trigger" est
coché.

87
Ajoutez l'élément "Rigidbody 2D" et vérifiez que, dans la fenêtre Inspector, la valeur de la
gravité soit bien 0.

Dans la fenêtre "Project", ouvrez le dossier Scripts et ajoutez un nouveau script en C#.
Appelez-le "Destroyer". Double-cliquez dessus pour ouvrir Monodevelop.

88
Copiez-collez dans Monodevelop les lignes de codes suivantes :
using UnityEngine; using System.Collections;
public class Destroyer : MonoBehaviour {
// Use this for initialization void Start () {
}
void OnTriggerEnter2D(Collider2D other){ //if the object that triggered the event
is tagged player if (other.tag == "Player") {
Debug.Break (); return; } if (other.gameObject.transform.parent) { Destroy
(other.gameObject.transform.parent.gameObject); } else { Destroy
(other.gameObject); } }
}

Glissez-déposez le script "Destroyer" dans l'objet "Destroyer" (fenêtre "Hierarchy"). Ensuite,


faites un clic-droit sur Destroyer dans la fenêtre "Hierarchy" et cliquez sur "Duplicate".

89
Paramétrez le nouveau Destroyer de la façon suivante :

 pour "Position", indiquez x=0 et y=-15


 pour "Scale", indiquez x=50 et y=1

Si vous cliquez sur "Play" et que votre joueur tombe de la barre de navigation, vous verrez
"Player" disparaît de la fenêtre "Hierarchy". Cela arrêtera le jeu et vous ramènera à l'éditeur.

90
Nous réglerons ce problème plus tard.

Pour finir, glissez-déposez les deux "Destroyer" dans "Main Camera".

La main qui dessine la ligne est assez simple à faire.

Dans la fenêtre "Hierarchy", sélectionnez "Main Camera". Dans "Project", ouvrez le dossier
"Sprites" puis glissez-déposez la main sur la scène.

91
Pour "Scale" (dans "Transform"), paramétrez de la façon suivante :

 x=2
 y=2

Créez un nouveau Game Object et appelez-le "Penciltip". Positionnez-le au bout du crayon.

92
Taguez-le en cliquant sur le cube en haut à gauche de la fenêtre "Inspector". Cela servira à le
retrouver plus facile.

Ensuite, glissez-déposez le Penciltip dans la main afin qu'ils soient liés l'un à l'autre et
fonctionnent ainsi ensemble.

93
Un prefab est comme un enregistrement d'objet. Si vous créez un objet dans un préfabriqué,
vous pouvez l'utiliser dans votre jeu. Nous allons en créer beaucoup par la suite.
Commencez par créer un nouveau dossier dans "Assets" et nommez-le
"Prefabs".

94
Ouvrez le dossier, faites un clic-droit et créez un nouveau prefab appelé
"pencilline".

Créez dans la fenêtre "Hierarchy" un nouveau "GameObject".

95
Ouvrez le dossier "Sprites" et glissez-déposez l'élément appelé "pencilline".

Ajoutez-lui un élément "Box Collider 2D" et indiquez pour "Size" les paramètres suivants :

 x=0,03
 y = 0,05

96
Ouvrez le dossier "Prefab" puis glissez-déposez le GameObject dans le fichier "pencilline".
Vous verrez l'icône du fichier changer.

97
Une fois glissé-déposé dans le prefab, vous pouvez supprimer le game object. Nous n'en
aurons plus besoin.

Vous devez ensuite ajouter un nouveau script en C# à notre dossier "Scripts".

Nommez-le "pencilline" et copiez-y les lignes de code suivantes :


using UnityEngine; using System.Collections;
public class pencilline : MonoBehaviour {
98
//to refer to our prefab pencilline public GameObject obj;
float lastx = 0f; // Use this for initialization void Start () {
}
// Update is called once per frame void Update () {
//if we have moved far enough make a new pencilline
if (transform.position.x > (lastx+0.02f)) {

Instantiate (obj,transform.position,Quaternion.identity); lastx = transform.position.x;


lastx = transform.position.x;
}
}}
Glissez-déposez ce script dans
"penciltip".

Sélectionnez ensuite "penciltip", ouvrez le dossier "Prefabs" puis glissez-déposez le prefab


"pencilline" dans le paramètre "Obj".

99
Notre caméra n'a toujours pas de script mais si vous cliquez sur "Play", vous verrez un point
blanc au bout du
crayon.

100
La caméra est déjà créée et nous avons juste besoin d'un script pour la contrôler.
Juste avant d'écrire ce script, nous aurons besoin de changer la couleur du fonds qui doit être
blanche car sinon nous ne verrons pas la ligne que nous avons créée à l'étape précédente.

Sélectionnez Main Camera dans la fenêtre "Hierarchy" et dans la fenêtre "Inspector", cliquez
sur l'échantillon de couleur face à "Background". Sélectionnez le blanc dans la fenêtre qui
vient d'apparaître.

101
Ouvrez le dossier "Scripts". Créez un nouveau fichier C# et nommez-le "pancam". Ouvrez
Monodevelop et copiez-collez les lignes de code suivantes :
using UnityEngine; using System.Collections;
public class pancam : MonoBehaviour {
float ydir = 0f; public GameObject player;
// Use this for initialization
// Update is called once per frame void Update () { //check that player
exists and then proceed. otherwise we get an error when player dies if
(player) { //if player has passed the x position of -1 then start moving
camera forward with a randomish Y position if (player.transform.position.x >
-1) {

float randy = 0f; randy = Random.Range (0f, 100f); if (randy < 20) { ydir =
ydir + .005f; } else if (randy > 20 && randy < 40) { ydir = ydir - .005f; }
else if (randy > 80) { ydir = 0f; } transform.position = new Vector3
(transform.position.x + 0.03f, transform.position.y + ydir, -10); } } } }

Glissez-déposez ce script dans "Main Camera" (dans la fenêtre "Hierarchy") puis glissez-
déposer le Player de la fenêtre "Hierarchy" dans "Player" du script "Pancam".

102
Si vous cliquez à nouveau sur "Play", vous verrez que la caméra avance de manière continue.

103
La main est un petit peu trop haute à mon goût. J'ai juste besoin de l'abaisser un peu dans la
fenêtre "Scene".

Cliquez sur GameObject >UI>Text. Nommez ce nouvel élément "Score".

Tapez dans la case "Text", "Score" et sélectionnez la couleur noire.

104
Paramétrez la position de ce mot comme vous le désirez, par exemple, en mettant dans "Rect
Transform" 0,03 pour Pos X et 0,97 pour Pos Y.

Nous avons maintenant besoin d'ajouter un peu de code au script de notre caméra. Copiez-
collez les lignes suivantes dans le code :
using UnityEngine; using System.Collections;
public class pancam : MonoBehaviour {
float ydir = 0f; public GameObject player; //for our GUIText object and our
score public GUIElement gui; float playerScore = 0;

105
//this function updates our guitext object void OnGUI(){ gui.guiText.text =
"Score: " + ((int)(playerScore * 10)).ToString (); } //this is generic
function we can call to increase the score by an amount public void
increaseScore(int amount){ playerScore += amount; }
// Update is called once per frame void Update () { //check that player
exists and then proceed. otherwise we get an error when player dies if
(player) {
//if player has passed the x position of -1 then start moving camera forward
with a randomish Y position if (player.transform.position.x > -1) {
//update our score every tick of the clock playerScore += Time.deltaTime;
float randy = 0f; randy = Random.Range (0f, 100f); if (randy < 20) { ydir =
ydir + .005f; } else if (randy > 20 && randy < 40) { ydir = ydir - .005f; }
else if (randy > 80) { ydir = 0f; } transform.position = new Vector3
(transform.position.x + 0.03f, transform.position.y + ydir, -10); } } } }

Enregistrez et retournez dans Unity.


Sélectionnez Main Camera et vous verrez qu'un nouvel élément est apparu dans Pancam.
Glissez-déposez le score dans Gui.

Cliquez à nouveau sur "Play" et vous verrez que le score augmente à mesure que le
personnage se déplace.

106
Pas de réel danger pour notre héros jusqu'à présent mais nous allons y remédier. Faisons
quelques bombes, comme celles que l'on voit dans les dessins animés qui tombent du ciel et
brisent la ligne.
Créez un nouveau Game Object que vous appellerez "Bomb".

Ouvrez le dossier "Sprites" et ajoutez à Bomb l'élément "Bomb_0". Dans "Transform",


indiquez les valeurs suivantes pour "Scale" :

 x=0,5
107
 y=0,5

Ajoutez un Circle Collider 2D et paramétrez la bombe comme vous le souhaitez. Pour qu'elle
tombe, nous avons besoin d'ajouter un Rigidbody 2D.

108
Nous avons aussi besoin d'un Animator pour contrôler l'explosion de la bombe. Dans la
fenêtre "Inspector", décochez la case "Apply Root Motion" et pour "Update Mode",
sélectionnez "Animate Physics".

109
Ouvrez la fenêtre "Animation" et assurez-vous que Bomb_0 est toujours sélectionné. Ajoutez
une nouvelle animation et nommez-la "bombidle".

Cela créera dans la fenêtre "Animator" une nouvelle animation dont les paramètres sont les

110
paramètres par défaut.

Glissez-déposez les trois premières bombes de la feuille "bomb" (Project>Assets>Sprites).


Dans la case "sample" (en haut à gauche, à côté de "bombidle", indiquez 20.

111
Créez une nouvelle animation que vous appellerez "bombexplode". Glissez-déposez le reste
des bombes et réduisez le "Sample" à 20.

Dans la fenêtre "Animator", créez une transition de bombidle à bombexplode.

112
Dans "Conditions", indiquez 5.00 en valeur pour "Exit Time". Cela signifie que vous avez 5
secondes avant que la bombe n'explose.

Créez une troisième animation dans la fenêtre "Animation" que vous appellerez "bombdead".
Laissez-la vide. Dans la fenêtre "Animator", créez une transition de "bombexplode" à
"bombdead".

113
Dans votre dossier "Scripts", créez un nouveau fichier C# que vous nommerez "bomb" et
copiez-collez dans les lignes de code suivantes :
using UnityEngine; using System.Collections;
public class bomb : MonoBehaviour { //a holder for our Animator Animator
anim; //a public float for the explosion radius public float explodeRadius =
1f;
// Use this for initialization void Start () { anim = GetComponent
<Animator>(); }
// Update is called once per frame void Update () { //if we are done
exploding if (anim.GetCurrentAnimatorStateInfo (0).IsName ("bombdead")) {
//destroy all the objects in a radius unless they are tagged Player or hand
Collider2D[] colliders = Physics2D.OverlapCircleAll
(transform.position,explodeRadius); foreach(Collider2D col in colliders){ if
(col.tag != "Player" && col.tag != "hand"){
Destroy(col.collider2D.gameObject);
} } Destroy(this.gameObject);
} } }

114
Enfin, glissez-déposer le script dans bomb_0.

Une dernière chose pour terminer cette étape. J'ai oublié de vous informer de taguer la main
avec "hand". Pour cela, sélectionnez "hand" dans la fenêtre "Hierarchy" et pour "Tag",
sélectionnez "Add Tag".

115
En face de "element_0", inscrivez "hand". Fichier:Step.1420.jpg
Ensuite sélectionnez "hand" pour "Tag". Sélectionnez aussi le tag "hand" pour "penciltip".

116
Si vous cliquez à nouveau sur "Play", la bombe doit tomber, exploser et supprimer la barre de
navigation.

117
1.8. Travaux Pratique

a. Partant de notre jeu de cochon d’inde, faites un jeu en 2D qui aura comme 3
niveau :

- Le premier niveau il y aura beaucoup des nourritures et moins des


adversaires (Chat) et
- Le deuxième niveau il y aura moins de la nourriture et plusieurs
adversaires
- Le troisième niveau il y aura un endroit spécifique pour prendre des
nourritures avec plusieurs adversaires.

b. Créer un jeu de gestion de parc d'attraction pour parler de ce style de jeu et de ses
contraintes. En premier lieu, il faut énormément d'éléments de gameplay (les
attractions, les décors, les files d'attente, les ventes de produits annexes, etc ...)
beaucoup de sprites en perspective, il y a aussi de l'IA, les personnes qui viennent
dans le parc, qui utilisent les attractions et qui consomment des produits.
L'interface va être un point très important avec tous les menus de gestion et de
construction, de plus la caméra est primordiale dans le confort du gameplay. Tous
ces points sont techniques et certains comme les éléments de gameplay nécessaires sont très
chronophages. Si vous développez seul, je vous déconseille de vous lancer dans une telle
aventure, il y a peu de chance qu'elle aboutisse et même si vous y arrivez ça va être très dur de
tenir la comparaison avec les jeux du même style faits en studio, autant en terme de quantité
d'élément et de fonctionnalité qu'en terme de qualité graphique.

118
CHAPITRE 3 : INTRODUCTION A LA TROSIEME DIMENSION (3D)

Dans ce chapitre, nous essaierons aborder cela sous forme théorique pour
éclairer les apprenants dans le monde de la modélisation à trois dimensions et comment
utiliser les éléments de base d’Unity pour vous donner un élan ‘apprentissage.
3.1. Les concepts de base

Travailler dans le monde de trois dimensions exige de connaitre les éléments


phares que peut vous garantir un excellent apprentissage dans le monde de la
programmation de jeu vidéo.
3.1.1. Les coordonnées
Comme nous venons d’apprendre le 2D, nous avons travaillé que avec de deux
points qui se représente sous forme des coordonnées, entre autre X et Y, mais
Ici nous introduisons la notion d’axe Z qui est probablement familière. L’axe Z
représente la profondeur et s’ajoute aux axes X, pour le plan horizontal, et Y, pour le
plan vertical. Dans les applications 3D, les informations sur les objets sont indiquées
selon un système de coordonnées cartésiennes, autrement dit au format X, Y, Z. Les
dimensions, les valeurs de rotation et les positions dans le monde 3D peuvent toutes tre
décrites de cette façon. Dans ce support, comme dans d’autres documents concernant
la 3D, ces informations sont écrites entre parenthèses, de la manière suivante : (1, 15,
30), (10, 2, 25)
Cette façon explique principalement pour des raisons de clarté, mais aussi parce
que ces valeurs doivent être écrites de cette façon dans le code. Indépendamment de
leur présentation, vous pouvez partir du principe que tout ensemble de trois valeurs
séparées par des virgules est présenté dans l’ordre X, Y, Z.
 Quelques définitions
Par rapport au soleil, la Terre tourne sur elle-même en 24h. La rotation se fait
autour d'une ligne passant par deux points à la surface de la Terre. Ces deux points, qui
sont appelés pôle nord et pôle sud, sont les seuls qui ne sont pas affectés par cette
rotation. Le pôle nord et le pôle sud servent à définir le quadrillage géographique de la
terre. Le grand cercle, dont tous les points sont équidistants des pôles, est l'équateur.
On peut tracer à la surface de la terre une famille de cercles parallèles à
l'équateur : ce sont les parallèles. Pour repérer un parallèle, on utilise la latitude qui est
l'angle formé par l'équateur et le parallèle.

119
Tout demi-cercle passant par les pôles est un méridien. Pour repérer les
méridiens, on choisit une méridienne origine qui le méridien de Greenwich

On utilise les coordonnées pour repérer une position. Nous allons en étudier
deux : les coordonnées géographiques et les coordonnées cartésiennes.

1. Les coordonnées cartésiennes s'expriment en fonction de X, Y et Z. L'origine est le


centre de masse de la terre. La surface X-Y est le plan équatorial moyen et l'axe Z
est l'axe de rotation de la terre.

2. Les coordonnées géographiques s'expriment en fonction de la longitude et de la


latitude. La lettre grecque (lambda) désignant la longitude , la lettre
grecque (phi) la latitude.

120
3.1.2. Les vecteurs

Un vecteur est représenté par un segment orienté (une flèche), ayant pour
extrémités un point de départ et un point d'arrivée. L’emplacement dans le plan ou
l'espace n’a pas d’importance, deux déplacements de deux points d'origine distincts
peuvent correspondre au même vecteur, seuls comptent sa longueur, sa direction et son
sens. Il est donc possible de le faire glisser librement dans le plan, parallèlement à lui-
même. Si A et B sont deux points distincts, le vecteur AB possède trois éléments
caractéristiques :

 sa direction (droite (AB)) ;


 son sens (il y a deux sens possibles de parcours de la droite (AB) : de A vers B ou
de B vers A) ;
 sa norme (ou sa longueur, la longueur du segment [AB]).
Attention cependant à ne pas confondre sens et direction. En effet, dans le
langage courant, lorsqu'on se trouve sur une route entre Paris et Versailles et que l'on
dit que l'on va dans la direction de Versailles, on se rapproche de cette dernière ville.
Mais dans le langage mathématique, la direction est portée par la route (direction Paris-
Versailles) sans savoir si l'on va de Versailles vers Paris ou de Paris vers Versailles.
Pour savoir vers quelle ville on se dirige, il faudra aussi donner le sens : le sens Paris-
Versailles par exemple pour indiquer que l'on va de Paris vers Versailles.
Une définition formelle utilise au préalable la notion de bipoint. Il est défini
comme un couple de points. L’ordre a une importance : le premier point est
appelé origine. Deux bipoints (A, B) et (C, D) sont dits équipollents lorsque les
segments [AD] et [BC] ont le même milieu. La relation d'équipollence constitue
une relation d'équivalence sur les bipoints. Une classe d'équivalence contient tous les
bipoints dont le deuxième membre est l'image du premier point par le déplacement.

121
Si l’on a choisi une unité de longueur dans le plan, un vecteur est caractérisé
par :

Exemple :

 La direction de est la droite (AB).


 Le sens de est de A vers B.
 La norme de est la longueur AB.

Au tout début du 20è siècle, voici comment le Nouveau Larousse illustré


(Dictionnaire Encyclopédique Universel, sous la direction de Claude Augé, 7 volumes)
définit un vecteur : On appelle vecteur une droite AB ayant une direction, un sens et une
grandeur (celle de la longueur AB, essentiellement positive). Les points A et B se nomment
respectivement l'origine et l'extrémité du vecteur AB. Deux vecteurs sont égaux lorsqu'ils
possèdent une direction, un sens et une grandeur identiques, quelles que soient du reste leurs
positions dans l'espace. On n'altère donc pas un vecteur en le transportant parallèlement à lui-
même; aussi, pour désigner un vecteur de position déterminée on se sert souvent du mot segment.

 Egalité de vecteurs

Deux vecteurs sont égaux s’ils ont la même direction, le même sens et la
même norme ou longueur.

Exemple :

Les vecteurs et ont le même sens.


= si :

 (AB) // (CD)
 AB = CD

Théorème : Soient A, B, C, D quatre points du plan. A et B étant


distincts. Les deux vecteurs et sont égaux si et seulement si ABDC est un
parallélogramme.
122
Remarque 1 :

Explication du "si et seulement si"

 Si, alors ABDC est un parallélogramme.


 Si ABDC est un parallélogramme, alors.

Remarque 2 :

 si et seulement si [AD] et [BC] ont le même milieu.


 Soit un vecteur. Il y a une infinité de représentant du vecteur (autant que de
points dans le plan)
 Soit un vecteur et M un point du plan

 Construction de la somme de vecteurs

Si et sont deux vecteurs donnés, pour construire la somme :

o On trace le vecteur à partir d’une origine O, ce qui nous donne


le vecteur .
o En O’, on trace le vecteur , ce qui nous donne le vecteur et la
somme des vecteurs et est le vecteur .

Exemple : Construire où , et O sont donnés ci-dessous.

Règle du parallélogramme n°1.

= équivaut à : « ABDC est un parallélogramme ».

123
Règle du parallélogramme n°2.

Si et alors où R est le point défini de sorte que OMRN est un


parallélogramme.

Pour construire la somme des vecteurs et , on construit le quatrième sommet du


parallélogramme OMRN.

Règle du parallélogramme n°3.

Les points A, B et C étant donnés, si ABCD est un parallélogramme alors :

Relation de Chasles.

Les points A et C étant donnés, pour tout point B, on a la relation :

Ce qui est important pour cette relation de Chasles, c’est que le deuxième point du
premier vecteur (ici B) soit le même que le premier point du second vecteur.

124
Translation.

Le point M’ est l’image du point M dans la translation de vecteur signifie que


. (ABM’M est donc un parallélogramme.)

L’image d’une droite (d) par une translation est une droite (d’) qui est parallèle à (d).

Norme d'un vecteur

La norme du vecteur est la longueur AB. On la note et on lit "norme du vecteur AB" Un
vecteur unitaire est un vecteur de norme égale à 1.

3.1.3. Notion sur le vecteur en modélisation tri dimensionnelle

À l'origine, un vecteur est un objet de la géométrie euclidienne. À deux points,


Euclide associe leur distance. Or, un couple de points porte une charge d'information
plus grande : ils définissent aussi une direction et un sens. Le vecteur synthétise
ces informations.

La notion de vecteur peut être définie en dimension deux (le plan) ou trois
(l'espace euclidien usuel). Elle se généralise à des espaces de dimension quelconque.
Cette notion, devenue abstraite et introduite par un système d'axiomes, est le
fondement de la branche des mathématiques appelée algèbre linéaire. Le vecteur
permet, en physique, de modéliser des grandeurs qui ne peuvent être complètement
définies par un nombre ou une fonction numérique seuls. Par exemple, pour préciser
un déplacement, une vitesse, une force ou un champ électrique, la direction et le
sens sont indispensables. Les vecteurs s'opposent aux grandeurs scalaires décrites par
un simple nombre, comme la masse, la température, etc.

Par exemple, les trois vecteurs de la figure ci-dessous sont égaux, même s'ils ont
des points initiaux et terminaux différents. Ces trois flèches représentent donc le
même vecteur. Un vecteur n'a pas de « point d'attache ».

125
 Le vecteur qui a une longueur de 0 est appelé vecteur nul et est noté ⃗𝟎.
 Le vecteur nul n'a évidemment pas de direction, donc pas de sens.

Les trois vecteurs ci-contre sont les représentants d'un même vecteur car ils ont même
sens, même direction et même norme. On peut donc désigner ce vecteur par un nom
unique, par exemple :

 Les quatre propriétés de d'addition


⃗ et 𝒘
a. L'addition de vecteurs est commutative. Cela signifie que, si 𝒗 ⃗⃗⃗ sont
des vecteurs, alors

⃗⃗ , 𝒗
b. L'addition de vecteurs est aussi associative. Cela veut dire que, si 𝒖 ⃗ et
⃗⃗⃗ sont des vecteurs, alors
𝒘

c. L'addition a un élément neutre : le vecteur nul. En effet :

⃗ est un vecteur, alors −𝒗


d. Enfin, si 𝒗 ⃗ est le vecteur ayant la même direction
et la même intensité que 𝒗⃗ , mais de sens opposé. Donc

126
⃗ −𝒘
La différence 𝒗 ⃗⃗⃗ de deux vecteurs est définie comme

Représentation des vecteurs dans le plan

On utilise un système de coordonnées rectangulaires pour représenter les vecteurs dans


le plan. Appelons 𝒊 un vecteur de longueur 1 dont la direction est celle de l'axe Ox et 𝒋
un vecteur de longueur 1 dont la direction est celle de l'axe Oy.

Il est tout à fait possible de prendre deux autres vecteurs pour former une base, pourvu
qu'ils ne soient pas multiples. Il est à noter que l'ordre des vecteurs a de l'importance.

En deux dimensions, les deux vecteurs 𝒊 et 𝒋 forment ce que l'on appelle la base
canonique. Elle est orthonormée : les deux vecteurs sont orthogonaux et ont une
longueur de 1.

⃗ est un vecteur ayant son point initial à l'origine O et son point terminal en P(a,b),
Si 𝒗
⃗ comme combinaison des vecteurs 𝒊 et 𝒋:
alors on peut représenter 𝒗

127
⃗ dans la base ( 𝒊 ; 𝒋 ), a étant
Les scalaires a et b sont appelés les composantes du vecteur 𝒗
la composante dans la direction 𝒊 et b la composante dans la direction 𝒋. En n
dimensions, les vecteurs ont n composantes.

Supposons qu'un vecteur 𝒗⃗ a pour point initial P1(x1; y1) et comme point terminal
P2(x2; y2). On a alors :

3.2. Travaux Pratique

01. ABCD est un parallélogramme et ses diagonales se coupent en O.

02. Soit ABC un triangle quelconque.

128
03. Soit G le centre de gravité d’un quadrilatère quelconque ABCD, c.-à-d. G est l’unique
point vérifiant l’égalité :

0.4. Soit ABCD un parallélogramme. Construire les points M, N, P, Q définis par :

05. coordonnées de vecteurs dans un repère.

129
CHAPITRE 4 : EN ROUTE VERS LA BASE D’UNITY 3D

4.1. Lancer Unity 3D et créer un nouveau projet

Lancer le logiciel Unity 3D. Une fenêtre de dialogue apparaît, vous


demandant de vous connecter avec un compte utilisateur. Vous avez donc deux
options : soit vous vous créez un compte maintenant, soit vous choisissez l’option
« Work offline ». Vous pourrez réaliser ce tutoriel sans problème en choisissant
l’option « Work offline ». Cependant, si plus tard vous souhaitez récupérer des
données de l’asset store Unity 3D (modèles 3D, scripts, etc.), vous aurez besoin
d’un compte (il sera possible de créer et de vous connecter avec un compte plus
tard même si vous choisissez l’option « Work offline » maintenant).
• Créer un nouveau projet Unity 3D en cliquant sur « NEW ». Choisir 3D, ainsi que
le nom et la destination de votre projet. Vous n’avez pas besoin de charger de
packages prédéfinis pour le moment (vous pourrez le faire par la suite ci-besoin).

• Enregistrer la scène courante (extension .unity) en lui donnant un nom (File >
Save Scenes).

Sauvegarder votre travail : projet et scenes.

Unity 3D sauvegarde de façons différentes les informations à propos de votre


projet. Cela veut donc dire que vous devez sauvegarde différemment votre
travail selon les informations que vous avez modifiées :
- La scene correspond à la scène 3D contenant une hiérarchie d’objets
(GameObject) ainsi que leur paramètres (position, etc.). Lors que vous effectuez
une sauvegarde de la scene, le projet est également automatiquement
sauvegardé. Plusieurs scenes peuvent être créées dans un même projet.
- Le projet permet de stocker les informations qui ne sont pas spécifiques aux
scenes, comme par exemple les paramètres du projet, les scripts, les packages
importés, les paramètres de « Build », etc.
4.2. L’éditeur d’Unity 3D

Lorsque vous créez un projet, vous obtenez par défaut dans la scène une caméra
(Main Camera) et une lumière pour éclairer la scène 3D (Directional Light). La
fenêtre de l’éditeur se présente alors de la façon suivante :

130
Cette fenêtre de l’éditeur est composée des éléments suivants :
1. L’éditeur graphique de la scène 3D permettant de manipuler directement des
objets de la scène.
2. L’arborescence de la scène permettant de visualiser la hiérarchie des objets
présents dans la scène.
3. L’inspecteur permettant de voir les différents scripts rattachés à l’objet
sélectionné (par 1 ou 2) et de modifier leurs paramètres.
4. L’explorateur de projet permettant de voir les différents composants du projet
et de les ajouter à la scène par un simple glisser-déposer. Pour l’instant, il y a
seulement la scène dans le projet.
5. Les boutons permettant de lancer l’exécution de la scène 3D dans l’éditeur ce
qui est très utile pour tester et debugger la scène (nous verrons plus tard
comment créer un exécutable pour la scène).
6. La visualisation de la scène 3D à partir du point de vue de la caméra virtuelle.
L’éditeur bascule automatiquement sur cette visualisation lorsque l’exécution
de la scène est lancée.

131
7. La console permettant de voir les messages d’erreurs ou les logs lors de

l’exécution de la scène. Les interactions dans l’éditeur graphique peuvent se

faire à partir des boutons suivants :

4.3. Créer une scène simple

Pour commencer, nous allons créer une application toute simple qui affiche
plusieurs cubes de couleur bleue à des positions différentes :
• Insérer un plan dans la scène pour créer un sol (GameObject > 3D Object >
Plane).
Au moyen de l’inspecteur (3), placer ce plan aux cordonnées (0, 0, 0) et vérifier
qu’il est bien visible par la caméra maintenant. Agrandir ce plan en jouant sur
l’échelle pour qu'il est une longueur et une largeur de 100 mètres et vérifier qu’il
est bien visible à l’infini lorsque l’on prend la vue de la caméra.
• Ajouter un cube dans la scène (GameObject > 3D Object > Cube) et placer le
pour qu’il soit visible par la caméra.

• Créer un material pour donner une couleur au cube (Assets > Create > Material).
Un nouveau composant est créé dans le projet (4), donner lui un nom. Puis
modifier sa couleur dans l’inspecteur pour obtenir le bleu de l’image suivante.
Ensuite glisser-déposer le material à partir de l’explorateur de projet (4) sur le
cube dans l’arborescence de la scène (2). Le cube devrait prendre la couleur bleue
dans l’éditeur graphique (1).

• Ajouter une texture sur le plan : télécharger la texture grid_grey.png sur le site du
cours, aller dans (Assets > Import New Asset…) et choisir la texture. Glisser-
déposer la texture à partir de l’explorateur de projet (4) sur le plan dans
l’arborescence de la scène (2). Puis sélectionner le plan dans l’arborescence de la
scène (2) et modifier les paramètres du material dans l’inspecteur (3) afin
d’obtenir la même texture du sol que dans l’image ci-dessous. Il faudra en
particulier jouer sur le nombre de fois que la texture est répétée (« tiling »).

• Déplacer le cube et la caméra afin d’obtenir une image similaire lorsque vous
exécutez la scène :

132
• Ajouter un comportement physique au cube : sélectionner le cube et lui ajouter
un Rigidbody (Component > Physics > Rigidbody). Observer ce qui se passe
lorsque vous exécutez la scène.

• Glisser-déposer le cube depuis l’arborescence de


la scène (2) vers l’explorateur de projet (4) : cela
va créer un « Prefab » à partir du cube (cf. icône
bleue) qui vous devrez renommer (CubePrefab
par exemple). Puis, par l’opération inverse,
insérer 11 autres cubes à partir de ce modèle dans
la scène et déplacer les instances de ce cube afin
d’obtenir la même disposition que dans l’image
de droite.

• Exécuter la scène.

• Sélectionner le CubePrefab dans l’explorateur de projet (4) et modifier les


paramètres de son Rigidbody afin de changer son comportement physique (en
particulier, la masse « Mass » et la friction « Drag »). Exécuter la scène avec plusieurs
paramètres différents.

4.4. Animer un objet de la scène

Des scripts en C# ou Javascript permettent de donner un comportement aux


objects. Nous préférons les scripts en C# car ce langage est plus proche du Java que
vous connaissez probablement mieux (typage, etc.). Nous allons donc créer un
nouveau script C# permettant de faire tourner les cubes que nous avons crées :
• Créer un nouveau script (Assets > Create > C# Script) que vous nommerez
RotateCube.
• L’éditer en double cliquant dessus (par défaut, il sera ouvert avec Mono).

133
• La fonction Update(), qui est héritée de la classe MonoBehaviour, est appelée à
chaque pas de temps lors de l’exécution de la scène. Dans cette fonction Update(),
effectuer une rotation de 3° selon l’axe vertical (Y). Pour cela, vous pourrez
accéder à la position de l’objet auquel le script sera associé au travers de l’attribut
transform (déjà défini dans la classe mère MonoBehaviour). Vous pourrez utiliser
l’auto-complétion de Mono pour voir les fonctions que l’on peut appliquer à cet
attribut transform et trouver la fonction qui permette d’effectuer la bonne
rotation.

• Ajouter le script au CubePrefab par glisser-déposer sur l’icône du prefab dans


l’explorateur de projet (4). Noter l’apparition du script en tant que composant
dans l’inspecteur (3) : on peut le désactiver ou le supprimer. Noter également
que toutes les instances de CubePrefab ont été modifiées par cet ajout.

• Exécuter la scène.

• Pour une plus généricité du script, ajouter un attribut public dans la classe
RotateCube avant la fonction Start() : public float speed = 3.0f;

• Modifier le script en conséquence.

• Vous remarquerez l’apparition de cet attribut dans l’inspecteur (3), ce qui permet
de modifier la valeur de la vitesse de rotation sans éditer le script à chaque fois.
Noter que la valeur 3.0f est la valeur par défaut lorsque l’on ajoute le script à un
nouvel objet.

• Tester avec différentes valeurs.

4.5. Gestion des interactions

Unity 3D permet de capter les entrées de base comme les appuies sur les touches
du clavier ou les actions de la souris. Cependant, afin de permettre une plus grand
généricité et de ne pas coder en dur toutes les commandes dans les scripts, Unity
3D propose un système de gestionnaire d’Input.

Nous voulons donc maintenant modifier le script qui fait tourner les cubes pour
que l’on puisse activer et désactiver la rotation. Par défaut, la rotation sera
désactivée. Lorsque l’utilisateur appuiera sur la touche « r » (et la relâchera ensuite),
les cubes se mettront à tourner. Puis lorsqu’il appuiera à nouveau sur la touche « r
» (et la relâchera ensuite), les cubes s’arrêteront de tourner, et ainsi de suite : dès

134
que la touche « r » est appuyée, les cubes changeront leur comportement. Pour cela
:
• Aller dans le menu (Edit > Project Setting > Input), ajouter un nouvel axe en
modifiant la taille Size. Changer son nom en « ActivateRotation » par exemple et
définir le Positive Button comme la touche « r ».

• Pour récupérer l’événement « ActivateRotation » dans votre script, vous pourrez


utiliser les fonctions suivantes qui retournent des booléens (cf. documentation
avec l’auto-complétion de Mono) : -Input.GetButton("ActivateRotation")
-Input.GetButtonDown("ActivateRotation")
-Input.GetButtonUp("ActivateRotation")

• Pour vérifier le bon fonctionnement de votre script, vous pouvez afficher dans la
console de l’éditeur (7) un message chaque fois que la touche « r » est appuyée.
Pour cela, vous pourrez utiliser la syntaxe suivante : Debug.Log ("votre message");

4.6. Programmation d’interaction simple avec la souris

Nous souhaitons créer un nouveau script permettant de pousser les cubes lorsque
l’on clique dessus et de changer la couleur du cube change lorsque l’on passe la
souris sur ce cube. Pour cela, nous allons utiliser les fonctions OnMouse… de la
classe mère MonoBehaviour :
-void OnMouseDown ()
-void OnMouseDrag ()
-void OnMouseEnter ()
-void OnMouseExit ()
-void OnMouseOver ()
-void OnMouseUp ()

• Créer un nouveau script C# que vous nommerez MouseInteraction.

• Créer deux attributs privés de type Rigidbody et Renderer afin de pouvoir stocker
des liens vers le RigidBody (pour la physique) et le Renderer de l’objet (pour
pouvoir accéder au material et changer la couleur).

• Dans la fonction Start(), initialiser vos deux attributs en utilisant les fonctions : 

GetComponent<Rigidbody>() et GetComponent<Renderer>()
• Pour pousser le cube, vous pourrez appliquer une force sur son Rigidbody en
utilisant la fonction AddForce(Vector3D val_dir_force). L’attribut Camera.main
permet d’accéder à la caméra principale et Camera.main.transform.forward

135
donne le vecteur pointant vers l’avant de la caméra. Cependant, il faudra le
multiplier pour obtenir une force suffisante.

• Pour changer la couleur, vous pourrez accéder à l’attribut .material sur le


Renderer et à l’attribut .color sur le material : rend.material.color. Cela devrait
vous permettre à la fois de stocker la couleur initiale de l’objet (pour la remettre
une fois que la souris aura quitté le cube) et de changer cette couleur en utilisant
une couleur prédéfinie comme : Color.red.

6.7. Navigation en ré-utilisant des scripts d’interaction clavier/souris

Unity 3D propose plusieurs composants pour gérer différents types d’interaction de


base. Dans cette partie, nous allons ajouter un composant pour pouvoir naviguer
dans la scène à la façon d’un FPS :
• Importer le package Characters (Assets > Import Package > Characters).

• Ajouter le prefab nommé FPSController dans


l’arborescence de la scène (2). Il possède sa propre
Main Camera : désactiver la Main Camera utilisée
précédemment en décochant la case dans l’inspecteur
(3).

• Modifier la position du FPSController pour avoir une vue à la 1ère personne de


la pile de cubes, en étant posé sur le plan.

• Exécuter la scène, tester les commandes (flèches, barre d’espace, souris) et écouter
aussi le son produit.

4.8. Création dynamique d’objets

Nous voulons maintenant créer dynamiquement des objets dans la scène 3D. Pour
cela, Unity 3D propose une fonction Instantiate(GameObject obj) qui permet
d’instancier dynamiquement dans la scène une copie de l’objet passer en paramètre.
L’objet passé en paramètre peut être un objet déjà présent dans la scène ou bien
un prefab si l’on ne veut pas que l’objet soit déjà dans la scène.

Nous souhaitons faire en sorte que des cubes jaunes soit lancés dans la direction de
la caméra lorsque l’utilisateur appuie sur le bouton droit de la souris :
• Créer un nouveau script C# que vous nommerez CreateOnClick.

• Ajouter ce script au FirstPersonCharacter (l’object qui suit les mouvements de la


souris) qui est le fils du FPSController. C’est aussi lui qui porte la caméra.

136
• Créer un attribut public GameObject aCopier qui vous permettra de stocker une
référence sur l’objet à instancier. Il faudra initialiser cet attribut en faisant un
glisser-déposer du CubePrefab dans le champs de l’attribut dans l’inspecteur (3)
lorsque l’on a sélectionné le FirstPersonCharacter.

• Par défaut dans les Input du projet, le clique droit génère l’événement « Fire2 »
que vous pourrez capter avec les fonctions getButton… comme pour l’évènement
« ActivateRotation ».

• A chaque clique droit :


- Instancier un nouveau cube avec la fonction Instantiate(GameObject obj),
- Changer sa couleur,
- Placer le devant le FirstPersonCharacter, sinon il sera éjecté dans n’importe
quelle direction (collision avec le FirstPersonCharacter), - Appliquer lui une
force pour le lancer en avant.

Noter que l’on peut aussi supprimer des objets de la scène grâce à la fonction
Destroy(GameObject obj).

4.9. Charger une géométrie

Nous souhaitons charger le modèle 3D d’une voiture avec des textures plaquées
dessus :
• Décompresser cette archive. Il contient un .obj décrivant le mesh, un .mtl
décrivant les couleurs et les placements des textures, ainsi que les images de
texture .tga.

• Effectuer un glisser-déposer de tout le dossier contenant les différents fichiers du


modèle dans l’explorateur de projet (4). Le modèle devrait être chargé dans Unity
3D.

• Glisser-déposer le modèle dans l’arborescence de la scène (2) pour l’ajouter à la


scène. Ajuster sa taille pour qu’il soit à la même échelle que les cubes et sa position
pour qu’il se trouve près de la pile de cubes. • Le chargement de nouveaux
modèles 3D souffre souvent de petits problèmes de compatibilité dans toutes les
librairies 3D. Observerer qu’ici, la transparence des vitres de la voiture n’a pas été
conservée. Trouver le material qui correspond aux vitres et changer son
Rendering Mode, ainsi que la composante alpha (A) de la couleur de la Main
Maps afin de rendre les vitres transparentes.

137
• Essayer de lancer des cubes sur la voiture ou de marcher au travers. Qu’observez-
vous ? Pourquoi ?
• Trouver une solution pour régler ce problème. Vous pourrez utiliser des Box
Colliders que vous placerez vous même ou des Mesh Colliders que vous ajouterez
aux parties adéquates de la voiture (cf. images sur la page suivante). La 2nd
solution est plus précise, mais plus couteuse en temps de calcul.

4.10. Créer un exécutable pour la scène

Enfin, nous voulons créer un exécutable pour cette scène afin de pouvoir visualiser
la scène en plein écran et éventuellement de la distribuer :
• Aller dans File > Build Settings…

• Sélectionner la cible PC, Mac & Linux Standalone. Observez qu’il y a d’autres
cibles intéressantes comme par exemple WebGL (cf. l’exécutable de la scène du
tutoriel sur le site du cours).

• Cliquer sur Build.

• Tester votre exécutable.

Vous pouvez ensuite cliquer sur Player Settings… en bas de la fenêtre Build
Settings… et explorer les différents paramètres du player (fenêtre de dialogue au
lancement, resolution, etc.).

138
4.11. TP
1. Concevoir une animation en 3d d’un cochon d’inde en utilisant l’objet Game
Play et remplir que l’objet puisse être dynamique et que sa puisse interagir
avec le clavier et la souris.
2. Ajouter l’animation des ennemies (Chat) ainsi que la nourriture de notre
cochon d’inde.

Conclusion

Unity est une petite révolution : outil de développement 3D et moteur de


jeux, il permet de produire simplement, grâce à une interface d’intégration d’objets
et de scripts très intuitive, des jeux de standard professionnel pour Mac, PC et le
Web. Une version du moteur existant également pour la Wii, l’iPhone et l’Android,
il offre un accès aux consoles et aux mobiles une fois que vous en maîtrisez les bases.

139
Bibliographie

1. Livre
 Développez des jeux 3D avec Unity traduit par Philippe Beaudran, avec la
contribution technique de Nicolas Colliot, responsable développement chez
Yamago
 Tutoriel Complet Unity Défi 3 et 2 par microsoft et magic
 INTRODUCTION TO UNITY, University of Queensland 2016
 3D Game Development with Unity A Case Study: A First-Person Shooter
(FPS) Game
2. Site web
 https://www.supinfo.com/articles/single/6880-creer-simple-jeu-unity-3d-
partie-1
 https://fr.tuto.com/unity/
 https://medium.com/@lycanthrop/d%C3%A9couvrir-les-bases-de-unity-
avec-boris-tome-1-a3a4a24f8b05
 http://math.ens-paris-saclay.fr/version-francaise/formations/master-
mva/contenus-/nuages-de-points-et-modelisation-3d-
219052.kjsp?RH=1242430202531
 https://www.sciencedirect.com/science/article/abs/pii/S1286011505833715

140

Vous aimerez peut-être aussi