top of page

Lumis

Projet de groupe | 4 personnes | 1 an

Contexte

Lumis est mon projet de fin d'études, il dure un an et est composé de 3 autres personnes :
Louis Deprez
Anatole Lesur
Mercury De Sainte Maresville


Je suis en charge de la programmation de ce projet.

Concept

Lumis est un jeu dans lequel on peut solidifier les ombres.
On y incarne Noisette, qui se retrouve dans un endroit mystérieux, le but est donc de résoudre des énigmes en marchant sur les ombres tout en cherchant ce qu'il s'est passé.

Le jeu a comme ligne directrice le message qu'il veut transmettre, celui-ci étant d'affronter ses problèmes.

D'autres mécaniques sont présentes, comme les Luxo (interrupteur) et des crochets sur lesquels on peut placer un objet, et déclencher des mécanismes.

Luxo

Crochets

Aperçus Graphique

Programmation

Je suis en charge de la programmation de ce projet, j'ai donc programmé la mécanique des ombres ainsi que des outils permettant aux membres du groupe d'utiliser plus simplement les éléments du jeu.

Player

Pour le joueur j'ai utilisé des courbes pour l'accélération et la décélération, ainsi que le New Input System

Courbes

New Input System

States machines

En restant sur le joueur, j'ai utilisé des states machines pour gérer les états suivants :

- Idle
- Walk
- Jump
- Fall
Et sûrement d'autres états

Héritage & Interfaces

Au tout début, j'ai utilisé des interfaces mais en refactorisant, j'ai utilisé de l'héritage, en soi leurs fonctionnements sont assez similaires mais l'avantage, c'est qu'avec l'héritage on n'est pas obligé d'override.

Interfaces

Les interfaces étaient utilisées pour 2 choses :
- Les éléments interactifs
- Les teneurs d'objets

Héritage

Comme dit précédemment je suis en train de refactoriser mes scripts, et j'ai décidé de passer à de l'héritage classique plutôt qu'une interface.

Eléments interactif

Pour les éléments interactifs, tout début avec une classe abstraite, InteractableObject, l'intérêt de la mettre abstraite est d'avoir des fonctions abstraites d'interactions, fonctions qu'on pourra aller chercher et override.

Ensuite, on a TakableObject qui concerne tous les objets que le joueur peut ramasser, et pour finir on a Lantern et Weight qui sont 2 objets que le joueur peut ramasser avec en plus des fonctionnements propres à eux.

Donc Lantern hérite de TakableObject qui lui-même hérite de InteractableObject.

Teneurs d'objets

En ce qui concerne les teneurs d'objets, leur fonction va être de tenir un objet, et de changer leur état si le joueur interagit avec.

On commence avec ObjectTaker qui contient les fonctions pour changer d'état et les variables associées.

Les Hook (crochets) et le PlayerObjectTaker sont des scripts qui héritent de ObjectTaker. 
Pour le crochet, il a 2 modes, normal ou à poids (déclenche quelque chose quand il a un objet) et pour le PlayerObjectTaker, il gère l'objet que tient le joueur et les éléments interactifs.

Schéma Teneurs d'objets

image.png

Inspecteur d'un crochet à poids

Dev tools & Editeur de niveaux

Une de mes priorités c'est que le reste du groupe n'ait pas de difficulté à utiliser mes scripts et mes systèmes, c'est pourquoi j'ai fait quelques systèmes pour les aider.

Dev Tools

Pour faciliter la vision des scènes, j'ai créé une fonction statique pour prendre un screenshot de la vision de la caméra en cours.

Je n'hésite pas aussi à utiliser des attributs pour mieux gérer l'inspecteur, en utilisant le package NaughtyAttribute, je peux avoir un peu plus d'attributs et je peux aussi mettre des couleurs ou encore même cacher certaines informations si pas nécessaire.

Comme les crochets, selon le mode certaines informations ne sont pas nécessaires.

image.png
image.png

Ou encore pour les niveaux, les niveaux sont gérés par une grid de niveaux, chaque case étant donc un niveau, ensuite j'ai créé des repères visuels pour chaque niveau.

Chacun a des flèches jaune représentant le BoxCollider qui fera transitionner le joueur vers le niveau voisin et les traits bleu représentant le point d'apparition du joueur après une transition.

Capture d'écran 2026-01-07 160159.png
image.png

Editeur de niveau

J'ai aussi créé un éditeur de niveau, son but était de rendre la création de niveau plus simple à itérer, Dès qu'on enlève Play, il sauvegarde automatiquement une nouvelle scène avec les éléments ajoutés.

Système d'ombre

Le système d'ombre changera de fonctionnement, je suis actuellement en train de refactoriser mon code et je tente d'autres pistes de fonctionnement.

Néanmoins un moyen fonctionnel qu'on a utilisé pour notre vertical slice est le suivant :

Etape 1 : Séparation Elements du jeu / Lights et ombres
       - On a une caméra qui ne voit que les lumières et les ombres

Screenshot_20260107_153448.jpg

Etape 2 : Séparation Pixel Noir / Pixel Blanc
       - On crée une RenderTexture2D

       - On lit la texture et on détecte où les pixels blancs et les pixels noirs se séparent

image.png

Etape 3 : Création de collider sur la technique des Marching Square
       - On crée des collider sur un PolygonCollider2D

Nouveau Système d'ombre

Le nouveau système n'est pas terminé mais son fonctionnement sera similaire à ce que fait Unity pour les ombres visuelles. Unity utilise un shader mais ce que j'ai prévu de faire c'est de récupérer tous les casters (objets qui font de l'ombre) et toutes les lights pour ensuite projeter les ombres depuis chaque lumière grâce à des calculs.

Le but est d'avoir une mécanique qui demande un peu moins de ressources car la méthode actuelle peut faire freeze si on met une trop grande résolution.
J'essaye donc d'avoir un équilibre entre optimisé et fidèle au visuel d'ombre (d'où le fait que je m'inspire du système d'Unity)

Fin

bottom of page