Tester son gameplay
Quand des développeurs arrivent du web ou du logiciel d'entreprise vers le modding de jeux vidéo, ils débarquent souvent avec des réflexes scolaires : il faut écrire des tests unitaires automatisés pour chaque fonctionnalité avant même de lancer le jeu.
Puis ils ouvrent Visual Studio, essaient d'instancier un Ped ou d'appeler Game.Player, et se prennent un mur immédiat : NullReferenceException. Hors du processus actif de GTA V, le moteur n'existe tout simplement pas. Il n'y a ni contexte de rendu DirectX, ni pools de mémoire, ni tables de natives, ni simulateur physique.
Si tu décortiques le code source des mods les plus réputés de la communauté, de Los Santos RED à InteractV, tu ne trouveras aucun projet de test xUnit pour les mécaniques de jeu. Les vrais créateurs de mods testent leur travail différemment.
Pourquoi les tests classiques échouent sur le gameplay
Un test unitaire traditionnel compare une valeur attendue avec un retour de fonction :
Assert.Equal(expected, actual);
Cette assertion fonctionne très bien pour valider le calcul d'une remise ou parser une adresse email. Elle devient inutile dans un monde ouvert :
- Un test unitaire ne peut pas te dire si une animation semble naturelle ou si le PNJ s'encastre dans une barrière.
- Un test unitaire ne peut pas mesurer si un rayon de menace de huit mètres crée une vraie tension ou s'il agace le joueur.
- Un test unitaire ne peut pas prouver qu'un piéton va contourner un poteau plutôt que de courir contre un mur.
Le feeling physique d'un jeu doit se vivre directement à l'intérieur du moteur.
La boîte à outils du moddeur : knobs et overlays
Au lieu de s'enfermer dans des suites de tests déconnectées, les moddeurs d'expérience construisent leurs propres instruments de mesure directement dans GTA V :
- Les knobs de réglage : Des paramètres chargés depuis un fichier
.iniou JSON que tu peux modifier à chaud, pour ajuster tes distances et tes délais sans devoir recompiler. - Les touches de dev : Des raccourcis clavier dédiés (comme
F10ouInsert) pour déclencher un scénario d'épreuve, faire apparaître un ennemi de test ou forcer un changement d'état. - Les overlays visuels de debug : Des sous-titres à l'écran ou des marqueurs 3D dans le monde qui affichent en temps réel ce que le script est en train de décider.
Voici une instrumentation concrète en jeu qui affiche directement à l'écran les décisions de notre machine à états :
using System;
using System.Windows.Forms;
using GTA;
public sealed class GameplayTestingScript : Script
{
private readonly EncounterEvaluator _evaluator = new EncounterEvaluator();
private EncounterState _currentState = EncounterState.Calm;
private bool _showDebugOverlay = true;
public GameplayTestingScript()
{
Tick += OnTick;
KeyDown += OnKeyDown;
}
private void OnTick(object sender, EventArgs e)
{
Ped player = Game.Player.Character;
if (player == null || !player.Exists())
{
return;
}
// Mesure de la distance et détection d'arme
float distance = 10.0f;
bool isArmed = player.IsArmed(WeaponCheckFlags.All);
_currentState = _evaluator.Evaluate(distance, isArmed, _currentState);
// Overlay visuel : lire les décisions du cerveau directement à l'écran
if (_showDebugOverlay)
{
GTA.UI.Screen.ShowSubtitle($"[DEBUG] State: {_currentState} | Dist: {distance:F1}m | Armed: {isArmed}", 1000);
}
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
// Touche de dev : activer ou couper l'overlay en pleine partie
if (e.KeyCode == Keys.F10)
{
_showDebugOverlay = !_showDebugOverlay;
GTA.UI.Notification.PostTicker($"Debug overlay: {(_showDebugOverlay ? "ON" : "OFF")}", false);
}
}
}
Avec cet overlay sous les yeux, tu marches vers le garde et tu vois immédiatement l'état basculer de Calm à Alert à l'instant précis où ton personnage franchit le seuil. Si la distance te semble trop courte ou trop punitive manette en main, tu modifies ton fichier de configuration, tu appuies sur Insert pour recharger ScriptHookVDotNet, et tu réévalues le réglage cinq secondes plus tard.
Quand le test automatisé a du sens
Est-ce que cela signifie que les tests automatisés ne servent à rien en modding ? Pas du tout.
Quand tu as structuré ton architecture dans la leçon 38, tu as isolé l'EncounterEvaluator dans du C# pur. Cet évaluateur ne contient aucun appel à GTA.dll ni aucune native. C'est de la logique de décision pure.
Pour cette couche découplée spécifique, un test automatisé apporte un gain immense : il valide tes formules limites en quelques millisecondes sans t'obliger à patienter devant les écrans de chargement de GTA V.
using Xunit;
public sealed class EncounterEvaluatorTests
{
private readonly EncounterEvaluator _evaluator = new EncounterEvaluator();
[Fact]
public void ArmedPlayer_WithinThreatDistance_TriggersCombat()
{
// Joueur a 6 mètres avec une arme sortie : combat immédiat
EncounterState state = _evaluator.Evaluate(6.0f, isPlayerArmed: true, EncounterState.Alert);
Assert.Equal(EncounterState.Combat, state);
}
[Fact]
public void UnarmedPlayer_BeyondThreatThreshold_RestoresCalm()
{
// Repli au-delà de 18 mètres : retour au calme
EncounterState state = _evaluator.Evaluate(20.0f, isPlayerArmed: false, EncounterState.Alert);
Assert.Equal(EncounterState.Calm, state);
}
}
La règle d'or
Garde cette frontière bien nette dans tes projets :
- Les tests unitaires prouvent que tes calculs sont justes : ils confirment que les états changent selon les règles établies et que tes chiffres ne dérapent pas.
- Les knobs et overlays en jeu prouvent que ton mod est amusant : ils confirment que le rythme fonctionne, que le monde réagit naturellement et que le joueur y croit.
Dans le Projet 05, tu vas combiner ces deux approches pour mettre sur pied une confrontation de gang vivante dans les rues de Los Santos.