Cogito, ergo sum

Dynamic arrays

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search

Dynamic arrays are a special composite type in UnrealScript that contains a variable number of elements in a well-defined order. These elements all have the same type, called the "inner type" of the array.

UnrealScript's dynamic arrays are a true dynamic array implementation, i.e. unlike Java's dynamically-allocated fixed-size arrays they can be resized at runtime. The type declaration syntax was available (almost) from the start, but Unreal Engine 1 never provided any way to actually access or modify them at the UnrealScript level. In other words, dynamic arrays are fully usable in UnrealScript only in Unreal Engine 2 and later.

Unlike any other data type in UnrealScript, dynamic arrays have absolutely no support for replication. Attempting to replicate a dynamic array variable will have no effect on the remote instance of that variable. Attempting to use a dynamic array as parameter of a replicated function will result in the parameter being empty when the function is executed on the remote side.

Declaration syntax

Dynamic arrays are declared as part of the type:

array< type >

The inner type of a dynamic array can be a class limiter or the name of any other non-array type, including delegate types. Note that Unreal Engine 2 does not support dynamic arrays of type bool and the compiler will complain accordingly. Dynamic arrays of bool values are possible in Unreal Engine 3, though.

Be careful when declaring a dynamic array of a class limiter or delegate type. The compiler recognized two consecutive > characters as the operator >> and will fail with a syntax error. Insert whitespace to get around this limitation:

array< class< classname > >

A dynamic array type can be used in all places that allow a type definition. The following example code defines a class-global dynamic array of bytes and a function that uses dynamic arrays as return type and as the type of a parameter and a local variable:

var array<byte> ByteArray< SEMI >
 
function array<int> RoundAll(array<float> Values)
{
  local array<int> Result;
 
  //...
 
  return Result;
}

The only exception are type declarations of variables, struct members and function parameters that are declared as static arrays. In this case, the dynamic array declaration is ignored.

Usage in code

Dynamic arrays provide various ways for reading and manipulating the content and length of the array. All of these must be done through variables or struct members, dynamic arrays returned from functions must be assigned to a variable first.

Accessing array data

The entire array data can be passed around if the target variable or function parameter or return type is declared as a dynamic array of the same inner type as the source array. The array data is copied in this process, so afterwards there are two independent arrays with the same data, modifications to one of them won't affect the other array's data in any way.

To access values of individual array elements, use the following syntax:

arrayreference[index]

The index may be any non-negative that is smaller than the length of the array. Any other values, i.e. negative numbers or values >= the length of the array, will return the null value of the array's inner type and write an out-of-bounds warning message to the main log file.

The same syntax can be used for assigning values to individual array elements. In this case the index must be non-negative, but may exceed the array length. If the index is equal to or greater than the current length of the array, the array grows so its last element has the specified index, i.e. its length is now index + 1. If you can estimate the final number of elements an array will have, you can resize it manually before assigning the values.

An access method only available in Unreal Engine 3 is iteration via the foreach loop:

foreach arrayreference(valuevariable , [indexvariable]) {
  ...
}

You can just loop over the values, or also let the loop fill in a variable with the current element's index. The value variable must be of the same type as the array's inner type, the index variable must be of type int. In Unreal Engine 2 you have to use a regular for loop with a counter variable to iterate over the array:

for (index = 0; index < arrayreference.Length; ++index) {
  value = arrayreference[index];
  //...
}

Accessing and modifying the array length

The length of an array can be retrieved with the following syntax:

arrayreference.Length

The length of an array can be set with the following syntax:

arrayreference.Length=Value

If used on the left side of the simple assignment operator, this syntax can also be used to add or remove elements to/from the array. Like all operations that add elements to the array, this will initialize the new elements with the null value of the array's inner type. Important: The Length attribute must not be used on the left side of combined assignment operators or passed to a function parameter declared with the out modifier!

It is possible to clear a dynamic array by setting its length variable to 0.

Any reduction or increase to the array's Length variable will add or remove elements starting at the end of the array.

Inserting and removing elements

To insert elements anywhere in the array, you can use the following syntax:

arrayreference.Insert(index, count);

This will insert count elements into the array, so that the first inserted element ends up at the specified index. The element originally located at index and any following elements are moved to make room for the new elements. The inserted elements are initialized with null values.

To remove elements from anywhere in the array, use the following syntax:

arrayreference.Remove(index, count);

This will remove count successive elements, starting with the element at index. Elements after the removed array section are moved to close the gap.

Additional array operations in Unreal Engine 3

To add empty elements at the end of the array, use:

arrayreference.Add(count);

This has the same effect as any of the following operations, but the intention is much more obvious:

  • arrayreference.Length = arrayreference.Length + count;
  • arrayreference.Insert(arrayreference.Length, count);

To add a single value to the end of the array, use:

arrayreference.AddItem(value);

This is basically the same as arrayreference[arrayreference.Length] = value;.

Inserting individual items in the middle of the array can be done with the following syntax:

arrayreference.InsertItem(index, value);

The corresponding Unreal Engine 2 code would be arrayreference.Insert(index, 1); arrayreference[index] = value;, i.e. two statements.

To remove all occurrences of a specific value from the array, you can use:

arrayreference.RemoveItem(value);

This will perform a linear search for the value and remove any instance it finds. In Unreal Engine 2 you need something like this for loop to do the same:

local int i;
 
for (i = 0; i < arrayreference.length; ++i) {
  if (arrayreference[i] == value) {
    arrayreference.Remove(i--, 1);
  }
}

Unreal Engine 3 also offers two methods to search for values in an array. The simple version just looks for a value:

arrayreference.Find(value)

This returns the index of the first element containing the specified value. If the array doesn't contain this value, INDEX_NONE is returned, i.e. the value -1. For dynamic array of structs, a second version of Find is available, which looks for values of struct members:

arrayreference.Find(membername, value)

The member name must be a name literal specifying the name of a struct member variable.

Starting with newer versions of the Unreal Engine 3 there is also a simply way to sort an array:

arrayreference.Sort(comparefunction)

The comparefunction is the name of a function that takes two parameters of the array's element type and returns a value of type int. Negative return values indicate that the first parameter should come after the second, i.e. the values are not in order. Positive return values mean the first element should come before the second, i.e. they are in order. Zero means the elements are equal and thus in order. The magnitude of the positive or negative return value don't matter, only its sign.

Usage in defaultproperties block

The default data for a dynamic array can either be specified per element, similar to static arrays, or for the entire array at once.

The per-element syntax is identical to that of static arrays:

arrayvariable[index] = value

For historical reasons, you can also use round parentheses to enclose the array index.

To specify all elements at once, or to clear an array from a superclass, use the following syntax:

arrayvariable = (value,value,...)

This will set the default value of the array variable to contain the specified number of elements with the specified values. A pair of empty parentheses, i.e. (), will explicitly clear the array. As always with defaultproperties, you can not execute any code here. For Unreal Engine 2 this includes not being able to use declared constants.

Additional operations in Unreal Engine 3

In Unreal Engine 3 you can use more convenient operations to manipulate the default values of dynamic arrays based on their parent class default data:

  • arrayvariable.Empty clears the entire array
  • arrayvariable.Add(value) adds the value to the end of the array
  • arrayvariable.Remove(value) removes all occurrences of the specified value from the array
  • arrayvariable.RemoveIndex(index) removes the element with the specified index
  • arrayvariable.Replace(search,replacement) replaces all occurrences of the search value with the replacement value

These operations can be mixed with regular array default values and will be "executed" at compile-time in the order they are found.

Suppose, class X contains an array called values that was filled with the following default data:

values = (1,2,3,4,5,4,3,2,1)

Now a class Y that extends X could modify the inherited default array data:

values.Remove(4)
values.Replace(1,10)
values.Add(1)

Its actual default array data now is (10,2,3,5,3,2,10,1).

Download (not export!) the original UT3 UnrealScript source files for more examples.

Usage in UnrealEd

An actor's Skins material array property in UnrealEd 3.

Using and modifying dynamic array properties in UnrealEd property windows is pretty straight-forward with the buttons provided by the property window.

UT3-UnrealEd-Properties-Empty.png Empty
Removes all array elements.
UT3-UnrealEd-Properties-Add.png Add
Adds an empty element at the end of the array.
UT3-UnrealEd-Properties-Duplicate.png Duplicate
Duplicates the array element. (This button is not available in UnrealEd 3.)
UT3-UnrealEd-Properties-Remove.png Delete
Removes this array element.
UT3-UnrealEd-Properties-Insert.png Insert
Inserts an empty element above this one.

See also