Iterator
The Actor List
All actors in Unreal are connected though a gigantic list (well it is actually a dynamic array, but to make life easier think of it as a list) that exists only in the native C++ code. Without this list, actors would be just plain old objects. The base of this "list" is actually the native level object (the XLevel
property of all actors). This list exists on both client and server. When a client "receives" an actor, it is added and when its connection is closed (except with bNetTemporary), it is removed.
Spawning an actor automatically adds it at the end of the list. Note that LevelInfo (accessed via the Level
property of any actor) is always the first actor. Destroying an actor automatically removes it from the list.
UnrealScript's ForEach
command makes it easy to deal with large groups of actors, for example all of the actors in a level, or all of the actors within a certain distance of another actor. ForEach
works in conjunction with a special kind of function called iterator function whose purpose is to iterate through a list of actors. Most of these iterator functions use the native actor list, so sometimes it's faster to use For
to iterate through much smaller linked lists like the pawn list or one of the mutator lists.
Syntax
All iterator function use a similar syntax:
local aClassName aVariable; foreach IteratorFunction(class'aClassName', aVariable, other parameters) { // execute something here }
The variable used as the second parameter must declared to hold an instance of the class used as the first parameter. The class must be class'Actor'
or a subclass for all iterators except AllObjects and AllDataObjects which can use class'Object'
or any other Object subclass.
Iterators can also be called for other objects:
local aClassName aVariable; foreach anotherObject.IteratorFunction(class'aClassName', aVariable, other parameters) { // execute something here }
This syntax doesn't make sense for all iterator functions, though. It is useful when using an iterator function which returns objects based on the object it was called for (e.g. ZoneActors or ChildActors) or when you want to use an iterator that isn't available in your class. (e.g. DynamicActors from an Interaction)
Note that the game will crash with the error "Unknown code token 58" when the anotherObject
variable is None
. Also the actor iterators should only be called in a game environment. They will cause problems (e.g. a crash with "Unknown code token 31") when executed e.g. from BrushBuilder code in the editor.
Definitions
Object
- AllObjects (class<Object> BaseClass, out Object Object)
- Included in Deus Ex and Unreal Engine versions later than UT. Iterates through all objects, including all loaded classes.
Actor
- AllActors (class<Actor> BaseClass, out Actor Actor, optional name MatchTag)
- Iterates through all actors of the specified BaseClass in the level. These will be assigned to the variable you specified as the second parameter. If you specify an optional MatchTag, only includes actors which have a "Tag" variable matching the tag you specified. This will go through every actor in the level and is thus somewhat slow (this is not noticeable however unless it is called multiple times in one frame), so use it sparingly. If a more class specific list exists, such as
Level.PawnList
andLevel.NavigationPointList
, use those instead. - DynamicActors (class<Actor> BaseClass, out Actor Actor, optional name MatchTag)
- Iterates through all the actors that have
bStatic=False
. Works only (apparently) in Unreal Engine versions later than UT (v436). This is supposed to be faster thanAllActors
because it doesn't iterate through all the static actors. Again, if you specify an optional MatchTag, the iteration will only include those dynamic actors in your game that have a "Tag" variable that equals your MatchTag. - ChildActors (class<Actor> BaseClass, out Actor Actor)
- Iterates through all actors in the level which have their owner set to the class this is run on. This has the same speed hit as
AllActors
. - BasedActors (class<Actor> BaseClass, out Actor Actor)
- Iterates through all actors which are standing on the actor this is run on, i.e. all actors which have their
Base
property set to this actor. This has the same speed hit asAllActors
. - TouchingActors (class<Actor> BaseClass, out actor Actor)
- Iterates through all actors which are touching (interpenetrating) this actor. This seems to be pretty fast.
- TraceActors (class<Actor> BaseClass, out Actor Actor, out vector HitLoc, out vector HitNorm, vector End, optional vector Start, optional vector Extent)
- Iterates through all actors which touch a line traced from the Start point to the End point, using a box of collision extent Extent. On each iteration, HitLoc is set to the hit location, and HitNorm is set to an outward-pointing hit normal. This is as fast as any Trace.
- RadiusActors (class<Actor> BaseClass, out Actor Actor, float Radius, optional vector Loc)
- Iterates through all actors within a specified radius of the specified location (or if no location is specified, this actor's location). This has the same speed hit as
AllActors
. - VisibleActors (class<Actor> BaseClass, out Actor Actor, optional float Radius, optional vector Loc)
- Iterates through a list of all actors who are visible to the specified location (or if no location is specified, this actor's location). Here "visible" means "a line can connect some part of an actor and this actor's center without passing through level geometry", not "bHidden=False". This has the same speed hit as
AllActors
. - VisibleCollidingActors (class<Actor> BaseClass, out Actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden)
- Iterates through a list of all actors which are visible to the specified location (or if no location is specified, this actor's location) and have
bCollideActors=True
. Here "visible" does not mean "bHidden=False", but this can be changed through bIgnoreHidden. (just a guess) The bIgnoreHidden parameter might not be available in earlier engine versions. (prior to UT v436 or Unreal v226) Usually this is much faster thanAllActors
because it uses the collision hash instead of the much larger native actor list, but with a very high radius VisibleActors might be more efficient. - CollidingActors (class<Actor> BaseClass, out Actor Actor, float Radius, optional vector Loc)
- Iterates through all actors within the specified radius using the collision hash. (
bCollideActors=True
) This is slightly faster than RadiusActors with radii at least up to 2000UU and much faster than VisibleActors or VisibleCollidingActors due to the visibility check those iterators have to perform for each actor.
ZoneInfo
- ZoneActors (class<Actor> BaseClass, out Actor Actor)
- Iterates through all actors of type BaseClass within the acting ZoneInfo. Same speed hit as
AllActors
.
GameInfo
- AllDataObjects (class objClass, out Object obj, string packageName)
- Uhm...
Usage
Iterating actors is one of the most important concepts to understand in UnrealScripting. There are many times when this will be the only way for you to gain valid reference to other classes for use in your function, and as such, it is essential that you gain a very familiar understanding of the methods used in iterating.
AllActors is normally used with two parameters - the class, and a variable. The variable parameter may be a global, local, or argument variable, and there are situations when it is good to use each one. To use AllActors, first define a variable of the class you want to iterate. Next, designate the variable that will host the reference to this class object. Inside the brackets, specify what you want to happen each time an object of the specified class is found. The iterator variable is always equal to the last object that was found matching that class, so if you want to get a valid reference to each object in the game of a particular type, you would need to somehow assign that object to yet another variable inside the iterator, before it continues on to the next object of that class.
class MyMut extends Info; function PostBeginPlay() { local Pawn OnlyThisPawn; foreach AllActors(class'Pawn', OnlyThisPawn) { break; } }
This above code reads something like "Look for all actors in the game that are of the class 'Pawn'. When a Pawn is found is found, assign THAT Pawn to the variable OnlyThisPawn, then perform the statements within the next set of brackets. Once finished with those statements, look for the next actor of the class 'Pawn' and assign THAT pawn to the OnlyPawnVariable, overwriting the last value of the OnlyThisPawn variable." But, there is only one statement there! The break statement causes the foreach iterator to stop it's cycling through the Actors on the level. (It will stop looking for other Actors to assign to OnlyThisPawn). This is an extremely useful way to get a valid reference to an instance of a particular class when there isn't aren't any other ways of attaching to this class. In the example above, the iterator assigns the first actor of class'pawn' that it finds to the OnlyThisPawn variable, breaks out of the "ForEach" statement, and script execution continues through the rest of the function. You may now use the OnlyThisPawn variable without receiving the "Access None" error in the logfile, as long as there are valid Pawns in the level when you perform this iterator.
Typically, however, a ForEach statement should be used to perform a particular action on multiple instances of a class, to be most efficient. Avoid using extensive iterators in rapidly executing code (such as Tick), and instead try to place in situations where they are only executed once or at least rarely (PostBeginPlay, BeginState are good places). You should also avoid using iterators for assigning object variables, instead trying less resource-expensive methods of gaining valid references. For some ideas of how to do this, see Traversing Classes
Wormbo: Iterating through all Pawns is a bad example. Avoid using ForEach AllActors(class'Pawn', P)
on the server.For (P = Level.PawnList; P != None; P = P.NextPawn)
does the same and is much more efficient. Always look for a linked list that contains the actors you want to access before using ForEach AllActors(...)
.
Using Iterators From Objects
Ever have an Object and want to use an iterator but realized much to your frustration that they are all defined down in Actor? Well boys and girls, this is actually very easily worked around as demonstrated by the following example:
class MyObj extends Object; var Actor MyActorRef; function SomeNiftyFunc() { local Actor AnActor; foreach MyActorRef.AllActors( class'Actor', AnActor ) break; }
Since iterators are just normal functions you can treat them as such and call them from any other Object that has a reference to them. Just be sure that your Actor reference is valid before you attempt to call an iterator on it, otherwise all sorts of "bad things" can happen.
function SomeNiftyFunc() { local Actor AnActor; if ( MyActorRef == NONE || MyActorRef.bDeleteMe ) return; foreach MyActorRef.RadiusActors( class'Actor', AnActor, 500 ) break; }
Related Topics
- Tim Sweeney's reference: UnrealScript Language Reference/Advanced Language Features
- Flow Syntax
- Optimization Techniques – If your framerate drops considerably when using iterators.
- Linked List/Existing Lists In Unreal Tournament also has some info on execution speed of the various iterator functions
Comments
COuld we have more examples? I don't really understand
AllObjects (class<Object> BaseClass, out Object Object)
since the code I see looks like:
foreach AllObjects(class'Actor', A)
where is the BaseClass variable? Can I write
foreach AllObjects(class'SomeClassOrOther', A)
Wormbo: Is the Syntax section enough to answer this question?
Tarquin: Yup. It's great! Thanks I've actually managed today to get iterators to work in Brushbuilder. I'll post about it when I've got it all worked out.
Foxpaw: Destroying actors in Iterators seems to cause some strangeness. The following code caused mysterioud GPFs for the longest time for me:
foreach AllObjects( class'VehicularThing', Old ) Old.Destroy();
It wouldn't crash as soon as I executed it, but would go for about 8 cycles or so before crashing. I believe this may cause some kind of a memory leak or something, possibly due to the internal workings of the iterators. I stopped the GPFs by doing the following, and it hasn't caused a crash since:
foreach AllObjects( class'VehicularThing', Old ) MarkedMen[MarkedMen.Length] = Old; for (i=0;i<MarkedMen.Length;i++) MarkedMen[i].Destroy();
Daid303: The killall cheat never crashed for me... but it uses DynamicActors, why are you using AllObjects? (I can't think of any slower function)
exec function KillAll(class<actor> aClass) { local Actor A; if ( ClassIsChildOf(aClass, class'AIController') ) { Level.Game.KillBots(Level.Game.NumBots); return; } if ( ClassIsChildOf(aClass, class'Pawn') ) { KillAllPawns(class<Pawn>(aClass)); return; } ForEach DynamicActors(class 'Actor', A) if ( ClassIsChildOf(A.class, aClass) ) A.Destroy(); }
Foxpaw: It may only apply to AllObjects, since that one operates on non-actors as well, and the notion of an object having been destroyed in a previous iteration doesn't really apply for garbage collection, which is what it was designed for. I'm using AllObjects because it's being called from a non-actor class, and only actors can use the AllActors, DynamicActors, etc. iterators. As far as I can tell only AllObjects is valid for use in classes not derived from actor.
Wormbo: Avoid AllObjects when AllActors or DynamicActors gives you the same results. Also when UsingAllObjects, make sure the actor you try to Destroy() isn't already destroyed (i.e. bDeleteMe should not yet be True).
Foxpaw: Well, objects not derived from Actor can't use any iterators except AllObjects, so my options are limited. Plus, since it's in the GUI, I don't really have to worry much about framerate.
Dma: Actually, you can use any iterator even in a static function in a non-actor class by doing something like this:
static final function Test() { local PlayerController PC; foreach class'Object'.AllObjects(class'PlayerController', PC) { foreach PC.AllActors(...) { // ... } return; } }