Post Mortem – Partie 2 : Un jeu en 2D avec Unity3D


Ceci est la partie 2 du post mortem de mon jeu, L’Antre du Protecteur. Elle fait suite à la Partie 1 – Un voyage de 4 ans.

L’Antre du Protecteur est mon premier jeu utilisant Unity, un moteur de jeu gratuit devenu extrêmement populaire aujourd’hui. Du moins, le premier jeu que j’ai commencé avec Unity, vu que j’ai sorti plusieurs jeux de game jams entretemps. L’utilisation d’un moteur de jeu en soi était une première pour moi. J’ai toujours rejeté les logiciels de création de jeu, d’une part par fierté de vouloir tout faire moi-même et d’autre part par peur d’être très limité à un genre ou des mécaniques de jeu particulières. Concernant ce dernier point, c’est certainement le cas pour des logiciels spécifiques comme RPG Maker ou Twine. Mais Unity n’ayant pas ce genre de contraintes, j’ai finalement décidé de l’essayer.

Dans la suite de ce post, je vais tâcher d’évaluer cette première expérience qu’était la création d’un jeu en 2D avec Unity.

Screenshot de Unity avec mon projet ouvert au dernier niveau

Unity vs C++/SFML

Auparavant, je faisais tous mes jeux en C++ avec l’aide de SFML, une librairie gérant les aspects graphiques, audio et les inputs (entre autres), mais sans fonctionnalités spécifiques aux jeux vidéo.

Je dois bien reconnaître que Unity a simplifié pas mal de choses et m’a permis d’aller bien plus loin que si j’avais dû tout faire par moi-même. Parmi les choses que j’ai aimées, je citerais entre autres :

  • Avoir un éditeur intégré. Probablement LE truc qui change tout. Avoir un éditeur pour naturellement construire les niveaux, modifier des éléments, avoir un aperçu en temps réel, prévisualiser les animations en changeant les valeurs à la volée… Tellement de choses qui accélèrent le développement ! Bien entendu, cela est possible en faisant tout soi-même aussi, mais cela demande de développer soi-même l’éditeur, ce qui est rapidement très laborieux et doit se faire en parallèle du développement du jeu en lui-même. C’est ce que j’avais fait pour Onalyan en 2011, mais le résultat était très rudimentaire.
  • Ne pas devoir redévelopper tout un tas de trucs récurrents à beaucoup de jeu. Je dois bien avouer que la plupart de mes anciens projets avaient pas mal de choses en commun que je finissais inévitablement par redévelopper. Une perte de temps évitée avec un moteur de jeu qui fournit déjà naturellement une boucle principale, un système d’update des objets du jeu, une gestion des événéments, un système d’animation, etc. Même sans moteur de jeu, il y a bien sûr la possibilité d’utiliser des librairies externes pour gérer certains aspects du jeu. Mais ce n’était cependant pas toujours facile en C++.
  • Les builds multiplateformes. La possibilité de sortir sont jeu à la fois sous Windows, Linux et Mac (voire dans le navigateur avec WebGL) est un bonus formidable. Cela peut vite devenir un enfer avec du code fait maison, surtout si on n’a pas un accès direct aux dites plateformes.
  • Une communauté très grande. La communauté Unity est vaste et de très nombreuses ressources sont disponibles pour apprendre ou trouver des réponses aux problèmes rencontrés.

Je n’ai pas cité l’Asset Store (que je n’ai pas utilisé) ou le système de particules et bien d’autres possibilités offertes par Unity qui sont certes très intéressantes mais plus spécifiques. Beaucoup de positif de cet expérience, donc. Néanmoins, certaines choses m’ont aussi manqué par rapport au développement en C++/SFML :

  • Un code propre et bien structuré. Beaucoup de gens se lançant dans la création de jeu sans expérience en programmation y voient un énorme obstacle et préféreront alors avoir le moins possible de code à écrire, utilisant au maximum des librairies externes ou s’aidant d’outils tels que le Visual Scripting. Personnellement, j’aime la programmation et j’aime pouvoir organiser mon code comme je le veux. J’aime que tout s’assemble parfaitement, et trouver la manière la plus optimale ou élégante de résoudre un problème. Avec Unity, ce plaisir s’est retrouvé entaché par plusieurs choses :
    • L’obligation d’utiliser C#, qui sans être mauvais n’est pas mon langage préféré.
    • Devoir tout lier à un GameObject : un objet « physiquement » présent dans le jeu, un élément d’UI et un élément purement logique type « GameController » vont tous devoir être liés à des GameObjects, qui seront mélangés ensemble sans distinction dans l’éditeur. Il y a moyen d’extraire de la logique vers des classes à part mais en fin de compte, il faudra toujours bien un script attaché à un GameObject pour les appeler. Je me suis retrouvé avec un grand nombre de scripts indépendants plutôt qu’avec une codebase propre et organisée. Cela a aussi pour conséquence que les scripts ne sont pas toujours compréhensibles en eux-mêmes mais dépendent fortement du contexte qui n’est visible que dans l’éditeur.
  • Être dépendant des caprices d’Unity. En codant tout moi-même, je comprends ce que je fais et je sais précisément ce que va faire tel ou tel élément du code. Avec Unity, je me suis retrouvé dépendant de beaucoup de composants sur lesquels je n’avais pas de contrôle. À de nombreuses reprises, je me suis demandé si implémenter moi-même une fonctionnalité n’aurait pas été plus simple que de me battre avec les comportements pas toujours cohérents ou bien documentés des composants propres à Unity.
  • Le manque de légèreté. Unity peut être vraiment lourd, et inclut par défaut une myriade de choses dont je n’avais pas nécessairement besoin. Quand je code moi-même, je n’ajoute que des choses dont j’ai besoin et cela est je crois un peu moins pesant.

Points négatifs

Dans la section précédente, j’ai détaillé certains des aspects de Unity qui m’ont beaucoup plu, et il va sans dire que Unity est outil formidable offrant bien plus de choses que ce que j’ai pu citer. De plus, ayant réalisé un jeu en 2D, je n’ai pas pu juger tous les éléments propres à la 3D qui sont au cœur de ce moteur de jeu. Dans cette partie, je vais donc plutôt me concentrer sur les choses qui m’ont déplu durant les 4 années de la réalisation de mon jeu.

  • Devoir se préoccuper de la 3D alors que je fais de la 2D. Comme le laissait présager le titre de ce post, c’est probablement LE truc qui m’a le plus embêté. Unity est fait pour la 3D. Et, même s’il propose tout un tas d’éléments et de fonctionnalités spécifiques à la 2D, elles s’intègrent néanmoins dans un écosystème où la 3D est omniprésente et prioritaire. Outre le fait que les menus s’en retrouvent chargés de composants qui me sont inutiles, le problème majeur vient du fait que tous les objets ont une position en x, y, z. En pratique, en 2D, la position en z n’a pas de sens, pourtant elle est bien là et il faut régulièrement s’en préoccuper. Quelques exemples :
    • La caméra ne « voit » que jusqu’à une certaine distance en z, il faut donc vérifier que ce z se situe à bonne distance, ou vous vous retrouvez à chercher pendant des plombes pourquoi un objet ne veut pas s’afficher.
    • Les sources audio proposent un système d’atténuation du volume en fonction de la distance entre le « listener » et la source. Sauf que si par malheur ils se situent sur des z très éloignés, quand bien même il seraient très proches sur la projection 2D, alors le volume sera systématiquement trop faible.
  • La documentation pas toujours claire. Difficile de trouver des exemples ici, néanmoins je me suis retrouvé de nombreuses fois à batailler avec des composants qui ne faisaient jamais ce que je voulais, sans que cela ne soit toujours bien expliqué dans la documentation. Je pense que cela manque d’exemples et de plus d’explications/astuces/avertissements propres au contexte dans lequel les composants pourront être utilisés.
  • La physique. Unity propose un système de gestion de la physique, et notamment des collisions, qui fonctionne assez bien. Cependant, dans mon cas, je ne voulais pas utiliser ce moteur physique à 100%, au profit d’une physique simplifiée mais plus agréable pour le joueur. Le problème est que j’ai trouvé difficile de n’utiliser qu’une partie de ce moteur physique : ça devient très vite le bordel et il faut vraiment penser à beaucoup de choses avant de trouver un équilibre.
  • Le chargement est loooong. Au fur et à mesure que mon projet grossissait, Unity a commencé à prendre de plus en plus de temps pour le charger. Sur la fin, c’était près de 10 minutes d’attente.
  • Les chargements après démarrage sont aussi pénibles. Par défaut, Unity charge les derniers changements dès que le focus repasse sur sa fenêtre : les scripts modifiés sont re-compilés, les nouveaux fichiers sont chargés, etc. Cela peut prendre un peu de temps, ce qui me paraît normal. Sauf que bien souvent je n’ai pas besoin de recharger tout immédiatement, et je me retrouve avec mon Unity bloqué pour plusieurs secondes parce que j’ai ajouté une ligne de code qui aurait pu attendre. Du coup, je suis passé en « reload manuel », ce qui a maintenant pour effet qu’une fois sur trois j’oublie de recharger et je ne comprends pas pourquoi mes changements n’ont eu aucun effet quand je lance le jeu. Un bouton « Reload & Play » serait tellement plus pratique !
  • Beaucoup d’aspects restent assez rudimentaires. Si le moteur physique et graphique sont très puissants, beaucoup d’autres aspects restent relativement peu développés et doivent être faits soi-même. Je pense notamment :
    • Au système d’inputs, qui ne permet pas de facilement reconfigurer les touches au runtime, ou qui est très obscur dès qu’il s’agit de gérer des contrôles à la manette. Ceci dit, je sais qu’un nouveau système est en bêta, mais je ne l’ai pas encore essayé.
    • À la gestion du son, peu intuitive à mes yeux. Avec notamment le « pitch » qui modifie en réalité la vitesse du son, ou le fait qu’on ne puisse pas faire dépendre un son du « timescale » automatiquement.
    • À la gestion des scènes : garder du contexte lors du passage d’une scène à l’autre n’est ni simple ni intuitif.
    • À la gestion des sauvegardes : là aussi il faut quasiment tout faire soi-même. Tout ce que fournit Unity est un système de base de données clé/valeur très primitif.

Pourquoi pas un autre moteur ?

Alors bien sûr, Unity n’était pas la seule option. J’aurais pu essayer l’Unreal Engine, ou plutôt des moteurs de jeu propres à la 2D tels que Löve2D. Pourquoi pas. Mais en soi, tout partait au départ d’une envie de découvrir Unity plutôt que d’un choix spécifique du moteur basé sur mes besoins. Et, malgré ses défauts, j’ai tout de même pu terminer mon jeu avec.

Conclusion

Dans l’avenir, j’aimerais explorer d’autres outils. D’autres moteurs de jeu, notamment. J’aimerais aussi tenter de créer des jeux en Rust (par exemple avec Amethyst) ou même en Elixir avec Phoenix LiveView. Dans tous les cas, mon expérience avec Unity n’a pas été mauvaise et il est fort possible que j’y retourne, notamment pour essayer de me mettre à la 3D.

Bref, il y a énormément de choses à explorer et il me tarde de le faire. Rester concentrer sur le même jeu et les mêmes outils pendant 4 ans peut être une expérience très frustrante par moment. Ce qui m’amène à la troisième partie de ce post mortem: Partie 3 – apprendre ou créer ?

Get L'Antre du Protecteur (2020)

Leave a comment

Log in with itch.io to leave a comment.