Iterators, AllActors, Tracing

In UnrealScript, an iterator is a type of specialized loop that allows you to go over a number of objects in the world according to a set of criteria.

Actor Iterators

Let's look at the iterators available through the Actor class. To use any of the following iterators, we must write the iteration loop in a member function in a class that is a descendant of Actor. The following list was fetched from the UDN UnrealScript Iterators Reference:

  • AllActors ( class BaseClass, out actor Actor, optional class InterfaceClass )
    • Iterates through all actors in the level. If you specify an optional InterfaceClass, only includes actors that implement the InterfaceClass.
  • DynamicActors( class BaseClass, out actor Actor, optional class InterfaceClass )
    • Iterates through all actors with bStatic=false
  • ChildActors( class BaseClass, out actor Actor )
    • Iterates through all actors owned by this actor.
  • BasedActors( class BaseClass, out actor Actor )
    • Iterates through all actors which use this actor as a base.
  • TouchingActors( class BaseClass, out actor Actor )
    • Iterates through all actors which are touching (interpenetrating) this actor.
  • TraceActors( class 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.
  • OverlappingActors( class BaseClass, out actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden )
    • Iterates through all actors within a specified Radius of the specified location (or if none is specified, this actor's location).
  • VisibleActors( class 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).
  • VisibleCollidingActors ( class BaseClass, out actor Actor, float Radius, optional vector Loc, optional bool bIgnoreHidden )
    • returns all colliding (bCollideActors==true) actors within a certain radius for which a trace from Loc (which defaults to caller's Location) to that actor's Location does not hit the world. Much faster than AllActors() since it uses the collision hash.
  • CollidingActors ( class BaseClass, out actor Actor, float Radius, optional vector Loc )
    • returns colliding (bCollideActors==true) actors within a certain Radius. Much faster than AllActors() for reasonably small radii since it uses the collision hash
  • ComponentList( class BaseClass, out ActorComponent out_Component )
    • returns all components in the actor's Component's list
  • AllOwnedComponents( class BaseClass, out ActorComponent OutComponent )
    • returns all components attached "directly or indirectly" to the actor
  • LocalPlayerControllers( class BaseClass, out PlayerController PC)
    • returns all local PlayerControllers

Using Iterators, AllActors

The simplest iterator is AllActors. It allows you to go through all of the actors in a level that inherit from a particular base class. Let's see a simple example of using AllActors:

function Foobar()
{
    local NavigationPoint point;
    foreach AllActors(class'NavigationPoint', point)
    {
        `Log("Iterating over navigation point "$point);
    }
}

Iterators are invoked with the special foreach syntax followed by the name of the iterator, passing it any parameters in parameters like a function. Following the invocation, a code body surrounded by curly braces must be present; this code body will be invoked with every actor in the level matching the iterator's criteria.

The AllActors iterator receives two parameters:

  • class BaseClass
    • This is the base class of the actors we are interested in iterating over. Our loop body will only be invoked with actors which are descendants of this class
  • out Actor Actor
    • This is the variable that will be used to store the current object we are iterating over. This is similar to a counter in a for loop.
    • Note that even though the type of this variable is Actor, the variable that you pass the iterator must be equivalent to or an ancestor of the class that you pass in through BaseClass

In the example above, the iterator loop did the following:

  • The base class that was passed in was NavigationPoint so the loop body would have been called once for every instance of a NavigationPoint object in the level
  • The iteration variable passed in was point. Note that the type of point was NavigationPoint to match the class that we passed in as the first argument
  • For each NavigationPoint object in the level, the following message would have been logged: Iterating over navigation point <name_of_navigation_point>

TraceActors

While AllActors is a very useful iterator, it is very generic. An example of a more niche and complex iterator is TraceActors. TraceActors shoots a line through the world beginning at a specific coordinate and ending at a specific coordinate, iterating over actors intersecting that line. Let's look at the parameters of this iterator:

  • class BaseClass
    • Like AllActors, TraceActors will process only actors that are descendants of a given base class which is passed in here
  • out Actor Actor
    • This is the iteration variable. Even though the specification shows this parameter's type as Actor, it must be equivalent to or an ancestor of the class that you pass in through BaseClass
  • out vector HitLoc
    • The location in the world at which the trace line makes contact with the current iteration actor
  • out vector HitNorm
    • The normal of the surface on the actor that the trace line makes contact with, facing out of the actor
  • vector end
    • The end point of the trace
  • optional vector start
    • The starting point of the trace. Defaults to this actor's location
  • optional vector Extent
    • The extent of the trace line, effectively the radii of a box that is swept along the trace line. This should typically be left out of the iterator call.

Here's an example of using the trace actors iterator:

function Foobar()
{
    local Pawn iterPawn;
    local vector hitLoc, hitNorm, end, start;

    end = vect(100, 0, 0);
    start = vect(0, 0, 0);

    foreach TraceActors(class'Pawn', iterPawn, hitLoc, hitNorm, end, start)
    {
        `Log("Contacted pawn "$iterPawn$" at location "$hitLoc$" and normal "$hitNorm);
    }
}

Let's break down what this example will do:

  • It will iterate over all actors of base class Pawn, storing the iteration actor in iterPawn
  • The trace line will start at (0, 0, 0) and end at (100, 0, 0)
    • This means that if a Pawn was positioned at (50, 10, 10) and had a collision object big enough to contact the trace line, eg a cylinder with a radius of at least 10 and a height of at least 10 (to account for the pawn's position being 10 on the Y and 10 on the Z away from the line), it would be considered for iteration

An alternative way to trace actors is to use the Trace function on Actor which will find only the first hit actor, or the world, or None. Read more about Actor's Trace function at beyondunreal wiki

Other Iterators

The other iterators have more specific use cases. Read about them in the above UDN reference pages for more information.