"SHIFT" est un jeu Fast Platformer en vue FPS où le joueur incarne un cyborg agile et rapide employé par une entreprise de nettoyage. Son but est de débarrasser des zones des parasites occupant les lieux le plus rapidement possible grâce à son dispositif de téléportation et de tuer le parasite mère.
Genre: Fast FPS / Fast Platformer
Moteur de jeu: Unity
Taille d'équipe: 3
Durée: Février 2024 - Juin 2024
Plateforme: PC (Itch.io prochainement)
Moteur de jeu: Unity
Taille d'équipe: 3
Durée: Février 2024 - Juin 2024
Plateforme: PC (Itch.io prochainement)
Dans le cadre de notre projet semestrielle de deuxième année, nous devions concevoir un jeu avec pour thème l'état critique avec le logiciel de développement unity.
![Conservation de la vitesse de l'avatar](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/49b85b98-b92c-454f-9508-62ece17f9800_rw_1200.png?h=dda0402df1ff7d2b79c0569f95b77c41)
Conservation de la vitesse de l'avatar
Résumé de la mécanique :
Pour se déplacer le joueur peut marcher, s'accroupir, courir, sauter et glisser.
Il dispose d'un téléporteur qu'il peut lancer et sur lequel il peut se téléporter en conservant la vitesse du téléporteur et sa position.
Il dispose de 2 charges de téléportation que l'on peut recharger et tirant sur des cibles parasites.
La mécanique est relativement simple à comprendre et à prendre en main.
Il dispose d'un téléporteur qu'il peut lancer et sur lequel il peut se téléporter en conservant la vitesse du téléporteur et sa position.
Il dispose de 2 charges de téléportation que l'on peut recharger et tirant sur des cibles parasites.
La mécanique est relativement simple à comprendre et à prendre en main.
Rôle et Responsabilité :
Au sein du projet j'ai été principalement en charge de la programmation, j'ai notamment développé les comportements de notre téléporteur au sein de l'environnement, les menus du jeu, une sauvegarde locale des temps du joueur et des rebinds de touches.
J'ai également fait l'UI en jeu en utilisant des placeholders pour préparer le travail de l'UI design, afin qu'il n'ait qu'à remplacer les sprites et quelques outils pour aider le level designer. Ainsi, que l'intégration du travail de chacun et la résolution des divers conflits que cela engendrait
![Vitesse avatar proportionnellement ajoutée](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/7fa54658-0279-4f0c-8183-70b355415aa1_rw_600.png?h=200a5e5bc38895e597b11663410ffce4)
Vitesse avatar proportionnellement ajoutée
Lanceur :
Un des problèmes que nous avons rencontrés avec notre lanceur était que sa vitesse au lancement n'était pas suffisante, ce qui faisait que le téléporteur passait derrière l'avatar du joueur lorsque ce dernier atteignait une certaine vitesse. Augmenter la force de lancé n'était pas possible, car à une vitesse plus faible de l'avatar, le téléporteur aurait été propulsé beaucoup trop rapidement.
Pour résoudre ce problème et donner l'impression que le téléporteur se déplace à une vitesse élevée, même lorsqu'il n'est pas lancé dans la direction du déplacement de l'avatar, j'ai utilisé un produit scalaire. Cela permet d'ajouter une partie de la vitesse du joueur à celle du téléporteur, donnant ainsi une impression de mouvement supplémentaire sans que le téléporteur soit lancé trop fort ni passe derrière le joueur.
On peut voir le fonctionnement actuellement comme lancer une balle d'une voiture en mouvement, la balle va à la vitesse de la voiture additionnée à celle du lancer.
Rebind des inputs :
Notre cible étant porté sur des joueurs Hardcore et ayant un attrait pour le speedrun, il me semblait important pour eux de pouvoirs changer leurs touches selon leur besoin et habitude.
J'ai donc utilisé un sample mis à disposition par Unity que j'ai adapté à nos besoins et en y ajoutant des gestions qui n'étaient pas présentes comme ne pas pouvoir attribuer 2 fois le même input à différentes actions.
J'ai donc utilisé un sample mis à disposition par Unity que j'ai adapté à nos besoins et en y ajoutant des gestions qui n'étaient pas présentes comme ne pas pouvoir attribuer 2 fois le même input à différentes actions.
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/7b91d1b6-8772-40c3-af18-1472ac475d13_rw_1920.png?h=76b911d0be5ed5e9907a8ef0b5a1d57a)
Sauvegarde Locale :
Dans le même raisonnement que le rebind des touches, permettre aux joueurs de conserver une trace de leurs performances entre sessions de jeu me semblait plus que pertinent, j'ai donc ajouté un système de sauvegarde grâce au PlayerPrefs de Unity, que je souhaite plus tard changer en un fichier json, plus simple à manipuler et à accéder que les PlayerPrefs et crypté.
J'y stocke ainsi les meilleurs temps par niveau et les rebinds de touche du joueur.
J'y stocke ainsi les meilleurs temps par niveau et les rebinds de touche du joueur.
![Script qui instancie un bouton de niveau dans le menu de selection](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/57136907-57b8-4e00-8816-75b8d982a719_rw_1200.png?h=a2c5477637de4491a60ca8664cc79d8f)
Script qui instancie un bouton de niveau dans le menu de selection
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/a2178380-b8bc-49d5-8700-c9f60b0986c8_rw_1920.png?h=d31fa553698021688e75ca79eccd74f0)
![Cheminement du chargement des sauvegardes de temps](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/41f199d0-e884-4199-be8d-93bc3addddbb_rw_1920.jpg?h=2c943698a3aa171cae3426d57a93bcf9)
Cheminement du chargement des sauvegardes de temps
Temps et Niveaux :
Les temps sont stockés en chaine de caractère sous la forme nomScene_temps, afin de les transformer en dictionnaire dans unity, ce qui correspond à une sauvegarde temporaire que j'utiliserais dans ma gestion de code, il me permet de récupérer le meilleur temps de chaque niveau, remettre à jour la sauvegarde locale et en même temps le dictionnaire.Pour notre écran de sélection de niveau, j'ai choisi de le gérer de façon dynamique afin d'éviter à notre level designer de devoir en créer un à chaque nouveau niveau. La seule condition est que le niveau doit être dans les builds settings.
J'ai également ajouté une preview du niveau qui va récupérer une image dans un dossier Ressources portant le nom du niveau associé.
Médailles :
La cible de notre jeu ayant une attirance pour le complétionnisme, j'ai donc proposé à mon groupe, un système de médaille que le joueur récupère en fonction du temps qu'il met à compléter un niveau. Cela permet de motiver le joueur à recommencer et améliorer son temps, tout en affichant le temps minimum pour atteindre la prochaine médaille, ou son meilleur temps, sur l'écran de fin.
Dans le GameManager, j'ai créé un tableau de données regroupant les 3 temps pour obtenir les 3 médailles de chaque niveau. Cela me permet de gérer l'affichage des médailles dans le menu de sélection de niveau et dans l'écran de fin, je n'ai ainsi pas à paramétrer les temps à deux endroits en même temps et j'évite ainsi des erreurs malencontreuses.
La cible de notre jeu ayant une attirance pour le complétionnisme, j'ai donc proposé à mon groupe, un système de médaille que le joueur récupère en fonction du temps qu'il met à compléter un niveau. Cela permet de motiver le joueur à recommencer et améliorer son temps, tout en affichant le temps minimum pour atteindre la prochaine médaille, ou son meilleur temps, sur l'écran de fin.
Dans le GameManager, j'ai créé un tableau de données regroupant les 3 temps pour obtenir les 3 médailles de chaque niveau. Cela me permet de gérer l'affichage des médailles dans le menu de sélection de niveau et dans l'écran de fin, je n'ai ainsi pas à paramétrer les temps à deux endroits en même temps et j'évite ainsi des erreurs malencontreuses.
![Tableau de données des temps Médailles à renseigner dans l'inspecteur](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/104951f6-f2c4-4346-b875-675189818ad7_rw_600.png?h=ac8e15da83a3b0c41bd1497991bbc309)
Tableau de données des temps Médailles à renseigner dans l'inspecteur
![Script qui retourne le nombre de médailles d'un niveau](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/278b0e02-95c9-41b8-82dc-4bf8fd620906_rw_600.png?h=ff2cc7695526226573c1124e5643a666)
Script qui retourne le nombre de médailles d'un niveau
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/07f57e8a-10f1-4034-9ad5-9b15c55c1512_rw_1920.png?h=6d57d256e2fc3221bf409c3b9387581f)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/cf4b8a77-df80-4169-bc96-5ba247f2979e_rw_600.png?h=05df5d28808d9bb7067a00dbc80ed6c9)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/f49923a8-7aeb-4283-9c45-629e484abba2_rw_600.png?h=3be1a85fe76989a00c9decb24c7887dd)
Altimètre :
J'ai pu remarquer lors de playtest que certains joueurs avaient du mal visualiser où le sol se trouvait par rapport à eux, surtout lorsqu'ils étaient au-dessus de parasite et voulaient attendre le dernier moment pour se téléporter, ils finissaient par mourir.
Pour pallier ce problème, j'ai décidé d'ajouter un altimètre dans l'UI en jeu, afin de donner l'information aux joueurs de leur position par rapport au sol au sein du niveau se trouvant juste en dessous d'eux.
J'ai pu remarquer lors de playtest que certains joueurs avaient du mal visualiser où le sol se trouvait par rapport à eux, surtout lorsqu'ils étaient au-dessus de parasite et voulaient attendre le dernier moment pour se téléporter, ils finissaient par mourir.
Pour pallier ce problème, j'ai décidé d'ajouter un altimètre dans l'UI en jeu, afin de donner l'information aux joueurs de leur position par rapport au sol au sein du niveau se trouvant juste en dessous d'eux.
Marqueurs de cible :
Notre avatar étant un cyborg, j'ai décidé d'ajouter un feedback visuel représentant un marquage de verrouillage que l'on peut retrouver dans certaines machines ou avion de chasse, lorsqu'une cible est en vue du joueur.
Notre avatar étant un cyborg, j'ai décidé d'ajouter un feedback visuel représentant un marquage de verrouillage que l'on peut retrouver dans certaines machines ou avion de chasse, lorsqu'une cible est en vue du joueur.
![Placeholder](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/7099a974-6329-4c44-b86b-89320b9da36d_rw_600.png?h=eb9a0e8ed65dad17b40d3523f22920a9)
Placeholder
![Rendu final de l'UI designer](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/d4ede7be-c30f-48d2-b217-c5550b7b05a4_rw_600.png?h=394711f35eab584eb8ea7e0bcea48f60)
Rendu final de l'UI designer
![Script plaçant les marqueurs sur l'écran](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/54566264-b8dc-4584-92b6-fdd94924aa97_rw_1200.png?h=3ded9a647babec1142b7161ebe2c3d2a)
Script plaçant les marqueurs sur l'écran
![Paramétrage des marqueurs](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/483807f1-45d6-48c9-8c9d-7660c6c58f67_rw_600.png?h=42e0634da5a57fdb0f0abbade61c1824)
Paramétrage des marqueurs
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/b589222a-f18e-41e2-9395-94376534bd05_rw_600.png?h=4de2530da09d0605339ec6a71150665c)
Intégration sonore :
Je me suis chargé d'intégrer les feedbacks sonores de notre projet en créant d'abord des placeholders dans FMOD. J'ai choisi de créer un SoundManager afin de centraliser la gestion audio du projet, de simplifier l'appel des sons en évitant leur dispersion à travers tous nos scripts, ce qui réduit le risque d'erreur. Je les place ensuite dans des EventUnity qui sont activés sous certaines conditions.
J'ai également adapté le script de la musique d'ambiance qu'un membre de mon groupe a fait afin de ne pas la stopper à chaque changement de scène (niveaux + menus) en plaçant le script dans le DontDestroyOnLoad.
Galerie du projet
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/50e29d62-70d8-44ef-8054-8d5ee092cfa3_rw_1920.png?h=d5db9ae49e9ab47e359966c961a2e10d)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/cec3d968-25f0-4bae-9486-1733f5b80748_rw_1920.png?h=97ef5c27952f1c86aab2fa0463c3d5ee)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/8e2243c3-e362-4166-8a78-07b960bb1399_rw_1920.png?h=dd5d4535af554cd2cceb11d2ed7ca3a0)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/61c14517-f76b-4bc2-a662-eac717408374_rw_1920.png?h=a039bc1de9a6859e4a958f2a03e9c926)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/e08f5e3f-a3ad-4da6-955e-ba9c21639ff0_rw_1920.png?h=4fda3d54457c17c90b912b82d19a3123)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/1a80d13e-1b44-4861-87c8-d23a7f4772c5_rw_1920.png?h=3d4aad26b11c442b811d9dd71f9f3de5)
![](https://cdn.myportfolio.com/e56bac67-6df1-4a3b-9333-6f0dbc203aae/47f4c39f-11b9-418e-b579-c55979e5bb8c_rw_1920.png?h=343b1995c9037bb1d657bddd12faf605)