Aperçu gratuit · E-book #1
Clean Unity : un jeu mobile à l'architecture robuste
Vous savez développer des applications ? Unity vous ouvre le jeu vidéo, la réalité augmentée et la gamification, avec un langage et des principes que vous connaissez déjà. Cet e-book vous fait installer Unity, ouvrir un vrai projet, puis y appliquer une architecture propre et testée : Clean Unity, sur un module d'achievements réutilisable, Clean Achiever.
Avant de commencer
Développeur d'applications, élargissez votre terrain de jeu
La plupart des développeurs qui ouvrent cet e-book n'ont jamais touché à Unity. C'est pour eux qu'il est écrit : vous partez de ce que vous savez déjà faire, et vous repartez avec une compétence de plus.
Pourquoi apprendre Unity quand on fait des applications
- Un nouveau terrain : Unity fait tourner une grande partie des jeux mobiles, et sert aussi pour la réalité augmentée, les simulations et les expériences interactives.
- Un langage familier : les scripts s'écrivent en C#, un langage typé et orienté objet, proche de Swift, Kotlin ou TypeScript.
- Une architecture que vous connaissez peut-être déjà : le cycle VIP de cet e-book vient du monde iOS, avec Clean Swift. Si vous avez croisé VIPER ou Clean Swift, vous êtes en terrain connu.
- Un vrai atout : beaucoup de projets Unity souffrent de scripts géants et sans tests. Savoir y mettre de l'ordre vous démarque.
Pas besoin de savoir faire de la 3D
Malgré son nom complet, Unity 3D, cet e-book n'enseigne ni la modélisation, ni l'éclairage, ni les caméras. Il vous apprend à structurer le code d'un jeu, en 2D comme en 3D. La démo, Clean Achiever, est d'ailleurs en 2D : des boutons et une fenêtre d'objectifs.
Installer Unity et ouvrir le projet
- Installez Unity Hub, le lanceur qui gère les versions d'Unity et vos projets, en suivant la page d'installation officielle. Créez un compte Unity : la licence Personal est gratuite pour apprendre et pour les petits projets.
- Dans Unity Hub, onglet Installs, installez la dernière version LTS (support long terme) proposée. Aucun module supplémentaire n'est nécessaire pour suivre l'e-book.
- Téléchargez le projet sur GitHub : l'état de départ pour coder au fil de la lecture, ou l'état final pour lire le code terminé. Prenez l'archive Source code (zip) et décompressez-la.
- Dans Unity Hub, onglet Projects, choisissez Add, puis le dossier
CleanAchieverqui contientAssets. - Le projet a été créé avec Unity 2017 : à l'ouverture, Unity propose de le mettre à jour vers votre version. Acceptez. La console peut ensuite afficher des avertissements liés aux noms d'API qui ont changé depuis (voir la note de la partie 6).
- Dans la fenêtre Project, ouvrez
Assets/Scenes/Menu.unity, puis cliquez sur Play : le jeu se lance dans l'éditeur.
Pour découvrir l'éditeur en douceur, les tutoriels gratuits de Unity Learn complètent bien cette lecture.
Partie 1
Le problème des classes Controller et Manager
Vous reconnaissez-vous dans l'une de ces situations, sur Unity ou dans vos applications ?
- Vous démarrez un tout nouveau projet Unity et vous ne savez pas par où commencer.
- Vos contrôleurs deviennent massifs, difficiles à comprendre et à enrichir.
- Vous sentez que ce que vous prévoyez finira en code spaghetti après quelques modifications.
- Vous passez un temps considérable à corriger des bugs de cas limites.
- Ajouter une fonctionnalité veut dire régressions et grosse refonte.
- Vous vous sentez coupable quand votre client vous dit « ça marchait avant ».
- Vous ne savez plus pourquoi votre classe
Playerest liée à votre classeEnemy. - Vous trouvez que le TDD demande trop d'efforts pour ce qu'il rapporte.
Ça ne doit pas forcément se passer comme ça. Vous n'êtes pas obligé de vous en tenir à MVC et à des MonoBehaviour géants.
MVC tient tant que le projet reste petit. Mais au fur et à mesure qu'il grandit, les classes enflent, la vue est liée aux modèles, rien n'est réutilisable, et on ne sait même plus comment tester tant tout est couplé. Parcourir des projets et des exemples de code ne donne que des astuces, pas une ligne directrice.
Imaginez savoir exactement quel fichier ouvrir et quelle méthode modifier, corriger un bug sans en créer un autre, ajouter une fonctionnalité sans rien casser, et dire précisément combien de temps elle prendra. Une bonne architecture rend tout cela possible, à commencer par les tests.
Unity 3D, en deux mots
Unity est un moteur de jeu : un logiciel qui gère la scène 3D, la physique, les entrées, le son et l'affichage, et qui exécute votre code C# à chaque image. Vous assemblez une scène à partir d'objets (les GameObject), vous attachez des scripts (les MonoBehaviour) à ces objets, et vous réglez leurs champs dans l'inspecteur.
Prérequis
- Savoir programmer dans un langage orienté objet : Swift, Kotlin, Java, C#, TypeScript…
- Aucune expérience d'Unity : les notions utiles (scène, GameObject, MonoBehaviour, inspecteur) sont expliquées au fil de l'e-book.
Pourquoi un jeu n'est pas une application classique
Une application classique attend les actions de l'utilisateur, affiche un écran, puis se repose. Un jeu tourne en permanence : la boucle de jeu recalcule la scène à chaque image, souvent 60 fois par seconde, même quand le joueur ne fait rien. Le temps devient une donnée à part entière (Time.deltaTime), l'état évolue sans demande explicite, et les événements se croisent en temps réel : collisions, minuteurs, réseau.
La gamification ajoute une couche de plus : objectifs, récompenses, progression. C'est exactement le genre de logique qu'on est tenté de mélanger avec l'affichage et le stockage, et qui finit dans un MonoBehaviour géant si l'architecture ne la protège pas. Clean Achiever est un exemple de module qui isole cette logique.
Côté business, les jeux se pilotent souvent avec trois indicateurs : l'acquisition (comment les joueurs arrivent), la rétention (combien reviennent, à J1, J7, J30) et la monétisation (combien rapporte chaque joueur). Ce ne sont pas des mécaniques de jeu, mais des mesures : la gamification sert à faire revenir le joueur, la rétention mesure si elle y arrive. Votre architecture doit permettre de brancher ces mesures sans que la logique métier dépende de l'outil d'analyse.
Dans cet e-book, vous apprendrez à :
- Installer Unity et lancer un vrai projet de jeu.
- Appliquer Clean Unity et le cycle VIP pour concevoir des modules Unity réutilisables.
- Séparer les responsabilités entre Controller, Interactor, Worker et Presenter.
- Garder vos données indépendantes d'un module à l'autre avec des DTO.
- Découpler vos objets de jeu avec le pattern Observer.
- Écrire des tests unitaires rapides, qui tournent dans l'éditeur Unity.
Partie 2
Clean Unity : la Clean Architecture appliquée à Unity
Une base de code Unity n'a pas à être un tas de « classes rangées par sujet ». Votre jeu gère les entrées du joueur, des calculs, du réseau, et doit rendre une image à chaque frame : il faut séparer les responsabilités.
Réduisez au maximum le couplage entre la vue et la logique, isolez le réseau dans un bloc à part, et concevez vos modules pour qu'ils soient réutilisables d'un jeu à l'autre. Évitez de partager les mêmes structures de données entre modules : chaque module doit rester indépendant.
Les principes SOLID
- S, responsabilité unique : chaque classe a une seule tâche (votre classe réseau n'affiche aucune interface).
- O, ouvert/fermé : un module est ouvert à l'extension mais fermé à la modification ; l'architecture anticipe les ajouts.
- L, substitution de Liskov : une sous-classe garde le sens de sa classe mère.
- I, ségrégation des interfaces : de petites interfaces, chacune avec un rôle précis.
- D, inversion des dépendances : les modules de haut niveau dépendent d'abstractions, pas des détails.
Pour appliquer ces idées au jeu vidéo, nous partons de la Clean Architecture d'Uncle Bob, simplifiée pour Unity : appelons-la Clean Unity. Elle organise le code par intention (ce que fait le joueur) plutôt que par choix techniques.
Le cycle VIP
Trois composants principaux s'enchaînent, chacun étant l'entrée du suivant, plus un quatrième qui les relie :
Événement (joueur, cycle de vie)
│
▼
Controller
│ Request DTO
▼
Interactor ◀──▶ Worker (stockage, réseau)
│ Response DTO
▼
Presenter
│
▼
Objets de la scène
Initializer : crée et relie les blocs,
détient les références de la scène
- Le Controller est le point d'entrée de tous les cas d'usage. Il reçoit les événements (toucher, collision, cycle de vie du MonoBehaviour) et déclenche le cas d'usage, à travers une interface.
- L'Interactor porte la logique métier : il calcule ce qu'il faut afficher. Il reçoit un DTO de requête plutôt que des variables du Controller : c'est l'indépendance des données, on peut changer la requête sans toucher au reste.
- Le Worker, optionnel, récupère la logique trop lourde ou réutilisable de l'Interactor : stockage, réseau.
- Le Presenter met en forme la réponse et l'applique à la scène : interface 2D, mouvements 3D, animations, sons.
- L'Initializer joue le rôle de « composition root » : il détient les références de la scène et des assets, les valide, et relie les blocs entre eux.
Résultat : vous savez exactement quel fichier ouvrir, vos méthodes sont courtes, et vos tests tournent en quelques secondes, sans lancer la scène.
Partie 3
Clean Achiever : les spécifications du module
Dans le dépôt : le fichier Objectives.cs.
Clean Achiever est une application de démonstration : un système d'achievements générique, réutilisable dans tous vos jeux. Trois buzzers déclenchent la progression des objectifs, du type « Touchez le buzzer jaune 10 fois ». Chaque objectif a une récompense, et les objectifs vont par groupes de trois, chacun avec un titre : « Quest 1 : The Beginning ! », « Quest 2 : A Great Adventure ! »…
Le code complet est sur GitHub : One-Week-Apps/CleanAchiever. L'état de départ est dans la release 0.1, l'état final dans la release 1.1. Il contient aussi des modules d'aide (menus, interface, fenêtres d'information) sur lesquels nous ne nous attarderons pas.
Les 5 cas d'usage
- Fetch : récupérer les objectifs du jeu depuis le stockage.
- Flush : renouveler le groupe d'objectifs pour en proposer un nouveau.
- Step : faire avancer un objectif actif d'une unité.
- Claim : réclamer la récompense d'un objectif atteint.
- Reset : réinitialiser la progression.
Le modèle
Tout le module tient dans une structure Objectives, qui regroupe les types, le modèle, le modèle de vue et les DTO de chaque cas d'usage :
public struct Objectives
{
public enum ObjectiveTypes { Scores, Kills, Hits, Boss, PowerItems, Time, // compteurs
Power, Currency, UnlockLevel, UnlockCharacter, Stats, // événements
Yellow, Green, Blue, // buzzers
Other, _COUNT }
// Un ensemble d'objectifs par monde, niveau ou mode de jeu
public enum ObjectiveSet { Game, World1, World2, World3, World4, World5 }
public struct ObjectivesModel
{
public int id;
public ObjectiveTypes type;
public string title;
public string description;
public bool isLocal; // « en une partie » ou compteur global
public int currentStep;
public int numberOfSteps;
public bool isRewardClaimed; // faux par défaut, vrai une fois réclamée
public int reward;
}
[System.Serializable]
public struct ObjectivesViewModel
{
public Text titleLabel;
public Text descriptionLabel;
public Text completionLabel;
public Text rewardLabel;
public Button claimButton;
public Image starImage;
}
}
L'attribut [System.Serializable] rend la structure modifiable dans l'inspecteur Unity : on y assigne simplement les éléments d'interface de chaque objectif.
Fin de l'aperçu
La suite est dans la formation One Week Apps
Vous venez de lire 3 modules sur 10. Les suivants vous attendent :
- L'Initializer, racine de composition
- Le Worker et la persistance
- Le cas d'usage Fetch, de bout en bout
- Step : faire avancer un objectif avec le pattern Observer
- Flush, Claim et Reset
- Les tests unitaires
- Bilan : les bénéfices de Clean Unity
La formation complète : La Méthode (4 modules, de l'idée à l'App Store), les e-books Clean Unity et Accessibilité iOS, le bonus App Store, et l'application Focus pour déléguer vos tâches au Runner.
Voir la formation