Logiciels / Unity 3D

Unity 3D est un logiciel permettant de créer rapidement des jeux, grâce à son système très flexible basé sur les composants. Il est maintenant très répandu dans l'industrie car les jeux peuvent être facilement déployé sur une grande variété de plateformes.

Mes compétences

  • Prototypage rapide d'idées de Game Design.
  • Création de niveaux de jeu: Terrains, objets...
  • Intégration de contenu de tous types.
  • Programmation de composants et de fonctionnalités avancées.
  • Conception et création d'outils d'aide à la production.
  • Enseignement: utilisation de l'éditeur, programmation...
  • Suivi de projets étudiants.

Travail: Boss fight: Teal'c VS Khufu

15.11.2013
Réalisé pour le projet: Stargate:Unleashed2 en 2013 à Arkalis Interactive - Compétence: Game Design
Logiciels: Unity 3D Microsoft Word
Dans le repaire du lion est le dernier chapitre de Stargate SG1 : Unleashed Episode 2. Dans ce niveau le joueur a de nombreuses révélations et finit sur un combat entre Teal'c et Khufu, un grand adversaire. J'étais en charge du design et devais m'accorder au scénario fourni par l'auteur.

Concept

Au départ il m'a été demandé de créer un combat épique mais en évitant d'ajouter des features supplémentaires pour rester dans les temps.

J'ai alors commencé à penser à un combat générique. La meilleure façon semblait d'utiliser les QTE de touch et de glisser et aussi, comme dans cette partie le joueur affronte un boss, je voulais que le joueur ressente le combat.

Donc, j'ai décidé de mettre en place un pattern qu'un boss peut avoir et j'ai ajouté une barre de vie sur les deux personnages pour amener la comparaison et donner plus de tension au joueur. Pour résumer le design, le combat se divise en séquences aléatoires de QTEs avec différentes pondérations. Au début, Teal'c essaiera de frapper son adversaire. S'il réussit, Khufu perd un peu de vie, dans le cas contraire, le boss bloque et essaie de contre-attaquer, donnant une ultime chance au joueur de sauver son personnage.

En bref, s'il est en vie, une autre séquence se joue. Peut-être Khufu attaquera Teal'c et le joueur devra parer au risque de perdre un peu de vie. Dans un autre cas, il pourra peut-être placer plusieurs combos. S'il échoue, Teal'c prend des dégats.

Une deuxième partie

Après, J'ai ajouté une autre partie au combat, comme une évolution du boss. Quand le joueur vide la barre de vie de Khufu, la seconde séquence commence avec Teal'c perdant son arme. Dans ce cas de figure le boss devient plus difficile mais la séquence est cette fois plus proche d'une cinématique montrant un combat plus épique, aidant à faire ressentir plus de tension au joueur.

Design des mouvements

Avec l'aide d'autres collègues nous avons pris quelques photos des mouvements pour donner le plus d'informations possibles aux animateurs. Après avoir défini le contenu, nous avons enregistré des vidéos.

Dans la première phase de combat, le personnage devait passer rapidement d'un mouvement à un autre dans le cas où le joueur réussissait ou non.

Pour la seconde phase, la séquence était plus épique, et devait montrer une victoire parfaite pour récompenser le joueur.

Résumé

Dans le dernier chapitre de Stargate: Unleashed, Teal'c combat Khufu, un adversaire implacable.
Travail: J'ai été en charge du design du combat.


Travail: La sauvegarde

22.04.2010
Réalisé pour le projet: Contre-Jour en 2010 à Supinfogame - Compétence: C#
Logiciels: Unity 3D

En tant que jeu d'aventure, Contre-Jour propose une histoire. Donc, il était nécessaire de pouvoir sauvegarder la progression du joueur. Aussi, le jeu est organisé en petits niveaux reliés par des entrées/sorties. Quand le héros se déplace dans un autre niveau, la progression est sauvegardée dans un fichier binaire.

La sauvegarde concerne différentes informations :

  • Les infos joueur : les pièces collectées, le niveau actuel, l'entrée actuelle dans le niveau... ;
  • Les informations concernant tous les niveaux : les positions des objets interactifs, les pièces et objets récupérés, les portes ouvertes, la position des interrupteurs,... ;
  • Les paramètres sauvegardables du GSE : Pour jouer un évènements une fois seulement...

Pour faire cela, J'ai utilisé un fichier binaire avec une nomenclature adaptée. Ce type de fichiers est organisé de manière séquentiel. Une tête de lecture lit et écrit les informations puis se déplace vers l'avant.

La nomenclature du fichier de sauvegarde

Dans le flux principal

  • Les infos joueur au début ;
  • Le nombre d'octets puis le flux concernant les niveaux.

Dans le flux des niveaux

Le flux contient le nombre total des niveaux et la liste des informations pour chaque niveau : le nombre d'octets et le flux du niveau correspondant.

Dans chaque flux de niveau

Chacun des flux contient le nombre d'objets sauvegardés et une liste séquentielle des informations pour chacun d'eux. Les informations d'un objet sont formées d'un identifiant et d'un flux spécifique (pour une caisse que l'on peut pousser, on conserve la position, par exemple) . Les boîtes du GSE sont gérées comme les autres objets mais on sauvegarde leurs paramètres à la place.

Côté code

A l'origine, j'ai utilisé deux types de fonctions basiques de C#.

Pour sauvegarder
//Créé un fichier ou ouvre le fichier existant et écraser le contenu
BinaryWriter binWriter = new BinaryWriter(File.Open("monfichier.txt",FileMode.Create));
//Ecrit des informations dans le fichier
binWriter.Write("CJSaveGame");//une chaîne: string
binWriter.Write(10);//un entier: int
binWriter.Write(10.5f);//un nombre à virgule flottante: float
binWriter.Write(true);//un booléen: bool
//etc.
binWriter.Close();//ferme le fichier
Pour charger:
if(File.Exists("monfichier.txt")){//Vérifie l'existence du fichier
//Ouvre le fichier
BinaryReader binReader = new BinaryReader(File.Open("monfichier.txt" , FileMode.Open));
try{
if(binReader.PeekChar() != -1)//Si le fichier n'est pas vide
{
//ReadString: lit les octets et déplace la tête de lecture
string str = binReader.ReadString();//une chaîne: string
int integer = binReader.ReadInt32();//un entier: int
float number = binReader.ReadSingle();//un nombre à virgule flottante: float
bool boolean = binReader.ReadBoolean();//un booléen: bool
//etc.
}
}
finally{
binReader.Close();//ferme le fichier
}
}

Résumé

Comme pour tous les jeux vidéo next-gen, Contre-Jour sauvegarde automatiquement la progression du joueur avec des checkpoints (Ici,le changement de niveau). Ainsi, le joueur peut reprendre au niveau en cours si il quitte.
Travail : J'ai programmé les processus de sauvegarde et de chargement.


Travail: GSE : Editeur Scripts Graphique

20.03.2010
Réalisé pour le projet: Contre-Jour en 2010 à Supinfogame - Compétence: C#
Logiciels: Unity 3D

Contre-Jour est avant tout un jeu d'aventure, avec un univers, une histoire, des personnages. Dans le jeu, Charles, le héros, communique souvent avec la reine des lucioles, croise un vigile plutôt patibulaire à plusieurs reprises... Pour mettre en place ces évènements et autres cinématiques, il fallait un outil. J'ai donc créé un éditeur destiné à l'équipe permettant de scripter ces éléments directement sur Unity3D.

L'idée a germé en début de production alors que nos ambitions en terme de scénarisation étaient grandissantes. Inspiré de l'outil disponible sur UDK, le Unreal Kismet, le GSE est une succession de boîtes reliées par des flèches.


Chaque script commence avec une boîte d'évènement (exemple : un personnage entre dans une zone qui déclenche un évènement) . D'autres boîtes sont connectées à elle et effectuent des actions (jouer une animation, émettre un son...) .


Un exemple plus précis


La mise en place

Mettre en place le GSE n'a pas été une décision simple. Il fallait que je vérifie que le temps de développement serait court et m'assurer que l'outil serait fonctionnel et facile à utiliser par toute l'équipe. J'ai donc pris une semaine pour faire un prototype pour quelques boîtes. Les résultats étaient plus qu'encourageants. En quelques jours, je pouvais faire des petites séquences d'actions simples et à l'utilisation, quelques cliquer/déposer permettaient de faire des enchaînements de boîtes.

L'étape suivante a été de communiquer le fonctionnement du GSE à l'ensemble de l'équipe. La plupart des membres du groupe connaissait le Kismet, ce qui m'a grandement facilité la tâche côté logique de l'éditeur. Au fur et à mesure de l'évolution du projet, j'ai ajouté des types de boîtes supplémentaires en fonction des besoins. A terme, nous en avions 65 en tout.

Résultat

Programmer cet éditeur m'a permis d'économiser beaucoup de temps en scripts d'évènements et de cinématiques. Désormais, l'équipe faisait ce travail. En outre, j'ai eu la possibilité de me concentrer sur d'autres features de code.

Résumé

J'ai créé un outil pour ajouter facilement des évènements et des cinématiques on jeu. Cela consiste en un ensemble de boîtes reliées entre elles par des flèches. Chaque type de boîte fait une action particulière (Emettre un son, jouer une animation, afficher des sous-titres...) . Inspiré de Unreal Kismet, l'outil était très utile car étant le seul programmeur du projet, j'aurais eu à intégrer les évènements moi-même sans cela. J'ai pu ainsi me concentrer sur d'autres features de code grâce à cet éditeur et le reste de l'équipe pouvait mettre en place ce qu'ils souhaitaient de manière très précise en jeu.
Travail : Design et code du GSE ; enseignement de son utilisation à l'équipe.


Travail: Le streaming de niveaux

05.02.2010
Réalisé pour le projet: Contre-Jour en 2010 à Supinfogame - Compétence: C#
Logiciels: Unity 3D

Dans Contre-Jour, les niveaux sont courts et le joueur les parcourt rapidement. Pour gagner du temps dans le chargement des scènes, j'ai créer un gestionnaire de streaming des niveaux.

Au lancement du jeu, il charge le niveau courant où le personnage se situe et lance la partie. Ensuite, le niveau est jouable directement mais pendant que l'on joue, le gestionnaire continue à charger les niveaux adjacents. Par exemple, quand le héros est dans la première carte (le point rouge), le deuxième niveau est préchargé.

Si il a fini son chargement quand le joueur termine le premier niveau alors on change de carte sans aucun écran de chargement. Une fois dans ce nouveau décor, le troisième se met en chargement et ainsi de suite. La première carte reste en mémoire parce qu'elle est adjacente. On peut donc revenir sur ses pas sans attente.

Côté code

Le gestionnaire de streaming des niveaux utilise une liste de niveaux. Chaque élément de la liste contient la scène à charger et une liste de booléens.

  • isLoading : Le niveau est-il en cours de chargement ;
  • isDataLoaded : La carte est-elle en mémoire.

[System.Serializable]
public class levelsList{
public string name;//identifiant du niveau
public string description;

[System.NonSerialized]
public bool isLoading = false;//Le niveau est-il en cours de chargement
[System.NonSerialized]
public bool isDataLoaded = false;//Le niveau est-il chargé
}

public class GameManager : MonoBehaviour {
public LevelsListElement[] levelsList;//Liste des niveaux
//...
}

Unity3D dispose d'une fonction simple de chargement de scène en asynchrone.

private IEnumerator streamLevelCoroutine(int level){
if(!levelsList[level].isLoading && !levelsList[level].isDataLoaded){//On lance le chargement que si nécessaire
//LoadLevelAdditiveAsync: Stream le chargement d'une scène.
yield return Application.LoadLevelAdditiveAsync(levelsList[level].name);
levelsList[level].isDataLoaded = true;//Le niveau est chargé et disponible

levelsList[level].isLoading = false;//Chargement terminé
}
}

Résumé

Pour avoir un jeu de qualité, nous avons décidé de diminuer le temps de l'écran de chargement entre les niveaux.
Travail : J'ai programmé un gestionnaire de streaming des niveaux.


Travail: Le rendu Ombre/Lumière

05.10.2009
Réalisé pour le projet: Contre-Jour en 2010 à Supinfogame - Compétence: Game Design
Logiciels: Unity 3D

Contre-Jour joue sur l'ombre et la lumière. Le rendu de l'environnement devait être lisible facilement de manière à savoir en un seul coup d'oeil si l'ombre enchantée de Charles est en sécurité ou non. J'ai proposé un rendu et l'ai testé avec le leader graphiste pendant la préproduction.

La solution était d'avoir une limite franche entre les zones d'ombre sûres et les lumières dangereuses. Chaque partie devait être clairement identifiable et l'affichage de ce rendu devait être possible techniquement avec Unity3D 2.6.

  • Dans la lumière : le rendu est réaliste, avec des textures colorées;
  • Dans l'ombre : la forme de chaque objet a des contours et on peut voir des motifs à l'intérieur. Grâce à eux, on peut déterminer les volumes facilement.

Avec le lead graphiste, nous avons créé les premiers objets utilisant le rendu (la villa dans la vidéo ci-dessous). Nous en avons tiré le pipeline de production pour les assets.



Comment ça marche?

La solution est simple, chaque objet est couvert d'un matériau comprenant deux textures.

  • La texture de base : c'est la première couche du matériau. Cette texture réagit normalement à la lumière.
  • La texture de lightmap : C'est une texture qui simule la lumière. Dans l'obscurité totale, les pixels colorés révèlent la texture de base en dessous.

Résumé

J'ai proposé ce rendu sur l'environnement pour séparer ombre (contour et fond noir) et lumière (textures réalistes).
Travail : Proposition, premiers assets et mise en place du pipeline avec le lead graphiste.

Quelques images

testUnity.png house3dsmax.png
houseUnity.png