You can operate dynamic arrays in UnrealScript on Unreal 227, and UT's XC_Engine.
What are dynamic arrays then? Let's talk about memory allocation.
You have an object, be it a struct, class or whatever.
This 'object' can be a part of any other object, it can exist on any part of the system, including the CPU cache's... and even where you don't expect to see them.
As a matter of fact, I pick some random 12 bytes in any part of your system's memory and those 12 bytes can be a X,Y,Z FLOAT vector, the same memory I can read it as a 'rotator' type if I wanted to.
Bottom line is, objects are what they are because of how we and our code candles them.
So before we continue, learn this well:
An object can be anywhere, a chunk of memory can be anything
===============================
Let's continue with arrays.
In UnrealScript the most basic type of array is the static array, it is a chunk of memory defined within the struct, class or stack you're operating on.
In the case of INT arrays, INT is a datatype 4 bytes long and therefore each element of an INT array will require 4 bytes.
A INT array of 128 elements long will take 4*128 bytes of
contiguous memory.
Contiguous, the elements of an array will never occupy different regions of memory (virtual memory we're talking about) and the access method is very simple.
In UnrealScript and other high level languages, access via array index is absolute offset.
Meaning, we see where the element 0 is, then we move the registers ahead using SIZE*INDEX (4*i) to locate the memory region we want to access.
C++ compilers will usually optimize loops to add (SIZE) to the iterator registers after every loop, etc.
It's very simple to do and just like any other variable, no extra steps or anything.
UnrealScript defines an opcode that takes a 'variable' opcode, and a 'index' opcode as parameters to understand what array and what index you want to access for read or writing.
Opcodes unlike constants can result in anything, even function calls, which explains why you can sometimes call functions inside a [] block, or why you can specify an array from a different object (Object2.OtherArray).
When it comes to UnrealScript,
the Dynamic Array accesor opcode (0x0F I believe) is identical to the static array one, they are compiled the same but with a different index so it gets treated internally like a dynamic array.
But of course, both things are not identical.
Dynamic arrays can have any size and thus, can be altered so that their size changes, so we need extra functions to know these details and to do said alterations.
Now you wonder... If static code already has predefined variable offsets and precompiled the way to operate on those...
how in earth is it possible to have an object that changes size?
It's simple in the case of Unreal's FArray types: 12 bytes
- Data pointer (offset 0)
- Array number (current max, offset 4)
- Array max (maximum allocated, offset
FArray is initally created with all three values zero'd, which automatically translates to: no allocated memory, zero elements.
The Data pointer indicates where our data is, it's a chunk of memory we dynamically allocate for our purposes, in this case: simple data storage reserved by the program.
When we issue the first size change order via ADD, INSERT or using the [] assignment operator (in write mode, it does ADD internally), the internal code will fetch some free memory using arbitrary rules.
Let's say... we want to insert 8 INT's, the code will probably fetch 44 bytes and the result will be this:
- Data pointer = address of new memory
- Array number = 8
- Array max = 11 (44 / sizeof(INT))
Memory allocation and deallocation can be very expensive and fetching additional memory will allow us to more efficiently add elements one by one, for example.
So let's say... we do Array_Add(1); and add one more element, we get:
- Data pointer = same as before
- Array number = 9
- Array max = 11
Following these arbitrary rules, the code will attempt to get more memory (using a different address) or will attempt to shrink the size of the allocated memory when necessary.
All done internally as you add, remove, set stuff on UnrealScript.
With the internals over, how do we efficently code in UnrealScript, and how do we fulfill our purposes?
Some simple things to know:
- If you intend an array's data to be known to clients connected to a server, you cannot use dynamic arrays, replication doesn't support those.
- If you don't want to loop over a full static array over and over, define an 'ArrayNum' variable yourself and imitate the behaviour of a dynamic array.
Code: Select all
Basically: var int Data[512]; var int DataCount; For (i=0 ; i<DataCount ; i++ ) Log("Found data: "$Data[i]);
- If you know how many things you're going to operate with in an algorithm, always use static arrays.
- If you constantly need to keep an element order, even when you remove elements from the middle of an array, consider using dynamic arrays.
- Don't do dynamic arrays inside functions, sometimes using a 512-sized static array is faster and easier to debug.