ScriptedSequence
Introduction
De la même façon qu'Unreal 2 possède un système de script créé par Legend Entertainement, UT2004 possède un système interne pour orchestrer des séquences complexes d'événements, permettant de facilement contrôler l'IA des bots, de déclencher et recevoir des events, d'émettre des sons, etc. Là où Unreal 2 utilisait des scripts écrits à la main dans des fichiers texte, nécessitant de connaître les commandes disponibles (listées dans la documentation de Legend), UT2004 possède des actors dédiés qui proposent une liste d'actions réalisables.
Trois actors permettent de réaliser ces scripts directement depuis UnrealEd : la ScriptedSequence et ses deux dérivés, le ScriptedTrigger et l'UnrealScriptedSequence.
Les trois fonctionnent de la même façon, mais s'utilisent dans des contextes différents. L'UnrealScriptedSequence est un actor utilisé comme point de défense, dans les modes de jeu avec objectifs en équipe, ou comme points à utiliser pour surveiller une zone, dans un mode de jeu "chacun pour soi".
Le ScriptedTrigger est un actor réagissant aux événements extérieurs et réalisant son script lorsqu'il est déclenché afin de dépasser les capacités limités du Trigger. Il remplace à la fois le Dispatcher, le Counter et le SpecialEvent d'UT99 en permettant de reproduire leur fonctionnement, et va au-delà de ces actors en proposant d'autres effets possibles.
La ScriptedSequence, elle, permet de créer des scripts IA contrôlant des bots ajoutés à la map en remplaçant leur comportement par défaut, afin de créer de véritables cinématiques.
Planification
Afin d'illustrer un bon nombre de possibilités, la scène interactive utilisera deux bots contrôlés chacun par une ScriptedSequence, interagissant entre eux et avec le joueur selon un plan prédéfini.
Les deux personnages commenceront à l'étage inférieur de la pièce principale, de part et d'autre de la vitre centrale. Dans notre scénario, celui situé du côté de l'ordinateur 1 (Romulus) "active" l'ascenseur permettant à l'autre (Remus) d'accéder à l'étage supérieur. Celui-ci, une fois en haut, rejoint le joueur et lui demande de le suivre s'il a pris le fusil Shock à proximité. Autrement, il lui indique de le prendre et attend que ce soit fait pour l'entraîner dans la pièce contenant le téléporteur. Une fois arrivé dans cette dernière, il fait signe au joueur de monter sur le téléporteur vert et l'active.
Deux scripts sont nécessaires au minimum : l'un contrôle Romulus et active la lumière de l'ascenseur, l'autre contrôle Remus et comprend un embranchement.
Les parties de la map que les deux personnages vont devoir traverser doivent être couvertes par un réseau de navigation valide, ce qui signifie que la map doit être couverte de PathNodes et que l'ascenseur doit avoir un LiftCenter et deux LiftExits.
Pour ajouter Romulus et Remus à la scène, il faut ajouter deux actors dérivés de Pawn. Un Pawn (pion, en français) est un actor doué d'une apparence définie qui peut être soumis à un Controller (le contrôleur du pion), qui lui permet de se déplacer, de prendre des dégâts, de prendre des décisions, etc. Ce Controller fait le lien entre l'intelligence artificielle ou le joueur humain et le Pawn qui en est la représentation visuelle. Les Pawn regroupent ainsi les véhicules, le missile du Rédempteur, les tourelles, les monstres et personnages.
La classe xPawn est responsable des personnages normaux d'UT2004. C'est celle qui peut être contrôlée par le joueur ou l'IA des bots lorsqu'ils sont à pied. Ses dérivés sont les monstres du mode Invasion et le mutant du mode éponyme, qui possède ses propres spécificités. Par défaut, un xPawn ajouté à une map utilise l'IA des bots du jeu. La ScriptedSequence permet de prendre la place de cette IA par défaut pour contrôler directement le comportement du personnage.
Les xPawns présentent l'apparence par défaut des joueurs : Gorge dans UT2003 et Jakob dans UT2004. Pour changer cela, il faut ouvrir le mesh voulu dans l'animation browser. Romulus et Remus utilisent le modèle MercMaleB, du package HumanMaleA.
Avec ce mesh ouvert dans le browser, il suffit d'aller dans les propriétés des deux xPawn, Display → Mesh et de cliquer sur "Util." qui permet d'utiliser le mesh sélectionné. La texture reste celle de Jakob, mais il suffit de vider les Skins pour que la texture par défaut du modèle prenne le dessus, ce qui est suffisant pour Romulus.
Dans le cas de Remus, la texture du visage doit être changée. Il s'agit de la seconde Skin. Si, pour un static-mesh, il serait suffisant de créer deux entrées dans le paramètre Skins et de remplir seulement la seconde, pour un mesh, la texture par défaut du corps (correspondant au premier champ Skins) est alors supprimée. Il faut donc ajouter manuellement les deux textures : celle du corps et celle du visage (Package PlayerSkins, textures MercMaleBodyA et MercMaleBHeadBFinal).
Le PlayerStart se trouve à l'étage, afin de pouvoir observer le déroulement des événements, à proximité d'un Trigger avec l'event "LancementSequence". C'est ce Trigger qui servira à activer tous les scripts.
Si la map est testée, les deux personnages redeviennent des Jakob et se comportent comme des bots normaux de DM : ils errent à la recherche d'items et se tirent dessus s'ils se rencontrent.
Script de Romulus
Association avec le script
Une ScriptedSequence est ajoutée n'importe où dans la map, mais de préférence à proximité du xPawn qu'elle va contrôler pour des raisons de clarté.
Pour remplacer l'IA par défaut de Romulus (celle d'un bot normal) par un script, il faut, dans les propriétés du xPawn, modifier AIScript → ControllerClass en ScriptedController. Il faut ensuite lui indiquer le script en question en ajoutant le tag de la ScriptedSequence dans AI → ScriptTag. Si le paramétrage est correct, une ligne reliant le personnage à la ScriptedSequence apparaît lorsque le xPawn est sélectionné.
Vous pouvez également changer le nom du xPawn dans AI → PlacedCharacterName (il s'agit de Jakob par défaut). Si la map est alors testée, Romulus est immobile, figé dans la position de course qu'il a lors du spawn.
Création du script
Dans les propriétés de la ScriptedSequence, dans l'onglet AIScript, il est possible d'ajouter des éléments à la liste Actions.
Chaque action est l'équivalent d'une commande du système de script d'Unreal 2. Les possibilités sont nombreuses et certaines sont spécifiquement prévues pour le contrôle d'un personnage (elles sont sans objet dans un ScriptedTrigger). Le premier objectif va être de faire en sorte que Romulus se tienne immobile tant qu'un événement extérieur ne déclenche pas le script. Pour cela, il faut ajouter deux actions : Action_PLAYANIM et Action_WAITFOREVENT.
Action_PLAYANIM permet de forcer le personnage à jouer une animation en entrant son nom dans BaseAnim. Dans l'animation browser, les animations disponibles peuvent être passées en revue. Dans notre cas, Idle_Rest est adaptée à l'attente. Les autres paramètres de cette action contrôlent la façon dont elle est jouée :
- BlendInTime et BlendOutTime : contrôlent le mélange de l'animation avec d'autres animations jouées en même temps (par exemple si le personnage marche, etc. Dans notre cas, ces paramètres sont sans importance.
- AnimRate : Vitesse à laquelle l'animation est jouée. 1 est la vitesse par défaut, mais il est possible de la jouer en accéléré en augmentant ce chiffre, ou de la jouer au ralenti avec des valeurs inférieurs à 1 (0.5 la joue à mi-vitesse).
- AnimIterations : Nombre de fois où l'animation doit être jouée.
- bLoopAnim : Si vrai, l'animation est jouée en boucle jusqu'à ce que le xPawn reçoive une nouvelle commande.
- StartFrame : Permet de ne pas commencer l'animation à son début mais à une frame définie en donnant son numéro.
Dans notre cas, seul bLoopAnim = vrai doit être paramétré.
Action_WAITFOREVENT permet de suspendre l'exécution du script jusqu'à réception d'un event envoyé par un Trigger ou n'importe quel autre déclencheur, ou même par une autre ScriptedSequence. Il suffit de paramétrer l'event du Trigger à l'étage.
Malgré tout, si la map est testée, Romulus reste figé dans sa position de course. En effet, les actions déclenchées dès le lancement de la map peuvent être "perdues" lors de l'initalisation du jeu. Il faut donc introduire un délai minimum avant le début du script pour que les commandes soient exécutées correctement. Pour ce faire, il faut insérer au début du script une Action_WAITFORTIMER dont l'unique paramètre, PauseTime, indique pendant combien de seconde le script doit être suspendu. Une valeur minuscule, même 0.1, suffit à retarder le début de la séquence de manière à ce que le jeu soit toalement opérationnel avant que l'exécution ne commence. Tester la map permet alors de constater que Romulus se tient devant sa fenêtre en exécutant en boucle son animation d'attente.
À ce stade, déclencher le Trigger n'a pas d'effet car le script ne contient aucune action à exécuter après réception de l'event. Il n'y a plus qu'à scripter le comportement voulu. La séquence désirée est la suivante :
- Se déplacer jusqu'à la console ;
- Jouer une animation pour donner l'illusion d'une interaction ;
- Retourner jusqu'à la vitre ;
- Se tenir immobile ;
La première action se réalise avec une Action_MOVETOPOINT. Celle-ci possède un unique paramètre, DestinationTag, qui permet de donner le tag de l'actor que doit rejoindre le xPawn. Si ce champ est vierge, le xPawn contrôlé tente de rejoindre la position de la ScriptedSequence elle-même. Il suffit donc de mettre un tag unique, par exemple "ActionSysteme" et de placer devant l'ordinateur, à l'endroit exact où Romulus doit s'arrêter, un PathNode avec ce tag.
Si la map est testée, le xPawn se déplace correctement mais ne termine pas son déplacement en faisant face à l'ordinateur. Si une animation est jouée, le résultat ne sera donc pas satisfaisant. Il faut donc ajouter une action indiquant à Romulus dans quelle direction regarder : Action_SETVIEWTARGET. Son paramètre ViewTargetTag permet de donner le tag de l'actor que le personnage doit regarder (dans le cas présent, l'ordinateur, dont le tag est "Console"). Il regarde alors dans la direction du pivot du static-mesh.
Romulus se retourne partiellement pendant son déplacement mais la distance n'est pas assez longue pour qu'il termine de se tourner totalement vers la console avant d'arrêter de bouger. L'action Action_WAITFORANIMEND permet de forcer le bot à terminer son mouvement avant de passer à la suite du script, ce qui permet à la fois de ne pas interrompre une animation en cours et d'aller jusqu'au bout de la rotation commencée. Avec ces deux actions, le personnage termine son mouvement en faisant bien face à l'ordinateur.
Une nouvelle Action_PLAYANIM peut alors être ajoutée avec l'animation gesture_point. Une Action_WAITFORANIMEND supplémentaire permet de ne pas interrompre l'animation avant que le bot ne passe à la suite de son script.
À cause de l'Action_SETVIEWTARGET utilisé précédemment, le bot ne lâche plus des yeux l'ordinateur s'il reçoit un autre ordre. Il faut donc en utiliser une nouvelle qui lui indique d'observer la vitre elle-même (il s'agit d'un static-mesh avec le tag Vitre).
Une nouvelle Action_MOVETOPOINT lui indique de se rendre à un PathNode placé devant la vitre (tag = Observation) et une Action_WAITFORANIMEND lui permet de finir de se retourner vers la vitre.
Afin de terminer le script sans abandonner Romulus dans sa position actuelle, une dernière Action_PLAYANIM avec l'animation idle_chat et bLoopAnim = vrai permet de lui faire jouer l'animation de discussion. Malheureusement, une fois l'animation jouée une seule fois, le script se termine et le xPawn devient inerte dans sa position d'attente par défaut. Afin de faire en sorte que le script ne se termine pas, il faut le faire boucler sur lui-même.
L'action Action_GOTOACTION permet de sauter à n'importe quelle autre action du script en indiquant son numéro dans ActionNumber. L'Action_PLAYANIM est l'action 11, c'est donc vers elle qu'il faut pointer l'Action_GOTOACTION.
Si la map est alors testée, le jeu crashe à ce moment du script.
En effet l'Action_PLAYANIM n'interrompt pas l'exécution du script lorsqu'elle est déclenchée (c'est la raison pour laquelle Action_WAITFORANIMEND doit être utilisée pour laisser une animation se terminer). L'Action_GOTOACTION située après est donc déclenchée en même temps que l'Action_PLAYANIM, ce qui signifie qu'en déclenchant celle-ci, l'Action_GOTOACTION se déclenche elle-même, ce qui cause une boucle infinie.
Pour éviter cela, il suffit d'introduire un délai entre les deux actions avec une Action_WAITFORTIMER. N'importe quelle durée peut être utilisée, mais plus la durée est longue, moins le jeu sera surchargé d'événements scriptés si la map est jouée pendant longtemps. Un PauseTime de 10 permet de laisser le bot jouer son animation en boucle 10 secondes avant de faire boucler le script.
Le script est déjà fonctionnel, mais afin de le compléter, on peut faire émettre un message à Romulus en insérant avant l'Action_PLAYANIM finale une Action_DISPLAYMESSAGE qui possède trois paramètres :
- Message : Message envoyé. Dans notre exemple, il peut s'agir de : "L'ascenseur est opérationnel."
- bBroadcast : Si ce paramètre est vrai, le message est envoyé à tous les joueurs. Si bBroadcast = faux, le message n'ets reçu que par l'exécuteur du script (dans le cas présent, Romulus) et le joueur ne le reçoit donc pas Il faut donc régler cette propriété sur vrai..
- messagetype : Le type de message utilisé. Par défaut, "CriticalEvent" est utilisé et affiche le texte en bleu comme les folies meurtières ou les décomptes du chronomètre. Utiliser le type "Chat" permet de l'afficher en blanc dans la console du jeu.
Lorsque Romulus atteint la fin de son script, il envoie désormais son message dans la console en jouant son animation.
Enfin, entre l'Action_DISPLAYMESSAGE et l'Action_PLAYANIM, une Action_TRIGGEREVENT peut être utilisée pour activer la TriggerLight rouge au-dessus de la cage d'ascenseur. Cette action fonctionne comme un Trigger normal : son event déclenche le tag correspondant.
Une seconde Action_TRIGGEREVENT est ajoutée, qui servira à déclencher le script de Remus de l'autre côté de la vitre. Elle est insérée entre l'Action_TRIGGEREVENT déclenchant la lumière et l'animation de fin, afin d'être la dernière commande exécuté avant la boucle finale. Son event est "PassageRelais". Il faut alors revenir à la dernière commande, Action_GOTOACTION qui renvoie toujours à l'action numéro 11. L'Action_PLAYANIM est devenue l'action 14 suite aux différents ajouts.
Ce changement est nécessaire car, autrement, toute la séquence à partir de l'action 11 se répète toutes les 10 secondes, ce qui signifie que le message et la TriggerLight seront redéclenchés à cette fréquence.
Le script de Romulus étant terminé, il faut s'occuper de celui de Remus, légèrement plus complexe.
Script de Remus
Une seconde ScriptedSequence est ajoutée près de Remus et configurée de façon identique à celle de son frère.
Le début de la séquence est relativement similaire : Remus joue en boucle son animation d'attente en attendant l'event "PassageRelais" envoyé par le script de son frère. Il exécute alors une nouvelle action, Action_MOVETOPLAYER, qui indique au bot de se rendre à proximité du joueur.
Cette dernière action n'a aucun paramètre : le xPawn qui l'exécute tente de rejoindre le joueur où qu'il soit en utilisant le réseau de navigation normal. Un xPawn utilisant un Controller de type ScriptedController n'est pas considéré comme un véritable joueur (il n'apparaît d'ailleurs pas dans le tableau des scores en cours de jeu), le mover doit donc avoir le réglage Mover → BumpType → BT_PawnBump, car il ne réagit par défaut qu'aux véritables joueurs (BT_PlayerBump).
Ce BumpType le force à réagir à tout type de Pawn, quel que soit leur Controller. Une fois ceci fait, Remus peut emprunter l'ascenseur pour rejoindre le joueur. Si ce dernier se déplace pendant que l'action est en cours, le xPawn réajuste en permanence sa trajectoire. Une fois qu'il rejoint le joueur, il s'immobilise.
Section conditionnelle
À ce point du script, il faut choisir entre deux séries d'événements. Si le joueur a déjà pris le fusil Shock qui se trouve près de lui, Remus doit lui faire signe de le suivre dans la salle du téléporteur. Autrement, il doit lui indiquer l'arme et attendre que le joueur la prenne, puis entraîner le joueur jusqu'au téléporteur normalement.
Une ScriptedSequence peut diverger suivant la situation grâce à une section conditionnelle. Il s'agit d'une suite d'actions précédées d'une condition (Action_IFCONDITION ou Action_IFRANDOMPCT) et terminée par une Action_ENDSECTION. Les actions situées entre ces bornes ne sont exécutées que si la condition posée est vérifiée. Autrement, la section est sautée et le script passe à l'action située après l'Action_ENDSECTION.
Action_IFRANDOMPCT permet d'ajouter une dimension aléatoire à un script. En effet, son unique paramètre, Probability, accepte une valeure entre 0 et 1 qui équivaut au pourcentage de chances que la section conditionnelle soit executée.
Dans notre cas, c'est l'Action_IFCONDITION qui permet de tester si le joueur s'est emparé du fusil Shock. Elle permet de n'exécuter la section que si la condition définie est vraie. Pour ce faire, le script se réfère à un type de Trigger particulier, le TriggeredCondition.
La position de cet actor n'a pas d'influence. Son unique rôle est de stocker un état (vrai/faux), qui est consulté par le script. Cet état peut être changé en cours de jeu en déclenchant le TriggeredCondition avec n'importe quel type de Trigger. Ses trois paramètres déterminent sa valeur initiale et son comportement.
- bEnabled : Détermine si l'état initial du TriggeredCondition est vrai ou faux.
- bToggled : Si ce paramètre est vrai, chaque déclenchement successif inverse l'état du TriggeredCondition. Autrement, déclencher le TriggeredCondition ne peut que lui donner l'état inverse de sa valeur initiale.
- bTriggerControlled : Si oui, le TriggeredCondition revient à son état initial à chaque fois que le Trigger qui le déclenche est "relâché".
Pour contrôler si le joueur a déjà pris le fusil Shock lorsque Remus le rejoint, il faut placer quelque part un TriggeredCondition avec bEnabled = faux, et lui donner un tag unique, "ShockPris" par exemple. Un Trigger englobant la xWeaponBase déclenche le tag de la TriggeredCondition, afin de changer l'état initial de l'actor lorsque le joueur ramasse le fusil Shock.
Dans le script de Remus, l'action_IFCONDITION référence ce même tag. Lorsque l'action est exécutée, le script regarde donc le valeur du TriggeredCondition et n'exécute la section conditionnelle que s'il contient la valeur "vrai", donc si le joueur possède l'arme. La séquence à exécuter dans ce cas est relativement simple :
- Jouer une animation et envoyer un message au joueur pour qu'il suive Remus ;
- Se rendre dans la pièce du téléporteur, le désigner au joueur et attendre qu'il monte dessus ;
- Jouer une animation et déclencher la téléportation (en réalité un changement de niveau) ;
La première action de cette section sera Action_TURNTOWARDPLAYED, qui permet d'ordonner au xPawn de se tourner vers le joueur (s'il y en a plusieurs dans la partie, vers le joueur ayant activé le script). Une Action_WAITFORANIMEND permet de s'assurer que la rotation est terminée avant d'exécuter une nouvelle Action_PLAYANIM. Celle-ci utilise l'animation gesture_beckon dans laquelle le mesh fait signe qu'il faut le suivre. Le résultat peut être testé, mais il faut veiller à prendre le fusil Shock avant ce point du script de Remus pour qu'il exécute la section conditionnelle.
La suite de la séquence n'utilise que des actions connues :
- Action_DISPLAYMESSAGE (avec un message du type "Suivez-moi !") ;
- Action_WAITFORANIMEND ;
- Action_MOVETOPOINT (amenant le personnage devant l'ordinateur dans la salle du téléporteur) ;
- Action_SETVIEWTARGET (avec le tag du téléporteur pour qu'il se tourne vers lui) ;
- Action_WAITFORANIMEND ;
- Action_PLAYANIM (avec l'animation gesture_point pour que Remus désigne le téléporteur au joueur) ;
- Action_WAITFORANIMEND ;
- Action_WAITFOREVENT qui attendra l'event "EnPlace", envoyé par un Trigger placé sur la plateforme du téléporteur, et donc déclenché quand le joueur monte dessus ;
- Action_SETVIEWTARGET (pour se retourner vers l'ordinateur) ;
- Action_WAITFORANIMEND ;
- Action_PLAYANIM (de nouveau gesture_point) ;
- Action_WAITFORANIMEND ;
Pour conclure, la dernière action est Action_CHANGELEVEL qui permet de changer de niveau en indiquant le nom de la map dans le champ URL. De la même façon que dans un téléporteur, il est possible de cibler une destination précise en ajoutant le tag de la cible après un #. Il est possible de désactiver l'écran de chargement avec bShowLoadingMessage = faux, mais le jeu se fige alors pendant que le chargement a lieu en arrière plan.
L'Action_ENDSECTION met fin à la section conditionnelle. La suite du script n'est exécutée que si la condition n'est pas remplie.
Script sans fusil Shock
Si le joueur n'a pas pris le fusil Shock, Remus doit lui indiquer de le prendre. La séquence appropriée se situe après l'Action_ENDSECTION de la ScriptedSequence, et n'a donc lieu que si la condition n'a pas été remplie. Son déroulement ressemble beaucoup à la section précédente :
- Se rendre jusqu'au fusil Shock, envoyer un message au joueur ;
- Désigner l'arme par une animation et attendre que le joueur s'en empare ;
- Amener le joueur au téléporteur ;
La séquence est très simple et n'utilise que des actions déjà maîtrisées.
L'Action_WAITFOREVENT attend l'event "ShockPris", déclenché par le Trigger sur la xWeaponBase. Il s'agit du même event que celui de la TriggeredCondition, cette dernière n'ayant plus d'importance dans la suite.
La dernière action de ce script est une Action_GOTOACTION qui renvoie directement à la première action de la séquence exécutée quand le joueur possède déjà le fusil Shock lorsque le xPawn le rejoint. En effet, une fois l'arme prise, le comportement attendu est strictement identique.
Notez qu'il aurait été possible d'inverser le fonctionnement : en changeant la valeur initiale du TriggeredCondition, il était possible d'indiquer dans la section conditionnelle la marche à suivre si le joueur ne possédait pas le fusil Shock, et en dehors, après l'Action_ENDSECTION, que faire si le joueur s'en était déjà emparé.
Les deux ScriptedSequences sont maintenant terminées, illustrant le fonctionnement de base : faire se déplacer un xPawn, lui faire jouer une animation, recevoir ou déclencher des events, faire des choix en fonction de conditions. Il est possible de compléter la séquence : l'ascenseur est par exemple fonctionnel dès le début du jeu et l'animation de Romulus n'a pas réellement d'effet. On peut envisager que Remus, en montant sur l'ascenseur, entre dans le rayon d'un Trigger dont l'event serait écouté par Romulus. Celui-ci, via une Action_TRIGGEREVENT, activerait alors réellement le mover, réglé en TriggerOpenTimed.
Notes sur les actions
Actions interruptives
Comme expliqué plus haut, si une Action_PLAYANIM est suivie par une action donnant l'ordre au xPawn de se déplacer, ce dernier abandonne l'animation qu'il jouait pour se mettre en mouvement, d'où l'obligation d'utiliser une Action_WAITFORANIMEND ou Action_WAITFORTIMER pour lui laisser le temps de terminer son geste.
À l'inverse, certaines actions interrompent le script le temps d'être terminées. Elles sont dites "latentes" ou interruptives et empêchent l'exécution des actions suivantes avant d'avoir été totalement accomplies. En voici la liste :
- ACTION_FinishRotation ;
- ACTION_Freeze ;
- ACTION_PlayExplosionSound ;
- ACTION_WaitForLIPSincAnimEnd ;
- Action_DrawHUDMaterial ;
- Action_FADEVIEW ;
- Action_MOVETOPLAYER ;
- Action_MOVETOPOINT ;
- Action_TELEPORTTOPOINT ;
- Action_TURNTOWARDPLAYER ;
- Action_WAITFORANIMEND ;
- Action_WAITFOREVENT ;
- Action_WAITFORPLAYER ;
- Action_WAITFORTIMER ;
En dehors de celles-ci, les actions sont exécutées successivement de façon instantanée. Pour l'envoi d'un message, le déclenchement d'un event ou autre, cela ne pose pas de problème car il s'agit d'événements ponctuels. Lorsque l'action doit avoir une certaine durée en revanche (pour jouer une animation ou attendre la fin d'un son), il est nécessaire de prévoir le temps nécessaire.
Autres actions
La liste complète des actions utilisables peut être trouvée sur UDN avec une rapide description (en anglais) de leur usage. Si le ScriptedTrigger utilise aussi des scripts à base d'actions, il ne peut pas être utilisé pour contrôler un Pawn comme la ScriptedSequence. Le wiki de BeyondUnreal répertorie pour chaque action si elle est utilisable ou non avec un ScriptedTrigger.
Limitations
Le système de script d'UT2004 reste relativement rudimentaire et soumis à de nombreux aléas. Comme constaté au début, il faut attendre quelques instants après le début de la partie (avec une Action_WAITFOREVENT) avant de commencer l'exécution d'une animation, sous peine de voir la première action passer à la trappe. De plus, dans certains cas, certaines actions peuvent ne pas fonctionner : Action_MOVETOPOINT tend à échouer si le joueur se place dans un coin de la géométrie. Même si le xPawn parvient à le rejoindre, la suite du script peut alors ne jamais se déclencher. De même, si le joueur se trouve loin de Romulus lorsque celui-ci doit envoyer son message et déclencher la ScriptedSequence de Remus, il arrive que rien ne se passe tant que le joueur ne regarde pas le xPawn. Enfin, certaines animations peuvent ne pas être jouées avant d'exécuter l'action suivante, et ce malgré une Action_WAITFORANIMEND.
S'assurer que le script fonctionne dans tous les cas est difficile et demande de nombreux tests en variant les situations. Malgré tout, il faut s'attendre à ce que le script ne se déroule pas toujours parfaitement.
RSS Feed