Last updated: 06/10/2024, 02:17

Current Project: Easing hk.fr into its new life.

Scripts IA

Préparation

Créez le répertoire de vos scripts .u2s scripts comme expliqué dans ce tutorial. Nous utiliserons le nom "u2stutorial". Téléchargez la map de test utilisée pour notre exemple. Il s'agit d'une simple pièce contenant 4 PathNodes, un PlayerStart, une Light et un marine. Le MapName du niveau est "u2stutorial", ce qui correspond à notre répertoire de scripts. La map contient également un Trigger qui sera utilisé pour des tests plus tard.

Map de test pour les scripts

Si le niveau est testé, le marine se déplace au hasard dans la pièce. N'ayant pas de script attribué, il est dans un état dit autonome et erre sans but. Le comportement IA de base du Pawn le fait réagir aux événements extérieurs (comme voir ou entendre un ennemi).

Créez un fichier texte vide que vous nommerez "marine01.u2s" et placez-le dans votre dossier /Scripts/u2stutorial. Il s'agit du script IA qui sera utilisé pour contrôler le marine. Assurez-vous que votre éditeur de texte n'y ajoute pas une extension .txt.

Dans les propriétés du marine, dans l'onglet AI, ajoutez "marine01" (sans aucune extension) au champ CommandFileName, afin que le jeu sache quel script utiliser pour contrôler le Pawn. Sauvegardez la map

Patrouille

Ajoutez les lignes suivantes au fichier "marine01.u2s" et sauvegardez-le :

sleep 2
gotoactor PathNode0
gotoactor PathNode1
sleep 2
gotoactor PathNode2
agentcall Event_U_Wave 1
gotoactor PathNode3
sleep

Quand le niveau est lancé, le marine reste en place 2 secondes, court jusqu'au PathNode0 puis jusqu'au PathNode1, attend 2 secondes puis se rend au PathNode2, où il joue l'animation "Event_U_Wave". Enfin, il court jusqu'au PathNode3 et s'y arrête définitivement.

Voici le détail des commands utilisées dans ces exemple. Les paramètres entre parenthèses, "()", sont obligatoires. Ceux entre crochets, "[]", sont facultatifs :

Toutes les commandes du script doivent être écrites en minuscules, mais les autres éléments (par exemple le nom des actors, comme PathNode0) ignorent les changements de casse.

Labels

Un label est une section de script portant un nom arbitraire. Celui-ci est précédé du caractère ":" et doit être composé uniquement de lettres, de chiffres et du caractère "_". La commande "gotolabel" permet au script de sauter jusqu'à la section dont le nom est cité. Il est ainsi possible de réaliser, par exemple, des boucles d'actions.

Ajoutez deux nouvelles lignes au début et à la fin de votre script et retirez la commande "sleep" pour qu'il ressemble à ceci :

:MarinePatrol
sleep 2
gotoactor PathNode0
gotoactor PathNode1
sleep 2
gotoactor PathNode2
agentcall Event_U_Wave 1
gotoactor PathNode3
gotolabel MarinePatrol

Testez le niveau et voyez le comportement du PNJ.

La commande "call" permet d'appeler, ou "d'insérer", les commandes du label au milieu d'un autre script. Quand un tel appel est exécuté, le script en cours se met en pause, exécute les commandes du label et reprend son cours normal quand il rencontre la commande "return" :

:WaitABit
sleep 5
call PatrolThisArea
sleep 3
gotolabel WaitABit

:PatrolThisArea
gotoactor PathNode0
gotoactor PathNode1
return

Dans cet exemple, le PNJ attend 5 secondes, puis (suite à "call PatrolThisArea"), se rend aux PathNode0 puis PathNode1. La commande suivante étant "return", il reprend le cours de la section WaitABit : le Pawn attend 3 seconds puis recommence la séquence.

Messages et Débuggage

Pour voir en temps réel si le script suit bien son cours, il est possible d'envoyer des messages dans la console une fois que celle-ci a été réactivée.

Modifiez à nouveau le script de cette façon :

:MarinePatrol
message "sleeping 2 seconds"
sleep 2
message "going to pathnode 0, then PathNode1"
gotoactor PathNode0
gotoactor PathNode1
message "sleeping 2 seconds"
sleep 2
message "going to pathnode 2"
gotoactor PathNode2
message "waving!"
agentcall Event_U_Wave 1
gotoactor PathNode3
message "starting over"
gotolabel MarinePatrol

En jeu, le script envoie des messages annonçant les actions que le marine s'apprête à entreprendre.

Le système de débuggage du jeu est cependant une meilleure façon d'étudier le déroulement du script sans s'appuyer sur des messages ajoutés à la main. En insérant "debugmode 11" au tout début du script, avant le label :MarinePatrol, le jeu écrit dans la console tout ce que le script exécute, à l'exception des Events.

Commandes principales

Voici les commandes principales, autres que celles déjà rencontrées :

Voici un exemple d'utilisation :

:MarinePatrol
sleep 2
gotoactor PathNode0
turntoactor Light0 // Le marine se tourne vers la Light
fire 2 // Il tire dessus pendant 2 secondes
firealt 2 // Idem, avec son tir secondaire
gotoactor PathNode1
sleep 2
setmovespeed 0.5 // Le marine se déplace maintenant à la moitié de sa vitesse normale
gotoactor PathNode2
setmovespeed 1 // Il reprend sa vitesse habituelle
agentcall Event_U_Wave 1
gotoactor PathNode3
gotolabel MarinePatrol

Events

Les Events sont extrêmement utiles pour faire réagir les scripts aux événements externes. Le niveau de test contient un Trigger qui émet l'Event "ChangeMarinePatrol". Par défaut, il ne peut pas affecter les PNJ : dans les propriétés du Trigger, la propriété bTriggerNPCs (dans l'onglet Trigger) doit d'abord être réglée sur vrai. Le marine réagira alors à l'Event une fois que la commande "ontrigger" aura été ajoutée à son script pour l'intercepter.

Observez le script suivant :

:MarinePatrol
ontrigger ChangeMarinePatrol gotolabel MarinePatrol2
gotoactor PathNode0
gotoactor PathNode1
sleep 2
gotolabel MarinePatrol

:MarinePatrol2
ontrigger ChangeMarinePatrol gotolabel MarinePatrol
gotoactor PathNode2
gotoactor PathNode3
sleep 2
gotolabel MarinePatrol2

En jeu, le marine répète le label MarinePatrol jusqu'à ce que l'Event "ChangeMarinePatrol" soit envoyé par la map. Il exécute alors le label MarinePatrol2 en boucle. S'il reçoit de nouveau l'Event, il reprend sa première routine.

Décisions aléatoires

Un degré de hasard peut être implémenté dans le script avec la commande "testrandom". Lorsqu'elle est exécutée, le script génère un nombre aléatoire entre 0 et 1. Si ce nombre est supérieur ou égal à celui utilisé comme argument, le test est considéré comme réussi et la seconde partie de la commande est exécutée :

testrandom 0.5 gotolabel Outcome1
gotolabel Outcome2

:Outcome1
[...]

:Outcome2
[...]

Dans cet exemple, si le nombre aléatoire est supérieur ou égal à 0.5, le script passe au label Outcome1. Autrement, le script continue avec la commande suivante, "gotolabel Outcome2" et passe donc au label Outcome2.
N'importe quelle commande peut être utilisée après "testrandom" pour indiquer quoi faire si le test est un échec, mais utiliser "gotolabel" pour se rediriger vers un label séparé est encouragé pour garder le script lisible et organisé.

Plusieurs commandes "testrandom" peuvent être utilisées à la suite pour faire un choix entre plus de deux possibilités :

testrandom 0.66 gotolabel Outcome1
testrandom 0.66 gotolabel Outcome2
gotolabel Outcome3

Ce script a 33 % de chances de passer au label Outcome1. En cas d'échec, il a 33 % de chances de passer à Outcome2. Si les deux tests sont des échecs, il passe au label Outcome3.

La commande "testrandom" peut être combinée avec "call" :

testrandom 0.5 call Outcome1
gotoactor PathNode3
[...]

:Outcome1
gotoactor PathNode1
return

Dans cet exemple, le script a 50 % de chances de passer au label Outcome1 (et donc d'amener le Pawn au PathNode1), puis la commande "return" le ramène à la suite du script (et le Pawn se rend au PathNode3). Dans les 50 % de cas restants, le marine se rendra directement au PathNode3 en sautant le label Outcome1.

Rencontres aléatoires avec "setlocation"

Le commande "setlocation" permet de téléporter un Pawn n'importe où dans la map. La ligne "setlocation PathNode11" déplace ainsi le Pawn contrôlé par le script sur le PathNode11. Cette technique peut être utilisée pour ajouter de la variation dans le placement des ennemis.
Si, par exemple, le joueur doit rencontrer un Skaarj dans une pièce parmi trois, la position de l'adversaire peut être déterminée aléatoirement :

testrandom 0.66 gotolabel TeleportToRoom1
testrandom 0.66 gotolabel TeleportToRoom2
setlocation PathNode3 // PathNode dans la pièce 3
sleep

:TeleportToRoom1
setlocation PathNode1 // PathNode dans la pièce 1
sleep

:TeleportToRoom2
setlocation PathNode2 // PathNode dans la pièce 2
sleep

Le moteur ne vérifie pas si la cible est visible lorsque le Pawn est téléporté, le Skaarj se matérialise donc soudain, sans prévenir. Il est donc préférable que le déplacement se fasse avant que le PathNode de destination ne soit visible par le joueur. Si un test de visibilité est nécessaire, il vaut mieux utiliser un PawnFactory (qui peut lui-même être contrôlé par script) que la commande "setlocation".

Recherche dynamique

La commande "findactor" est un outil puissant qui permet de rechercher un actor dans un rayon déterminé autour du Pawn pendant le jeu. Elle accepte un grand nombre de paramètres :

findactor [TargetName [Min [Max [DistanceType [VisibilityType [Num [gotolabel/call targetlabel]]]]]]]

Les crochets "[]" signifient que les paramètres à l'intérieur sont facultatifs, il n'est donc pas nécessaire de tous les utiliser à chaque fois que "findactor" est utilisé. Voici un exemple simple d'utilisation :

findactor engine.pathnode 32 1024 1
gotoactor found

Le Pawn recherche un PathNode dans un cercle autour de lui, qui doit être au moins à 32 unités mais pas à plus de 1024, et s'y rend si un PathNode est effectivement détecté. Le dernier paramètre (1) indique que le PathNode le plus proche sera sélectionné si plusieurs sont disponibles. Si la recherche est fructueuse, le résultat est stocké dans une variable interne, found.

La commande "findactor" peut être utilisée, par exemple, pour contrôler un scientifique terrifié qui suit le joueur mais qui, en cas de danger, court se mettre à couvert dans la cachette la plus proche (les zones sûres étant prédéfinies avec des ShadowNodes).

:FollowPlayer
onevent SeeEnemy gotolabel CheckForHiding
gotoactor Player 128 // Le PNJ reste dans un rayon de 128 unités autour du joueur
sleep 3
gotolabel FollowPlayer // Quand le PNJ rejoint le joueur, il s'arrête 3 secondes puis le suit à nouveau

:CheckForHiding
findactor U2AI.ShadowNode 0 2048 1 gotolabel Hide // Passe au label Hide si un ShadowNode est trouvé
message "No hiding spot found, continue script" // Aucune cachette dans un rayon de 2048 unités
sleep 1
gotolabel FollowPlayer

:Hide
gotoactor found 64 // Rejoint le ShadowNode et reste à 64 unités
findactor // Vide la variable found
setstance crouching
onevent SeePlayer gotolabel FollowPlayer

Cette commande a plus de paramètres que les précédentes :

Comme montré plus haut, utiliser "findactor" sans aucun paramètre permet de vider la variable found.

Voici quelques exemples de combinaisons et ce qu'elles sélectionnent :

findactor u2.alarmtrigger 0.0 4096.0 0 0 0 gotolabel useit // Premier actor dans un rayon de 4000, sans test de visibilité
findactor u2.alarmtrigger 0.0 4096.0 1 0 0 gotolabel useit // Le plus proche dans un rayon de 4000, sans test de visibilité
findactor u2.alarmtrigger 0.0 4096.0 2 0 0 gotolabel useit // Le plus loin dans un rayon de 4000, sans test de visibilité
findactor u2.alarmtrigger 0.0 4096.0 3 0 2 gotolabel useit // Tous dans un rayon de 4000, sans test de visibilité, 2 mis en mémoire
findactor u2.alarmtrigger 0.0 0.0 2 0 0 gotolabel useit // L'actor le plus éloigné, sans test de visibilité
findactor u2.alarmtrigger 0.0 0.0 2 1 0 gotolabel useit // L'actor visible le plus éloigné

Il existe beaucoup d'autres commandes et mêmes des Events internes générés par le jeu lorsque les PNJ détectent d'autres personnages ou interagissent avec. Une explication complète du système de scripts d'Unreal 2 peut être trouvée dans les documents de Legend Entertainement (en anglais), notamment dans le fichier AIScripting.doc, à lire en priorité.

© 2005-2026, by Hellkeeper.

Valid XHTML 1.1 & CSS 3