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

Unity Physics, Animation, Audio, UI, Netcode for GameObjects

⏱ 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 2 — Unity Physics, Animation, Audio, UI et Netcode

Construire un jeu complet avec physique réaliste, animations fluides, son immersif, UI moderne et multijoueur en réseau via Unity Netcode for GameObjects.

🎯 Objectifs pédagogiques

  • Configurer Rigidbody + Collider et utiliser Raycasts, Layers et Physics.OverlapSphere.
  • Maîtriser l'Animator Unity : state machines, blend trees, transitions, paramètres.
  • Mettre en place une Timeline cinématique et un IK rig (Inverse Kinematics) sur un personnage.
  • Intégrer du son spatial (AudioSource 3D, AudioMixer, snapshots) et déléguer à FMOD/Wwise pour la prod AAA.
  • Construire une UI moderne avec UI Toolkit (UXML+USS) et l'ancienne uGUI.
  • Implémenter un mode multijoueur via Unity Netcode for GameObjects + Relay + Lobby.

1. Physique Unity — Rigidbody, Colliders, Raycasts

Le moteur physique d'Unity repose sur PhysX (NVIDIA) pour la 3D et Box2D pour la 2D. Un objet acquiert un comportement physique en ajoutant un Rigidbody (3D) ou Rigidbody2D ; sa forme de collision est définie par un Collider (Box, Sphere, Capsule, Mesh). Les paramètres clés : mass (kg), drag (résistance air linéaire), angular drag (rotation), useGravity, isKinematic (ignore les forces, pilotable par script).

Les Layers (32 max) permettent de filtrer ce qui collide avec quoi (matrice Physics > Layer Collision Matrix). Exemple : la layer Player ignore Pickup mais collide avec Wall. Les Raycasts projettent un rayon depuis un point dans une direction et retournent le premier hit : indispensable pour le tir, la détection de sol, la sélection à la souris.

✏️ Code C# — Raycast tir + Coroutine

using System.Collections;
using UnityEngine;

public class WeaponShooter : MonoBehaviour
{
    [SerializeField] private float fireRate = 0.2f;
    [SerializeField] private float range = 100f;
    [SerializeField] private int damage = 25;
    [SerializeField] private LayerMask hitMask;
    [SerializeField] private ParticleSystem muzzleFlash;
    private bool canFire = true;

    void Update()
    {
        if (Input.GetButton("Fire1") && canFire)
            StartCoroutine(FireBullet());
    }

    IEnumerator FireBullet()
    {
        canFire = false;
        muzzleFlash.Play();

        if (Physics.Raycast(transform.position, transform.forward, out RaycastHit hit, range, hitMask))
        {
            Debug.DrawLine(transform.position, hit.point, Color.red, 1f);
            var enemy = hit.collider.GetComponent<Enemy>();
            if (enemy != null) enemy.TakeDamage(damage);
        }

        yield return new WaitForSeconds(fireRate);
        canFire = true;
    }
}

Coroutine : fonction qui peut suspendre son exécution via yield return. Idéale pour timer, animation, séquence d'actions sans bloquer le thread principal.

2. Animator : state machines et blend trees

Le composant Animator exécute un Animator Controller (.controller), c'est-à-dire une state machine visuelle où chaque état est un clip d'animation (Idle, Walk, Run, Jump, Death). Les transitions entre états sont conditionnées par des paramètres typés (Float, Int, Bool, Trigger). Exemple : transition Idle→Walk si Speed > 0.1. Les Sub-State Machines regroupent plusieurs états (ex : Combat = Attack1+Attack2+Block).

Le Blend Tree mélange plusieurs clips selon un ou deux paramètres : un Blend Tree 2D (X = speed, Y = direction) permet à un personnage de marcher dans 8 directions à partir de 8 clips, avec interpolation fluide. C'est la base de l'animation moderne 3D.

✏️ Code C# — Pilotage Animator

public class CharacterAnimator : MonoBehaviour
{
    private Animator anim;
    private static readonly int Speed = Animator.StringToHash("Speed");
    private static readonly int JumpTrigger = Animator.StringToHash("Jump");

    void Awake() { anim = GetComponent<Animator>(); }

    public void UpdateMovement(float speed) {
        anim.SetFloat(Speed, speed, 0.1f, Time.deltaTime); // damping 0.1s
    }

    public void TriggerJump() { anim.SetTrigger(JumpTrigger); }
}

Note perf : Animator.StringToHash convertit une string en int au démarrage. Toujours utiliser le hash dans Update (10× plus rapide que la string).

3. Timeline et IK — cinématiques et personnages réalistes

La Timeline (Window > Sequencing > Timeline) permet de séquencer cinématiques : pistes Animation, Audio, Activation (GameObject on/off), Control (Sub-Timeline) et Signals (events). Idéale pour cutscenes et tutoriels interactifs. L'Inverse Kinematics (IK) calcule la position des os intermédiaires (coude, genou) à partir d'une cible (main, pied). Activé via Animator > IK Pass et le hook OnAnimatorIK(). Le package Animation Rigging ajoute des constraints visuels (Two Bone IK, Multi-Aim, Chain IK) pour ajuster une animation à un objet du monde (poser la main sur une poignée, viser un ennemi).

4. Audio : AudioSource, AudioMixer, FMOD, Wwise

Un AudioSource attaché à un GameObject lit un AudioClip en 2D (UI, musique) ou 3D (positionnel, atténuation distance). L'AudioMixer permet de router les sources dans des groupes (Music, SFX, Voice) avec effets DSP (lowpass, reverb, compressor) et de gérer le volume global via Snapshots (Combat = ducking music, Menu = music up). En production AAA, FMOD Studio et Audiokinetic Wwise remplacent l'audio Unity natif : workflow audio designer dédié, events paramétriques, occlusion temps réel, profilage mémoire. FMOD intégration via le package gratuit fmod.com/unity.

5. UI : UI Toolkit (UXML/USS) vs uGUI

uGUI (Unity GUI, depuis 2014) est l'ancien système : composants Canvas, Image, Text, Button posés dans la scène. Simple mais coûteux (drawcalls élevés, layout en CPU). UI Toolkit (depuis Unity 2021, stable Unity 6) est le successeur inspiré du web : description en UXML (HTML-like) + style en USS (CSS-like) + binding C#. Avantages : 10× plus performant, hot-reload des styles, layout flexbox. UI Toolkit est désormais recommandé pour toute nouvelle UI runtime.

CritèreuGUI (legacy)UI Toolkit (Unity 6)
DescriptionScène + GameObjectsUXML + USS + C#
PerformanceMoyenne (drawcalls)Élevée (batched)
LayoutAnchors + Layout GroupFlexbox CSS
Hot-reloadNonOui (USS)
Recommandé pourProjets legacyTous nouveaux projets

6. Multijoueur : Netcode for GameObjects + Relay + Lobby

Unity Netcode for GameObjects (NGO, ex-MLAPI) est le framework officiel multijoueur depuis 2021. Architecture client-host ou dedicated server avec NetworkObject (spawn synchronisé), NetworkVariable<T> (variables auto-synchronisées) et RPC (ServerRpc, ClientRpc). Le service Unity Relay (Unity Gaming Services, freemium) permet le NAT punch-through gratuit pour 100 CCU. Unity Lobby gère matchmaking, codes de room, données joueurs. Pour des jeux compétitifs (FPS, MOBA), préférer une architecture dedicated server sur Unity Multiplay Hosting ou Edgegap.

"Netcode for GameObjects is built to be extensible and to scale. It works for casual co-op and competitive shooters alike." — docs.unity3d.com/Packages/com.unity.netcode.gameobjects

💡 Conseils pro

  • Active Multiplayer Tools (package gratuit) pour profiler la bande passante en Editor.
  • Pour le mobile, désactive l'AudioReverbZone par défaut (gros CPU sur Android low-end).
  • L'Animator est plus coûteux que tu ne le crois (~0,5 ms par perso) : désactive-le hors écran via Cullinng Mode.
  • Préfère FMOD Studio dès qu'il y a plus de 50 sons : un audio designer non-dev peut bosser sans toi.

⚠️ Pièges à éviter

  • Ne jamais utiliser Rigidbody.AddForce dans Update : toujours dans FixedUpdate (sinon comportement physique aléatoire).
  • Sur mobile, attention aux MeshColliders non-convex : très coûteux. Préférer Box/Sphere/Capsule.
  • Un NetworkVariable qui change chaque frame inonde le réseau : interpoler côté client + ne synchroniser qu'à 20 Hz max.
  • Ne mets jamais d'audio non compressé (WAV) en build : utilise Vorbis/MP3 (Inspector > Compression Format).

Approfondissement technique

La couche physique et la couche animation d'Unity sont deux sous-systèmes coûteux qui partagent une caractéristique fondamentale : elles tournent à fréquence fixe (FixedUpdate à 50 Hz par défaut pour la physique, Animator évalué à chaque frame de rendu) et leur découplage avec le Update gameplay est source des bugs les plus subtils en production. Comprendre quand un événement se produit dans le pipeline est aussi important que comprendre quoi il produit. Le Script Execution Order (Edit → Project Settings → Script Execution Order) permet de prioriser un script critique (par exemple un Camera Follow doit s'exécuter en LateUpdate après le mouvement physique du joueur, sinon la caméra tremble d'une frame).

Côté netcode, Unity propose désormais deux solutions officielles : Netcode for GameObjects (NGO) pour les projets clé en main avec composants NetworkBehaviour, et Netcode for Entities pour les projets DOTS où la performance prime. Une troisième voie communautaire, Mirror, reste populaire pour les projets indé : fork de l'ancien UNet, compatible Unity 6, communauté active de 12 000 développeurs sur Discord. Le choix dépend du modèle topologique : authoritative server (FPS compétitif, MMO), client-host listen server (coop 2-8 joueurs), ou peer-to-peer (jeu de stratégie tour par tour). Aucun moteur ne résout magiquement la latence : la conception du gameplay (input delay caché, animation de feedback, sound buffer) reste responsabilité du designer.

Animation Rigging et IK

Le package Animation Rigging apporte à Unity ce que MotionBuilder offre depuis 2003 : la possibilité de superposer des contraintes IK (Inverse Kinematics) sur une animation existante. Concrètement, un personnage qui tient une arme verra sa main gauche s'aligner dynamiquement sur la poignée de l'arme même si l'animation source a été faite pour une autre arme — un seul TwoBoneIKConstraint entre épaule-coude-poignet, target sur le grip de l'arme, et le runtime résout en temps réel. Les contraintes disponibles sont nombreuses : Damped Transform (suivi avec amortissement), Multi-Aim (la tête regarde une cible), Multi-Parent (swap d'objet attaché), Override Transform (force une position). Ce système est utilisé en production AAA chez Naughty Dog et Insomniac pour superposer des animations procédurales sur des clips capturés en mocap.

Le NavMesh reste la solution standard pour le pathfinding. Le NavMesh Surface permet désormais de générer la navmesh à runtime (dynamique pour les niveaux procéduraux), et les NavMesh Modifiers permettent d'exclure ou de réétiqueter des zones (escaliers, eau, falaises). Un NavMesh Agent avec updatePosition = false et updateRotation = false permet de récupérer juste le path calculé pour appliquer son propre déplacement (cinematic precision, root motion). Pour les jeux RTS où l'on déplace 200 unités, basculer sur A* Pathfinding Project Pro (asset store, 100 USD) reste plus performant car il offre du flowfield et du multi-thread, là où NavMesh est limité à 1 thread.

Cloth, Mirror vs NGO, lag compensation

Le composant Cloth (PhysX cloth) simule un tissu via un mailmesh de particules connectées par springs. Coût CPU : 0,3 à 1,2 ms par cape sur PC, prohibitif sur mobile. Pour un personnage avec cape, robe et cheveux flottants, on dépasse vite les 4 ms : la production AAA préfère désormais les bone chains avec contraintes Dynamic Bone (asset store) ou Magica Cloth 2 (75 USD) qui tournent en jobs multi-thread Burst-compiled.

Mirror vs Netcode for GameObjects (NGO) : Mirror offre une API plus mature et une licence MIT permissive, NGO est officiellement supportée par Unity avec roadmap publique. Sur 5 000 objets répliqués, Mirror tient 60 FPS avec snapshot interpolation, NGO tombe à 35 FPS sans optimisations manuelles (subnet de pertinence, batch size, custom serializer). Pour un jeu coop 4 joueurs, NGO suffit largement. Pour un MMO 100+ joueurs, considérer Photon Fusion 2 (rollback netcode, prediction) ou Unity Multiplayer Services + Game Server Hosting.

La lag compensation consiste à rejouer côté serveur l'état du monde au moment où le client a tiré (typiquement RTT/2 = 50 ms en arrière). C'est ce qui permet à un joueur à 100 ms de ping de toucher une cible avec un hitscan. L'implémentation nécessite de garder un historique circulaire des hitboxes (10-20 frames) côté serveur. Le piège classique : un joueur peut se tuer derrière un mur car son écran montre l'ennemi à découvert (déjà rentré en couverture côté serveur) — c'est le fameux "shot around corner" qui rage les joueurs CS et Valorant.

Cas pratiques détaillés

✏️ Cas 1 — Tir authoritative avec lag compensation côté serveur (NGO)

Un FPS coop veut empêcher le cheat tout en restant snappy. Le client envoie l'input, le serveur rejoue la hitbox cible à serverTick - clientRTT/2.

using Unity.Netcode;
using UnityEngine;

public class WeaponServer : NetworkBehaviour
{
    [ServerRpc]
    public void FireServerRpc(Vector3 origin, Vector3 dir, float clientTick)
    {
        // Re-simulate hitbox states at the client's perceived time
        float lagMs = (NetworkManager.ServerTime.Time - clientTick) * 1000f;
        var snapshot = HitboxHistory.GetClosest(clientTick);
        snapshot.Apply(); // teleport hitboxes in past pose

        if (Physics.Raycast(origin, dir, out var hit, 200f, LayerMask.GetMask("Hitbox")))
        {
            var target = hit.collider.GetComponentInParent<HealthSync>();
            target?.TakeDamageServer(25);
        }
        snapshot.Restore(); // teleport back to present
    }
}

✏️ Cas 2 — IK procédural pour pied posé sur escalier

Un personnage monte un escalier dont la hauteur de marche varie. L'animation walk_cycle est plate, mais on veut que les pieds touchent réellement chaque marche.

using UnityEngine;
using UnityEngine.Animations.Rigging;

[RequireComponent(typeof(Animator))]
public class FootIKAdjust : MonoBehaviour
{
    public TwoBoneIKConstraint leftFootIK;
    public TwoBoneIKConstraint rightFootIK;
    public LayerMask groundMask;
    public float rayHeight = 1.5f;

    void OnAnimatorIK()
    {
        AdjustFoot(leftFootIK, HumanBodyBones.LeftFoot);
        AdjustFoot(rightFootIK, HumanBodyBones.RightFoot);
    }

    void AdjustFoot(TwoBoneIKConstraint ik, HumanBodyBones bone)
    {
        Animator anim = GetComponent<Animator>();
        Vector3 footPos = anim.GetBoneTransform(bone).position;
        if (Physics.Raycast(footPos + Vector3.up * rayHeight, Vector3.down,
                            out var hit, rayHeight + 0.5f, groundMask))
        {
            ik.data.target.position = hit.point + Vector3.up * 0.07f;
            ik.weight = 1f;
        }
        else ik.weight = 0f;
    }
}

Comparaison et benchmark

Approche netcodeLatence ressentieAnti-cheatCas d'usage
Peer-to-peer relayFaible si proche★☆☆☆☆Coop 2 joueurs, jeu de table
Listen server (client-host)0 ms hôte, RTT clients★★☆☆☆Coop 4-8, hôte = ami
Dedicated serverRTT uniform★★★★☆FPS compétitif, MMO
NGO snapshot interp~100 ms perçu★★★☆☆Coop, MMO casual
Photon Fusion rollback~16 ms perçu★★★★☆Fighting, FPS rapide
Mirror authoritative~80 ms perçu★★★☆☆Indé MMO, RTS
WebRTC data channelRTT brut★☆☆☆☆Web HTML5, navigateur

Pièges fréquents en production

  • Physics.SyncTransforms désactivé par défaut : un Rigidbody.MovePosition suivi d'un Raycast dans la même frame peut retourner l'ancienne position — appeler Physics.SyncTransforms() explicitement.
  • Animator Override Controller qui casse les events : les animation events définis sur le clip original ne se déclenchent plus, il faut les redéfinir sur l'override.
  • NavMeshAgent qui glisse : si updatePosition = true et qu'une animation root motion est active, conflit garanti — désactiver l'un des deux.
  • NGO ClientNetworkTransform non-authoritative qui se fait téléporter par le serveur : utiliser NetworkTransform standard ou OwnerAuthoritative avec validation server-side.
  • Cloth qui explose au premier Time.timeScale = 0 puis reprise : appeler cloth.ClearTransformMotion() avant reprise.
  • UI Toolkit + Input System : les inputs ne se propagent pas automatiquement si un EventSystem classique est dans la scène — utiliser InputSystemUIInputModule.
  • Audio listener multiple : 2 AudioListener dans la même scène → "Warning: Multiple AudioListeners" et son spatial cassé.
  • FixedUpdate jitter sur faible FPS : passer en Interpolation = Interpolate sur les Rigidbody visibles.

Outils et écosystème

  • Animancer Pro — alternative scriptée à Animator Controller (asset store, 90 USD) ; supprime le besoin de state machine visuelle.
  • Final IK (RootMotion) — IK le plus complet du marché (FBBIK, LimbIK, AimIK), 90 USD, utilisé par Cyberpunk modders.
  • Photon Fusion 2 — rollback netcode, tick rate 60 Hz, gratuit jusqu'à 20 CCU.
  • Steam Networking Sockets — relay P2P gratuit via Steamworks, NAT-punchthrough automatique.
  • Magica Cloth 2 — cloth Burst-compiled, 75 USD, 10× plus rapide que PhysX cloth sur mobile.
  • FMOD Studio + plugin Unity intégré (snapshots, parameters, occlusion).
  • Mirror Networking + extension Edgegap (host dedicated server par région automatique).

Citations sources officielles

"Netcode for GameObjects is a high-level networking library built for Unity for you to abstract networking logic. It enables you to send GameObjects and world data across a networking session to many players at once." — docs-multiplayer.unity3d.com
"Animation Rigging lets you create and organize sets of constraints based on C# Animation Jobs to address different requirements related to animation rigging." — docs.unity3d.com — Animation Rigging

Glossaire (10 termes)

TermeDéfinition
FixedUpdateMéthode appelée à fréquence fixe (50 Hz par défaut) pour les calculs physiques déterministes.
Root motionDéplacement du personnage piloté par l'animation elle-même (et non par le script).
IK (Inverse Kinematics)Calcul des rotations d'os pour atteindre une position cible (target).
NavMeshMaillage de navigation pré-calculé pour le pathfinding A*.
Snapshot interpolationTechnique réseau qui interpole entre 2 états reçus du serveur pour lisser le mouvement.
Client predictionLe client simule localement le résultat de son input avant la confirmation serveur.
Server reconciliationQuand le serveur diverge du client, on rejoue les inputs depuis le dernier état confirmé.
RTT (Round Trip Time)Temps aller-retour client-serveur ; latence ressentie = RTT/2 + buffer.
Tick rateFréquence à laquelle le serveur simule le monde (20-128 Hz selon le jeu).
Snapshot deltaEnvoi par le serveur uniquement des champs modifiés depuis le snapshot précédent (économie bande passante).

Ressources d'approfondissement

Continuez le parcours 🚀

Inscrivez-vous pour accéder aux 5 autres leçons + le quiz final.

Créer mon compte
🍪 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