← Retour au cours
▶ Aperçu gratuit · Leçon offerte

Unity 6 : Editor, C#, GameObjects, DOTS/ECS

⏱ 960 min · 🎬 Lecon · 🏆 20 XP
🎬
Vidéo en production
Notre équipe pédagogique tourne actuellement cette leçon avec un·e formateur·rice expert·e. Le contenu textuel ci-dessous est complet et utilisable dès maintenant.

Leçon 1 — Unity 6 : Editor, C#, GameObjects, DOTS/ECS

Maîtriser l'environnement Unity 6 LTS, le cycle de vie MonoBehaviour, les Prefabs, ScriptableObjects, Cinemachine et l'architecture DOTS/ECS pour produire des jeux performants en C#.

🎯 Objectifs pédagogiques

  • Naviguer dans l'Editor Unity 6 (Hierarchy, Scene, Inspector, Project, Console) et structurer un projet propre.
  • Maîtriser le cycle de vie MonoBehaviour : Awake, OnEnable, Start, Update, FixedUpdate, LateUpdate, OnDestroy.
  • Utiliser Prefabs (variants, nested) et ScriptableObjects pour découpler data et logique.
  • Piloter une caméra cinématique avec Cinemachine (Virtual Camera, blends, dolly).
  • Migrer du paradigme classique vers DOTS/ECS (Entity Component System) pour gagner 10× en performance CPU.

1. Unity 6 LTS : positionnement et choix techniques

Sortie en octobre 2024, Unity 6 est la version Long-Term Support (LTS) qui remplace 2022 LTS. Elle apporte le GPU Resident Drawer (rendu CPU-free), le Spatial-Temporal Post-processing (upscaling AI), le support natif WebGPU, et surtout la stabilisation complète du DOTS stack (Burst Compiler, Job System, ECS) qui était en preview depuis 2019. Côté licence : Unity Personal reste gratuit jusqu'à 200 000 USD de revenus annuels, Unity Pro est facturé 2 200 USD/siège/an. Le scandale du Runtime Fee annoncé en 2023 a été annulé par le nouveau CEO Matt Bromberg en septembre 2024.

Unity domine le marché du mobile et de l'indie : 70 % des jeux mobile installés en 2025 tournent sous Unity (Source : data.ai). Le moteur excelle pour les jeux 2D, mobile, AR/VR, casual et mid-core. À l'inverse, pour de la production AAA photoréaliste sur PC/console, Unreal 5 reste préférable (voir leçon 3). Beaucoup de studios professionnels maîtrisent les deux moteurs et choisissent selon le projet.

"Unity 6 is the most stable, performant, and AI-ready version of Unity ever." — unity.com/releases/unity-6 (octobre 2024)

2. L'Editor Unity 6 — anatomie d'un projet pro

L'éditeur s'organise autour de cinq fenêtres principales : Hierarchy (arborescence des GameObjects de la scène), Scene (vue 3D éditable), Game (rendu caméra runtime), Inspector (composants du GameObject sélectionné) et Project (assets sur disque). La Console affiche logs, warnings et erreurs. Une scène (.unity) est un fichier YAML décrivant un graphe de GameObjects. Un projet pro comporte typiquement plusieurs scènes additives : Persistent (managers DontDestroyOnLoad), MainMenu, Level_01, Level_02, UI_HUD.

L'arborescence d'assets standard : Assets/_Project/Scripts/, Assets/_Project/Prefabs/, Assets/_Project/Materials/, Assets/_Project/Audio/, Assets/_Project/Scenes/. Le préfixe _Project garde tes fichiers en haut du Project window. Le dossier StreamingAssets/ embarque des fichiers bruts (vidéos, fichiers JSON, ScriptableObjects exportés) accessibles via Application.streamingAssetsPath.

3. MonoBehaviour : le cycle de vie qu'il faut connaître par cœur

Tout script attaché à un GameObject hérite de MonoBehaviour. Le moteur appelle automatiquement des méthodes spéciales selon l'événement. L'ordre exact d'exécution est documenté sur docs.unity3d.com/Manual/ExecutionOrder.html et conditionne le bon fonctionnement de tout système gameplay non-trivial.

✏️ Code C# — PlayerController complet

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private float moveSpeed = 5f;
    [SerializeField] private float jumpForce = 7f;
    [SerializeField] private LayerMask groundMask;
    private Rigidbody rb;
    private bool isGrounded;

    void Awake()  // appelé une fois, AVANT Start, même si l'objet est désactivé
    {
        rb = GetComponent<Rigidbody>();
    }

    void Start() // appelé une fois, après tous les Awake, avant le premier Update
    {
        Debug.Log("Player ready");
    }

    void Update() // appelé chaque frame (variable : 60-144 Hz selon FPS)
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        Vector3 move = new Vector3(h, 0f, v) * moveSpeed * Time.deltaTime;
        transform.Translate(move, Space.World);

        if (Input.GetButtonDown("Jump") && isGrounded)
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
    }

    void FixedUpdate() // fixe : 50 Hz par défaut, idéal pour la physique
    {
        isGrounded = Physics.Raycast(transform.position, Vector3.down, 1.1f, groundMask);
    }
}

Bonne pratique : récupère les composants dans Awake(), jamais dans Update() (10× plus lent). Utilise Time.deltaTime dans Update pour des mouvements frame-rate indépendants, Time.fixedDeltaTime dans FixedUpdate.

4. Prefabs, ScriptableObjects et architecture data-driven

Un Prefab est un GameObject réutilisable stocké comme asset. Modifier le prefab propage les changements à toutes les instances de la scène. Les Prefab Variants (Unity 2018+) permettent d'hériter d'un prefab parent en surchargeant certaines propriétés (façon class inheritance). Les Nested Prefabs autorisent un prefab à contenir d'autres prefabs (utile pour les modulaires : un château contient des Prefab tourelles).

Les ScriptableObjects sont des assets contenant uniquement de la data (pas de Transform, pas de scène). Ils servent à découpler la configuration du code : ItemData (nom, sprite, prix), EnemyConfig (HP, dégâts, IA), QuestData. Avantage clé : un designer modifie un asset .asset dans l'Inspector sans toucher au code C#.

5. Cinemachine : caméras procédurales en 10 minutes

Cinemachine, intégré nativement depuis Unity 2019, remplace le scripting manuel de caméra par un système déclaratif : tu poses une Virtual Camera qui pointe une cible, tu choisis le Body (Tracking 3rd Person, Framing Transposer 2D, FreeLook orbital) et le Aim (Composer, Hard Look At). Pour passer d'une caméra à une autre (cinématique → gameplay), il suffit de désactiver l'une et d'activer l'autre : Cinemachine effectue un blend automatique (cubic, ease-in/out) sur la durée définie. Un Cinemachine Brain unique sur la Main Camera orchestre l'ensemble.

6. DOTS/ECS : la révolution data-oriented

Le paradigme classique Unity (MonoBehaviour + GameObject) est object-oriented : chaque objet contient ses méthodes et ses data dispersés en mémoire (cache misses fréquents). Le Entity Component System (ECS) est data-oriented : les data sont stockées en arrays contigus en mémoire (chunks), processées en batch par des Systems via le Burst Compiler (compile C# en code SIMD natif) et le Job System (multithreading sans-fil-d'attente). Résultat : 10× à 100× plus rapide pour des milliers d'entités (boids, projectiles, particules).

CritèreMonoBehaviour (OOP)ECS (DOTS)
ParadigmeObject-OrientedData-Oriented (cache-friendly)
Performance max~1 000 GameObjects actifs~1 000 000 entités
MultithreadingManuel, complexeAutomatique via Job System
CompilationMono / IL2CPPBurst Compiler (SIMD natif)
Cas d'usageGameplay scripté, UI, niveauxBoids, RTS, simulations massives
Courbe d'apprentissageFacileRaide (debugger limité)

💡 Conseils pro

  • Commence en MonoBehaviour, migre en ECS uniquement les systèmes critiques (projectiles, foules).
  • Active toujours l'option Project Settings > Player > Configuration > Scripting Backend = IL2CPP pour les builds release (perf + sécurité).
  • Range les scripts dans des Assembly Definitions (.asmdef) pour réduire le temps de compilation de 30 s à 3 s.
  • Active Burst Inspector pour vérifier que ton code ECS est bien vectorisé en SIMD.

⚠️ Pièges à éviter

  • Ne jamais utiliser FindObjectOfType ou GameObject.Find dans Update : O(n) sur toute la scène, killer de perf.
  • Ne pas instancier/détruire des objets en boucle sans object pooling (réutilisation) : GC alloc = stutter.
  • Toujours désabonner les events C# (-= OnEvent) dans OnDestroy : sinon memory leak garanti.
  • L'ECS n'est pas toujours plus rapide : pour 100 objets, le MonoBehaviour reste plus simple et suffisant.

Approfondissement technique

Le passage à Unity 6 redéfinit la frontière entre CPU et GPU grâce au GPU Resident Drawer et à la consolidation du stack DOTS. Là où l'architecture historique MonoBehaviour traitait chaque objet de la scène comme une instance C# autonome (avec son cycle de vie, son overhead managé et sa cache miss à chaque Update()), Unity 6 propose un modèle data-oriented où les composants sont stockés en mémoire contiguë par archetype dans des chunks de 16 KB. Cette organisation permet au Burst Compiler (basé sur LLVM) de générer du code SIMD natif AVX2 ou ARM NEON, multipliant les performances par 10 à 50 sur les boucles serrées de gameplay, de physique custom ou d'IA de foule. Le coût d'apprentissage est réel : il faut accepter de manipuler des IComponentData, des SystemBase, et de penser en transformations par batch plutôt qu'en méthode Update() par GameObject.

Sur le plan rendering, Unity 6 unifie enfin les deux pipelines modernes URP (Universal Render Pipeline) et HDRP (High Definition Render Pipeline) autour d'une couche commune appelée Scriptable Render Pipeline (SRP) Core. URP cible mobile, WebGL, consoles d'entrée et VR autonome (Quest 3, Vision Pro) avec un budget de 4 à 8 ms par frame. HDRP cible PC haut de gamme, PS5, Xbox Series X et offre le path tracing temps réel, le subsurface scattering, les volumetric clouds et la GI avec APV (Adaptive Probe Volumes). Le choix du pipeline est irréversible en pratique : changer URP→HDRP en cours de production casse tous les shaders, tous les matériaux et tous les VFX Graphs. Une étude de marché en amont (plateforme cible, budget GPU, équipe artistique) est donc cruciale.

Burst Compiler et Jobs System en détail

Le Job System distribue les calculs sur les cœurs CPU via un thread pool managé par Unity. Un IJob classique exécute une tâche unitaire, un IJobParallelFor partitionne automatiquement un tableau de N éléments en sous-tâches confiées à autant de workers que de cœurs logiques. Le JobHandle permet d'établir des dépendances acycliques entre jobs (job B attend job A) avec un coût quasi nul. Couplé à Burst, ce système permet par exemple de simuler 100 000 ennemis IA sur une boucle de pathfinding en 1,2 ms sur un Ryzen 7 5800X, là où un MonoBehaviour classique demanderait 35 ms. Les règles d'or : pas de référence à des types managés (string, classe, GameObject) dans un job, utilisation exclusive de NativeArray<T> et NativeList<T>, structures unsafe autorisées si [BurstCompile] est appliqué, désactivation des Safety Checks en build release pour gagner 30 % supplémentaires.

Le GPU instancing tire parti d'une instruction unique de draw pour rendre des milliers d'objets identiques (matériau identique, mesh identique) en variant simplement la matrice de transformation. Unity 6 généralise ce mécanisme avec BatchRendererGroup et GPU Resident Drawer : les transforms vivent désormais en VRAM, la CPU n'a plus à pousser les données à chaque frame, et le rendu de 50 000 props (rochers, arbres, débris) tient en 2 ms GPU sur une RTX 4070. Pour exploiter pleinement ce gain il faut activer GPU instancing sur chaque matériau, utiliser des MaterialPropertyBlock pour les variations légères, et bannir les matériaux uniques par objet (un piège fréquent : modifier renderer.material à chaud crée une instance non batchable).

ScriptableRenderPipeline, Addressables et profilage

La Scriptable Render Pipeline (SRP) permet d'écrire son propre pipeline de rendu en C# en exploitant les RenderPass, RendererFeatures (URP) et CustomPasses (HDRP). Cas concret : ajouter un outline post-process pour un jeu cel-shaded demande 60 lignes de C# en URP via un ScriptableRendererFeature, contre 800 lignes et un fork complet du built-in pipeline historique. Les RenderGraph (intégré en Unity 6) optimisent automatiquement l'allocation des RenderTargets temporaires en analysant le graphe de passes, réduisant la bande passante mémoire de 40 % typique sur mobile.

Les Addressables remplacent l'ancien AssetBundle avec une API unifiée pour le streaming, l'over-the-air content, et le packaging multi-plateforme. Un asset référencé par AssetReference est chargé à la demande via Addressables.LoadAssetAsync<Texture2D>("hero/portrait"), le système gère le caching disque, la dépendance entre bundles, la CRC de vérification et le téléchargement CDN. Pour un MMO ou un live-ops, on déploie typiquement 2-5 GB d'assets via Addressables pour rester sous la limite store de 2 GB d'APK Android.

Le Unity Profiler moderne (Unity 6) intègre 4 modules essentiels : CPU Usage (timeline microseconde par thread), GPU Usage (timing par drawcall via API capture), Memory Profiler (snapshot des allocations managées et natives), Frame Debugger (replay frame par frame avec inspection des shader passes). Un workflow efficace consiste à profiler sur device cible (jamais sur l'Editor qui ment), à activer les Deep Profile uniquement sur les frames suspectes, et à fixer un budget par sous-système (16 ms = 8 ms gameplay + 4 ms physique + 3 ms rendu + 1 ms audio).

Cas pratiques détaillés

✏️ Cas 1 — Système de buff stackable en DOTS/ECS

Un RPG doit gérer 5 000 ennemis avec un buff de régénération qui se cumule (DoT inversé). En MonoBehaviour classique, chaque ennemi fait son Update() et accumule du retard. En ECS pur, on crée un HealthRegenComponent et un système qui parcourt l'archetype en SIMD :

using Unity.Burst;
using Unity.Entities;
using Unity.Mathematics;

public struct HealthData : IComponentData { public float current; public float max; }
public struct HealthRegen : IComponentData { public float perSecond; public float duration; }

[BurstCompile]
public partial struct RegenSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        float dt = SystemAPI.Time.DeltaTime;
        foreach (var (health, regen) in
                 SystemAPI.Query<RefRW<HealthData>, RefRW<HealthRegen>>())
        {
            health.ValueRW.current = math.min(health.ValueRO.max,
                health.ValueRO.current + regen.ValueRO.perSecond * dt);
            regen.ValueRW.duration -= dt;
        }
    }
}

✏️ Cas 2 — Drawer instancié pour 10 000 herbes via GPU Resident Drawer

On veut faire pousser un champ d'herbe sans tuer le framerate Quest 3. La solution : un seul mesh + un matériau GPU-instanced + un buffer de transforms.

public class GrassField : MonoBehaviour
{
    public Mesh bladeMesh;
    public Material grassMat;
    public int count = 10000;
    private Matrix4x4[] matrices;
    private MaterialPropertyBlock mpb;

    void Start()
    {
        matrices = new Matrix4x4[count];
        mpb = new MaterialPropertyBlock();
        for (int i = 0; i < count; i++) {
            Vector3 p = new Vector3(Random.Range(-50f, 50f), 0, Random.Range(-50f, 50f));
            Quaternion r = Quaternion.Euler(0, Random.Range(0, 360f), 0);
            matrices[i] = Matrix4x4.TRS(p, r, Vector3.one);
        }
    }

    void Update()
    {
        Graphics.DrawMeshInstanced(bladeMesh, 0, grassMat, matrices, count,
                                   mpb, UnityEngine.Rendering.ShadowCastingMode.Off);
    }
}

Comparaison et benchmark

ApprochePerformance (10k entités)ComplexitéCas d'usage
MonoBehaviour Update~28 ms CPU★☆☆☆☆Prototypage, équipe junior
MonoBehaviour + Object Pool~18 ms CPU★★☆☆☆Mobile casual, FPS classique
Job System (sans Burst)~6 ms CPU★★★☆☆IA modérée, multi-thread simple
Job System + Burst~1,3 ms CPU★★★★☆Simulation physique custom
ECS + Burst + Jobs~0,8 ms CPU★★★★★RTS, foule, MMO, projectiles massifs
GPU Compute (HLSL)~0,2 ms GPU★★★★★Particules, fluides, foule purement visuelle
GPU Resident Drawer~50k props @ 2 ms★★★☆☆Vegetation, débris, open world

Pièges fréquents en production

  • GC spikes dus à foreach sur List<T> en hot path : préférer for (int i = 0; i < list.Count; i++) ou passer en NativeArray.
  • Draw call explosion car chaque renderer.material instancié casse le batching : utiliser MaterialPropertyBlock et un matériau partagé.
  • Memory leaks sur scène additive : Scene.UnloadAsync ne libère pas les Addressables instanciés, il faut Addressables.ReleaseInstance(go) explicitement.
  • Frame drops mobile lors d'un Resources.Load en cours de gameplay : pré-charger tout avec Addressables au démarrage de niveau.
  • Profiler menteur en Editor : toujours profiler sur device cible (le JIT mono de l'Editor masque les vrais coûts du IL2CPP build).
  • Cinemachine et input new system : un CinemachineFreeLook ne lit pas l'Input System par défaut, il faut activer Cinemachine.Input Provider sinon la caméra reste figée.
  • ECS et UI Toolkit ne se parlent pas : l'UI vit côté managé classique, un pont via EntityManager + SystemAPI.GetSingleton est nécessaire.
  • WebGL build : pas de threads en WebAssembly classique, donc pas de Job System actif — concevoir un fallback single-thread dès le départ.

Outils et écosystème

  • Cinemachine 3.x — virtual cameras, blends, dolly, FreeLook, impulse listener (caméra cinématique en 30 minutes).
  • DOTween Pro — tweening engine ultra-léger, animation procédurale UI/transforms en 1 ligne (asset store, 15 USD).
  • Odin Inspector & Serializer — supercharge l'Inspector (dictionnaires sérialisés, attributs métier, validators) ; 55 USD/siège, indispensable studio.
  • FMOD Studio — audio middleware (gratuit < 200k USD revenu) avec routing complexe, snapshots, parameters live.
  • Wwise (Audiokinetic) — concurrent FMOD haut de gamme, free tier < 200k USD, certifié toutes consoles.
  • Photon Fusion 2 — netcode authoritative avec prediction/rollback intégré, alternative moderne à PUN.
  • Quixel Megascans — bibliothèque de 16 000 assets photoscan PBR, gratuit via Epic mais utilisable Unity via bridge.

Citations sources officielles

"Burst compiles a subset of C# to highly optimized native code using the LLVM compiler framework. Burst is particularly suited for code where you need to do a lot of math (Mathematics, Physics) on a lot of data (Collections, ECS)." — docs.unity3d.com — Burst manual
"DOTS (Data-Oriented Technology Stack) is a combination of technologies and packages that delivers a data-oriented approach to writing code. Together, these technologies offer better performance and improved iteration times." — unity.com/dots

Glossaire (10 termes)

TermeDéfinition
Draw callCommande envoyée à l'API graphique (Vulkan, Metal, DX12) pour dessiner un mesh — coût CPU + setup GPU non négligeable.
BatchingRegroupement de plusieurs meshes partageant le même matériau en un seul draw call (static, dynamic, SRP batcher, GPU instancing).
LOD (Level of Detail)Mesh simplifié activé en fonction de la distance caméra — économise polygones et bande passante GPU.
Occlusion cullingÉlimination par le moteur des objets cachés par d'autres (PVS pré-calculé ou GPU-driven occlusion).
PBR (Physically Based Rendering)Modèle de matériau basé sur albédo, métallique, roughness, normal, AO — standard depuis 2014.
Normal mapTexture encodant les normales d'une surface — simule des détails géométriques sans ajouter de polygones.
LightmapTexture pré-calculée stockant l'éclairage statique d'une scène — économise les calculs runtime.
MRT (Multiple Render Targets)Écriture simultanée de plusieurs textures par un shader (G-Buffer du deferred shading).
Forward vs DeferredForward = un shader par objet (rapide, peu de lumières) ; Deferred = G-buffer + lighting pass (scalable à 100+ lumières).
Archetype (ECS)Combinaison unique de composants définissant un layout mémoire — stockage par chunk de 16 KB.

Ressources d'approfondissement

Continuez le parcours 🚀

La leçon suivante est également gratuite. Découvrez-la sans inscription.

Leçon 2 — Continuer →
🍪 Nous utilisons des cookies essentiels et, avec ton accord, des cookies analytiques. En savoir plus

⚙️ Préférences cookies

Choisis quels cookies tu acceptes — modifiable à tout moment.

🔐 Essentiels (obligatoires)Authentification, session, sécurité. Toujours actifs.
📊 Analytics anonymesMesure d'audience anonymisée — aucune donnée personnelle.
📣 MarketingPublicités ITAG pertinentes sur d'autres sites.
💬 Contactez-nous sur WhatsApp