I don't need to test my programs. I have an error-correcting modem.

ForEach loop

From Unreal Wiki, The Unreal Engine Documentation Site
Revision as of 14:53, 14 November 2010 by Wormbo (Talk | contribs) (Undo revision 44119 by 82.73.101.51 (Talk) - That's actually how you log stuff in UE3)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

The ForEach loop in UnrealScript can be used to iterate over the output of iterator functions. Additionally, Unreal Engine 3 provides a special version of ForEach that iterates over the elements of a dynamic array.

Syntax[edit]

The general syntax of the regular ForEach loop is:

ForEach iteratorfunction(parameters) {
  ...
}

The first two parameters of iterator functions are always a parameter of a class limiter type and an out parameter of the same type as the first parameter's meta class, for example class<Actor> and Actor respectively. Through special compiler "magic", the accepted type of variables for the second parameter is further limited if the first parameter specifies a subclass of the declared meta class. (see examples below for details)

The special syntax for dynamic array in Unreal Engine 3 is:

ForEach dynarray(valuevariable) {
  ...
}

If the dynarray variable is of type array<X>, the valuevariable must be declared as type X.

If you also need access the the array index corresponding to the current value, use:

ForEach dynarray(valuevariable, indexvariable) {
  ...
}

The indexvariable must be declared as type int.

Iterator functions[edit]

Iterator functions, or "iterators" for short, are native functions that have been declared with the special modifier iterator. Iterators must be native and don't have a return value. They can only be called as part of a ForEach loop and usually have at least one out parameter.

A typical iterator function takes a class value as its first parameter and an object variable as its second parameter, which is defined with the modifier out. Most iterator functions have more than two parameters, some of them also declared as out, but most of them are optional.

A typical example is the VisibleCollidingActors function in the Actor class:

native(312) final iterator function VisibleCollidingActors(class<actor> BaseClass, out actor Actor, optional float Radius, optional vector Loc, optional bool bIgnoreHidden);

Examples[edit]

A typical iterator function call might look like this example:

function PokeTriggersFor(Pawn Other)
{
  local Trigger T;
 
  if (Other == None)
    return; // ForEach doesn't handle Accessed None gracefully!
 
  foreach Other.RadiusActors(class'Trigger', T, 100.0) {
    T.Touch(Other);
  }
}

This example shows various features of using iterator functions in a ForEach loop:

  • You can access iterators of other objects than the one containing the code. Just make sure you don't access the iterator function though None – before Unreal Engine 3 the game will crash mercilessly with a cryptic error message in that case! In this example an If statement performs a None check before the iterator is executed.
  • If you specify a specific class as the first parameter, the second parameter must be of the same type. It would actually be a compiler error if the local variable T was declared as type Actor.

The array iterators of Unreal Engine 3 are straight forward to use. The following example iterates over the GeneratedEvents array of the Actor containing this piece of code:

function IterateEvents()
{
  local SequenceEvent E;
 
  foreach GeneratedEvents(E) {
    `log(E);
  }
}

Like in the previous example, you can also iterate over dynamic arrays in other objects. Just remember to perform a check for None first to prevent log warnings.

Pitfalls[edit]

A foreach loop iterates over a list of values. How this list is implemented or how the engine iterates over it depends on the iterator function used. Some iterators, such as TraceActors construct a separate list and iterate over it. Others, such as AllActors or a dynamic array iterator, operate on a list that is directly or indirectly accessible inside the loop. Pay special attention when you modify the list in some way. Adding items to the list, for example spawning actors during an AllActors loop, can create an infinite loop where the engine continues to create actors until it runs out of memory or crashes for other reasons! Similarly, you should not modify a dynamic array while iterating over it.

It is possible to use foreach loops in state code. However, using latent functions inside these loops may not work as expected.