Une introduction technique à l'architecture brute de Unity ML-Agents.
Comprendre le code C# derrière le comportement.
ML-Agents est une symbiose asynchrone (gRPC) entre deux univers distincts.
Simulation 3D
Physique & Avatar
Réseau de neurones
Algorithme PPO
Le script Python (le Cerveau) écoute sur un port réseau. Unity (le Corps) s'y connecte, lui envoie ses observations et reçoit ses actions à chaque décision : dans le labo du colibri, une décision toutes les cinq trames de physique, dix fois par seconde.
Dans le labo Sorti du nid, voici la taille réelle de l'esprit qu'on fabrique.
Le processus fonctionne par Épisodes. Quand l'Agent réussit ou meurt, l'univers doit être réinitialisé. C'est le Big Bang de OnEpisodeBegin.
public override void OnEpisodeBegin()
{
// Réinitialiser la position de l'Agent
this.transform.localPosition = Vector3.zero;
// Réinitialiser la physique (Unity 6 : linearVelocity, plus velocity)
rigidbody.linearVelocity = Vector3.zero;
// Placer la cible (le nectar) aléatoirement
DeplacerCible();
}
L'IA Python est aveugle. CollectObservations traduit la réalité 3D en un tableau de nombres (floats) : c'est le vecteur sensoriel.
public override void CollectObservations(VectorSensor sensor)
{
// J'observe ma propre position (3 floats : X, Y, Z)
sensor.AddObservation(this.transform.localPosition);
// J'observe la position de mon objectif (3 floats)
sensor.AddObservation(target.localPosition);
// Taille totale de l'Input neuronal : 6 floats.
}
Le colibri n'observe jamais sa position absolue : sa rotation (4), un vecteur normalisé vers la fleur la plus proche (3), deux produits scalaires qui disent s'il est devant la fleur et s'il la vise (2), la distance relative (1). Dix nombres, plus trois capteurs à rayons pour les obstacles.
L'IA envoie ses décisions. L'Agent les exécute physiquement dans OnActionReceived et distribue la punition ou la récompense (Reward).
public override void OnActionReceived(ActionBuffers actions)
{
// 1. Exécuter l'action physique (voler, avancer)
float force = actions.ContinuousActions[0];
AppliquerForce(force);
// 2. Jugement (Le renforcement)
if (A_Touche_Un_Mur) {
SetReward(-1f); // Douleur fatale
EndEpisode(); // Mort -> Déclenche OnEpisodeBegin
} else if (A_Bu_Le_Nectar) {
SetReward(1f); // Extase absolue
EndEpisode();
}
}
Pour débugger la physique de l'Agent avant d'y connecter l'Intelligence Artificielle, l'Ingénieure utilise Heuristic pour le contrôler manuellement.
public override void Heuristic(in ActionBuffers actionsOut)
{
// Remplacer les actions de l'IA par le clavier de l'Ingénieure (Input System d'Unity 6)
var actions = actionsOut.ContinuousActions;
var clavier = Keyboard.current;
actions[0] = clavier.dKey.isPressed ? 1f : clavier.aKey.isPressed ? -1f : 0f;
actions[1] = clavier.wKey.isPressed ? 1f : clavier.sKey.isPressed ? -1f : 0f;
}
Behavior Type = Heuristic Only dans l'inspecteur, puis Play : si le corps répond au clavier, le cerveau pourra le piloter.
Après quelques millions de pas accélérés (deux millions en une heure sur un portable, dans notre test), le script Python mlagents-learn compresse tout ce que l'agent a appris dans un fichier de 300 ko : un modèle .onnx.
Ce cerveau autonome, fruit de ton architecture, est alors prêt à être inséré dans Unity, où Inference Engine le fait tourner sans Python.
Tout ce qui précède se construit en une séance de labo : trois scripts, une scène à configurer, un entraînement à lancer, un cerveau à donner à l'oiseau.