Aller au contenu principal

Détection de zone

Presque tout mod d'ambiance ou déclencheur de mission a besoin de savoir : « Le joueur est-il arrivé ici ? » Calculer une distance est mathématiquement trivial, mais le répéter soixante fois par seconde sur des dizaines d'emplacements gaspille inutilement le budget de calcul de ta machine.

Le calcul de proximité

Pour tester si le joueur se trouve dans un rayon donné autour d'un point :

Vector3 centreZone = new Vector3(190f, -850f, 30f);
float rayonDeclenchement = 15.0f;

float distance = Vector3.Distance(player.Position, centreZone);
bool estDansZone = distance <= rayonDeclenchement;

Le piège de performance : cadencer les balayages (throttling)

L'erreur classique consiste à calculer ces distances sur des dizaines d'entités ou de coordonnées à chaque image dans OnTick. À 60 FPS, tester 50 emplacements engendre 3 000 calculs de racine carrée par seconde, sans interruption, même quand le joueur roule tranquillement sur l'autoroute.

Le temps de réaction humain est d'environ 200 millisecondes. Balayer la proximité toutes les 400 millisecondes (2,5 fois par seconde) est invisible pour le joueur, mais divise la consommation processeur par plus de vingt :

private int _prochainBalayage;
private const int IntervalleBalayageMs = 400; // Cadence idéale issue de la pratique

private void OnTick(object sender, EventArgs e)
{
// Régulation : sauter cette image si le délai n'est pas écoulé
if (Game.GameTime < _prochainBalayage)
{
return;
}

_prochainBalayage = Game.GameTime + IntervalleBalayageMs;
EffectuerBalayageZones();
}

Détection de changement d'état : Entrée contre Présence contre Sortie

Tu ne veux généralement pas exécuter ton action en continu tant que le joueur reste dans la zone. Ce qui compte, c'est l'instant précis où le joueur franchit la frontière :

private bool _etaitDansZone;

private void EffectuerBalayageZones()
{
Ped player = Game.Player.Character;
if (player == null || !player.Exists())
{
return;
}

bool estDedans = Vector3.Distance(player.Position, _centreZone) <= _rayon;

// Entrée dans la zone à ce tour
if (estDedans && !_etaitDansZone)
{
SurEntreeZone();
}
// Sortie de la zone à ce tour
else if (!estDedans && _etaitDansZone)
{
SurSortieZone();
}

_etaitDansZone = estDedans;
}

private void SurEntreeZone()
{
GTA.UI.Notification.PostTicker("Tu pénètres sur un territoire hostile.", false);
}

private void SurSortieZone()
{
GTA.UI.Notification.PostTicker("Tu quittes la zone de danger.", false);
}

Mémoriser _etaitDansZone te permet de déclencher des événements uniques d'entrée et de sortie sans inonder l'écran de notifications.

Dans la leçon suivante, nous abordons les machines à états : structurer les comportements complexes en phases distinctes et maîtrisées.