Qu'est-ce
qu'un Iterator ?
Un Iterator est une instruction (une boucle pour être plus précis) qui permet
de rechercher des actors dans la map. En fait ils retournent les actors présents
dans une liste existant seulement dans le code natif. A chaque fois qu'un
actor est créé, il est automatiquement ajouté à la liste et automatiquement
supprimé de cette liste quand il est détruit. Il existe différentes listes
suivant les propriétés de l'actor. Les iterators permettent de fouiller dans
ces listes.
Comme leur exécution est plutôt lente, il faut éviter de les utiliser dans
des fonctions qui sont souvent appelées comme Tick() ou PostRender()
(pour le HUD) par exemple. Si les actors cherchés sont inscrits dans une linked
list ou un tableau (array, uniquement dans UT2003/4), mieux vaut
utiliser ces listes avec une boucle for. Exemple de recherche dans
la linked list des Pawns
L'utilisation
Un Iterator se présente sous cette forme :
Ils prennent au minimum deux paramètres :
- une class qui est la class ou une super-class de l'actor(s)
recherché(s)
- une référence à un actor qui est la valeur retournée par l'iterator : l'actor
que l'on cherche.
Exemple (on suppose qu'il existe une class nommée Actor1)
On peut aussi effectuer le code sur le premier actor trouvé avec la commande
break. break est un peu comme return : return
arrête la fonction entière alors que break arrête juste la boucle dans
laquelle il est inséré.
Cette fonction peut aussi se présenter comme ceci :
Sinon, si on trouve un actor de bon type mais qui ne nous plait pas (à cause
de la valeur d'une certaine variable par exemple), on peut le sauter avec
la commande continue.
Là il n'y a pas besoin de mettre de else, il est sous-entendu par le
continue qui arrête l'exécution de l'iterator pour le a1 qui
ne nous plait pas.
break et continue ne sont pas propres aux iterators, ils peuvent
s'utiliser dans n'importe quel autre type de boucle (for par exemple).
Les iterators peuvent aussi être appelés pour un autre actor (ou object) que
celui où ce trouve le code. Mais ceci n'est utile qu'avec certains types d'iterators
qui retournent des actors basés sur l'actor où est appelé l'iterator (ChildActors
par exemple). Exemple (on suppose qu'il existe une class nommée Actor2)
Pour ce type de syntaxe, il faut s'assurer que a2 n'est pas nul, dans
quel cas le jeu planterait avec une erreur critique.
Les
différents types d'iterators
Leur simple nomenclature permet souvent de déterminer quel type d'actor
ils cherchent. Les iterators précédés d'une astérisque (*) ne sont disponibles
que sous UT2003/4.
- * AllObjects(class baseClass, out Object obj)
Celui-ci est le seul qui permette de chercher autre chose que des actors.
Il n'a pas de paramètre particulier.
- AllActors(class<actor> BaseClass, out actor Actor, optional name
MatchTag)
Pour les anglophobes, je vais traduire l'avertissement qui se trouve avec
la définition de l'iterator : Evitez d'utiliser cet iterator trop souvent
car il cherche dans la liste entière d'actors et est donc lent.
-- Les deux premiers paramètres ont été décrits plus haut.
-- optional name MatchTag : ce paramètre est facultatif, il permet
de retourner seulement les actors dont le Tag correspond à ce paramètre.
- DynamicActors(class<actor> BaseClass, out actor Actor, optional
name MatchTag)
Celui-ci fonctionne comme celui du dessus. La seule différence est qu'il cherche
des actors qui ne sont pas statiques (avec la variable bStatic à false
par exemple). Bien qu'il soit plus rapide que AllActors, il reste globalement
lent mais peut être utilisé dans la plupart des cas.
- ChildActors(class<actor> BaseClass, out actor Actor)
Celui-ci cherche les actors dont la variable Owner correspond à l'actor
à partir duquel est appelé l'iterator.
Il est, comme AllActors, lent.
- BasedActors(class<actor> BaseClass, out actor Actor)
Je ne suis pas très sûr d'avoir compris, il chercherait les actors dont la
variable Base correspond à l'actor à partir duquel est appelé l'iterator.
Il est, comme AllActors et comme son homologue ChildActors,
lent.
- TouchingActors(class<actor> BaseClass, out actor Actor)
Je pense que vous comprenez à quoi il sert. Pour les deux du fond qui ne suivent
pas, il retourne les actors qui touchent (entrent dans le cylindre de collision,
s'il existe) l'actor à partir duquel l'iterator est appelé.
Celui-ci est rapide.
- TraceActors(class<actor> BaseClass, out actor Actor, out vector
HitLoc, out vector HitNorm, vector End, optional vector Start, optional vector
Extent)
Celui-ci retourne les actors qui touchent une ligne virtuellement tracée dans
le niveau. Il est plutôt rapide.
-- class<actor> BaseClass : si vous ne savez toujours pas à quoi
sert ce paramètre, relisez le tuto depuis le début, espèce de cancre
-- out actor Actor : idem
-- out vector HitLoc : retourne la position de l'actor retourné quand
la "ligne" le touche.
-- out vector HitNorm : Euh... ça retourne une normale, mais je n'ai
pas compris de quoi. Si vous ne savez pas ce qu'est une normale, révisez vos
cours de géométrie dans l'espace (excusez mois si je suis en Terminale S et
vous au CM2
)
-- vector End : défini la position du dernier point de la "ligne"
-- optional vector Start : facultatif, défini la position du premier
point de la "ligne". Si aucune valeur n'est entrée, la position de l'actor
où est appelé l'iterator est utilisée.
-- optional vector Extent : facultatif, permet de donner un "rayon"
à la "ligne".
- RadiusActors(class<actor> BaseClass, out actor Actor, float Radius,
optional vector Loc)
Retourne les actors situés dans un rayon donné. Lent, mieux vaut utiliser
CollidingActors ou VisibleCollidingActors si les actors recherchés
ont une collision (bCollideActors == true) et sont visibles (bHidden
== false) dans le deuxième cas.
-- class<actor> BaseClass : faut-il encore dire à quoi ça correspond
?
-- out actor Actor : idem
-- float Radius : rayon du rayon
-- optional vector Loc : facultatif, centre du rayon. Si aucune valeur
n'est donnée, la position de l'actor où est appelé l'iterator est utilisée.
- VisibleActors(class<actor> BaseClass, out actor Actor, optional
float Radius, optional vector Loc)
Retourne les actors visibles dans un certain rayon, où "visible" signifie
qu'une ligne peut être tracée entre le centre de l'actor où est appelé l'iterator
et une partie de l'actor cherché sans passer à travers le niveau (BSP,
terrain...) et que la variable bHidden de l'actor cherché est
à false.
Lent, utilisez plutôt VisibleCollidingActors si les actors recherchés
ont une collision (bCollideActors == true).
-- optional float Radius : facultatif, rayon du rayon
. Si aucune valeur n'est donnée, je pense qu'une valeur infinie est utilisée.
-- optional vector Loc : facultatif, centre du rayon. Si aucune valeur
n'est donnée, la position de l'actor où est appelé l'iterator est utilisée.
- * CollidingActors(class<actor> BaseClass, out actor Actor, float
Radius, optional vector Loc)
Celui-ci fonctionne comme RadiusActors, mis à part qu'il retourne seulement
les actors qui ont une collision (bCollideActors == true). De ce fait,
il est sensiblement plus rapide que AllActors.
Il prend les mêmes paramètres que RadiusActors.
- VisibleCollidingActors(class<actor> BaseClass, out actor Actor,
float Radius, optional vector Loc, optional bool bIgnoreHidden)
Celui-ci combine les fonctionnalités de VisibleActors et CollidingActors
: il cherche les actors qui sont visibles et ont une collision. Il est, lui
aussi, rapide et prend les même paramètres que RadiusActors plus
-- optional bool bIgnoreHidden : facultatif, ignore si les actors sont
invisibles (bHidden == true).
- ZoneActors(class<actor> BaseClass, out actor Actor)
Uniquement pour les ZoneInfos, celui-ci retourne tous les actors présent
dans la zone.
- * AllDataObjects(class objClass, out Object obj, string packageName)
Uniquement pour les GameInfos, je ne sais pas à quoi il correspond
et je ne l'ai jamais vu utilisé.