Gah - a solution with more questions. – EntropicLqd

Difference between revisions of "Types"

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to: navigation, search
m (String: only literals are limited + details about 'button')
m (Undo revision 46196 by SeriousBarbie (talk) there's more than just @ to concatinate strings, but this page isn't for operators)
 
(6 intermediate revisions by 5 users not shown)
Line 22: Line 22:
 
UnrealScript has a [[wp:single precision|single precision]] [[wp:floating point|floating point]] type called '''float'''. The possible float values are distributed over the huge range of about 3.403·10<sup>38</sup> to -3.403·10<sup>38</sup>. The smallest possible value greater than 0 is about 1.175·10<sup>-38</sup>. Generally, float values have a precision of about 6 or 7 decimal digits.
 
UnrealScript has a [[wp:single precision|single precision]] [[wp:floating point|floating point]] type called '''float'''. The possible float values are distributed over the huge range of about 3.403·10<sup>38</sup> to -3.403·10<sup>38</sup>. The smallest possible value greater than 0 is about 1.175·10<sup>-38</sup>. Generally, float values have a precision of about 6 or 7 decimal digits.
  
[[Literals#Float numbers|Float literals]] can either be specified in decimal or scientific notation. For example the literal 1.2e3 means 1.2·10<sup>3</sup> = 1230. Note that float literals must always contain the decimal point, even when using scientific notation, and must always start with a number or with the minus sign followed by a number. Unfortunately, negative exponents are not allowed in scientific notation. A hexadecimal representation like in Java is not supported.
+
[[Literals#Float numbers|Float literals]] can either be specified in decimal or scientific notation. For example the literal 1.2e3 means 1.2·10<sup>3</sup> = 1200. Note that float literals must always contain the decimal point, even when using scientific notation, and must always start with a number or with the minus sign followed by a number. Unfortunately, negative exponents are not allowed in scientific notation. A hexadecimal representation like in Java is not supported.
  
 
If a floating point operation has a result that exceeds the highest or lowest possible number, the return value has the special value of positive or negative infinity respectively. Invalid operations such as division by zero or adding positive and negative infinity return the special value ''NaN'', "Not a Number". Be careful about those three special values as they will propagate. That means, if you subtract, add, multiply or divide infinity values, the result will be infinity again. If you perform an operation with the ''NaN'' value, the result will either be ''NaN'' again or (for comparison operators) something totally unexpected. For example if you perform the operation <code>a = x / 0</code>, variable a will contain ''NaN''. Now the comparison <code>a == a</code> will actually return the value ''false''! Unlike ''NaN'', infinity values will behave as expected if used in comparison operations, that is positive infinity is greater than any other value, negative infinity is smaller than any other value.
 
If a floating point operation has a result that exceeds the highest or lowest possible number, the return value has the special value of positive or negative infinity respectively. Invalid operations such as division by zero or adding positive and negative infinity return the special value ''NaN'', "Not a Number". Be careful about those three special values as they will propagate. That means, if you subtract, add, multiply or divide infinity values, the result will be infinity again. If you perform an operation with the ''NaN'' value, the result will either be ''NaN'' again or (for comparison operators) something totally unexpected. For example if you perform the operation <code>a = x / 0</code>, variable a will contain ''NaN''. Now the comparison <code>a == a</code> will actually return the value ''false''! Unlike ''NaN'', infinity values will behave as expected if used in comparison operations, that is positive infinity is greater than any other value, negative infinity is smaller than any other value.
Line 42: Line 42:
 
The data type '''name''' is a very unusual one. To the programmer it appears a lot like a case-insensitive string with very limited character set. Every object and every class has a name, but names are also used for a variety of other things, such as identifying [[states]], code [[labels]], trigger events or bones of a [[skeletal mesh]].
 
The data type '''name''' is a very unusual one. To the programmer it appears a lot like a case-insensitive string with very limited character set. Every object and every class has a name, but names are also used for a variety of other things, such as identifying [[states]], code [[labels]], trigger events or bones of a [[skeletal mesh]].
  
[[Literals#Names|Name literals]] are enclosed in single quotes and may contain the letters A to Z, both upper and lowercase, the numbers 0 to 9, the underscore character _ and the space character. Names are limited to a length of up to 63 characters.
+
[[Literals#Names|Name literals]] are enclosed in single quotes and may contain the letters A to Z, both upper and lowercase, the numbers 0 to 9, the underscore character _, the hyphen character -, and the space character. This could be represented in [[wp:regular expression|regex]] as <code>([a-zA-Z0-9_\- ]*)</code>. Names are limited to a length of up to 63 characters.
  
 
Internally names are represented as int values, which makes sense since names are used in many places and would take up a lot of space if represented as strings. At runtime, the first mentioned string representation of a name is stored in the global name table. Whenever a name value is to a string through [[typecasting]], the string representation from the name table is used. This means that even though you could use the name literal <code>'cOnTrOlLeR'</code> in your code, it would most likely be represented by the string <code>Controller</code> instead, because that's the spelling used for the name of the class with that name.
 
Internally names are represented as int values, which makes sense since names are used in many places and would take up a lot of space if represented as strings. At runtime, the first mentioned string representation of a name is stored in the global name table. Whenever a name value is to a string through [[typecasting]], the string representation from the name table is used. This means that even though you could use the name literal <code>'cOnTrOlLeR'</code> in your code, it would most likely be represented by the string <code>Controller</code> instead, because that's the spelling used for the name of the class with that name.
Line 106: Line 106:
  
 
In [[Unreal Engine 1]], dynamic arrays can be declared, but there's no way to access them. Only starting with [[Unreal Engine 3]], dynamic arrays of type bool can be used. (You can declare dynamic bool arrays in Unreal Engine 2, but they don't work.) It is not possible to directly use a dynamic array type in other static or dynamic arrays. It is possible to wrap other arrays or bool variables in a struct type and create a dynamic array of that struct type, though. Function parameters that are dynamic arrays may not be optional. There are no literals for dynamic arrays.
 
In [[Unreal Engine 1]], dynamic arrays can be declared, but there's no way to access them. Only starting with [[Unreal Engine 3]], dynamic arrays of type bool can be used. (You can declare dynamic bool arrays in Unreal Engine 2, but they don't work.) It is not possible to directly use a dynamic array type in other static or dynamic arrays. It is possible to wrap other arrays or bool variables in a struct type and create a dynamic array of that struct type, though. Function parameters that are dynamic arrays may not be optional. There are no literals for dynamic arrays.
 +
 +
===Multi-dimensional arrays===
 +
{{main|multi-dimensional arrays}}
 +
Multi-dimensional and jagged arrays are not supported in UnrealScript. You can work around that either by using an array of [[structs]] that contain an array or by performing index arithmetics on any kind of one-dimensional array.
  
 
===Map===
 
===Map===
{{main|Map}}
 
 
See [[wp:Associative_array|Associative array]], [[wp:Map_(C%2B%2B)|C++ Map]] and [http://www.google.be/search?q=c%23+dictionary C# Dictionary].
 
See [[wp:Associative_array|Associative array]], [[wp:Map_(C%2B%2B)|C++ Map]] and [http://www.google.be/search?q=c%23+dictionary C# Dictionary].
  

Latest revision as of 22:57, 28 August 2015

UnrealScript is a strongly-typed language and has various built-in data types. UnrealScript types can be divided in three general groups: primitive types, reference types and composite types.

Primitive types[edit]

A primitive type only consists of a single and usually simple value. Variables declared of a primitive type directly contain that value and when assigning that value to another variable or passing it to a function call, a new copy of the value is created. Modifications to that copy have absolutely no effect on the original value still stored in the source variable.

Int[edit]

UnrealScript has two integer types and int is the larger of them. Int values are integer numbers in the range -2147483648 to 2147483647, in other words signed 32 bit values.

Int literals can be specified in decimal or hexadecimal notation. Values exceeding the allowed range are truncated to the least significant 32 bits. For example the hexadecimal literal 0x100000005 actually represents the value 5.

Byte[edit]

The smaller of UnrealScript's two integer types is byte. Byte values are integer numbers in the range 0 to 255, in other words unsigned 8 bit values.

Any int literal can also be used in "byte context". If the value is outside the allowed range it will be truncated to the 8 least significant bits. For example the hexadecimal literal 0x100 (256) actually represents the value 0 and the decimal literal -1 represents the value 255.

Bool[edit]

UnrealScript's boolean type is bool and allows the values true and false. These are also the names of the boolean literals.

The bool type has some restrictions in UnrealScript. For example it's not possible to declare static or dynamic arrays of bool values in Unreal Engine generations 1 and 2 or to use the parameter modifier "out" on bool parameters in function declarations. Starting with Unreal Engine 3 dynamic arrays of bool are supported, even though the UnrealScript reference on UDN disagrees.

Float[edit]

UnrealScript has a single precision floating point type called float. The possible float values are distributed over the huge range of about 3.403·1038 to -3.403·1038. The smallest possible value greater than 0 is about 1.175·10-38. Generally, float values have a precision of about 6 or 7 decimal digits.

Float literals can either be specified in decimal or scientific notation. For example the literal 1.2e3 means 1.2·103 = 1200. Note that float literals must always contain the decimal point, even when using scientific notation, and must always start with a number or with the minus sign followed by a number. Unfortunately, negative exponents are not allowed in scientific notation. A hexadecimal representation like in Java is not supported.

If a floating point operation has a result that exceeds the highest or lowest possible number, the return value has the special value of positive or negative infinity respectively. Invalid operations such as division by zero or adding positive and negative infinity return the special value NaN, "Not a Number". Be careful about those three special values as they will propagate. That means, if you subtract, add, multiply or divide infinity values, the result will be infinity again. If you perform an operation with the NaN value, the result will either be NaN again or (for comparison operators) something totally unexpected. For example if you perform the operation a = x / 0, variable a will contain NaN. Now the comparison a == a will actually return the value false! Unlike NaN, infinity values will behave as expected if used in comparison operations, that is positive infinity is greater than any other value, negative infinity is smaller than any other value.

Technical information: As specified in the IEEE floating-point standard, the float type internally has a length of 32 bits and consists of a 23 bit fraction part, an 8 bit exponent and one sign bit. Especially the 23 bit fraction part (called the "mantissa") imposes a limit on floating point precision. When large int values greater than 223 or smaller than -223 are typecasted to float, they may get rounded.

String[edit]

UnrealScript has a character string data type called string. Strings can contain any combination of Unicode characters.

String literals are enclosed in double quotes and may not extends past the end of a line. Technically string literals (but not values) are allowed to have a length of up to 1023 characters. Internally strings are zero-terminated, which means no string can contain the null character because it would be recognized as the end of the string.

String values are immutable and UnrealScript neither provides "character" type nor allows direct access to individual string characters. There are, however, functions for extracting substrings and returning the Unicode value of the first character of a string. There's also a function for returning a string of length 1 containing a character corresponding to a specified Unicode value.

Very early builds of Unreal Engine 1 had a fixed-length string type, which was declared with the syntax string[length]. This type is no longer supported and only mentioned here in case you run into its declaration in old code snippets.

In Unreal Engine 2 (or at least UT2004) there also is an undocumented type called button that is an alias for the standard string type, but implies the Cache variable modifier. It is not actually used in stock code and there's no reason for you to ever declare a variable with the cache modifier, so this is purely informative.

Name[edit]

The data type name is a very unusual one. To the programmer it appears a lot like a case-insensitive string with very limited character set. Every object and every class has a name, but names are also used for a variety of other things, such as identifying states, code labels, trigger events or bones of a skeletal mesh.

Name literals are enclosed in single quotes and may contain the letters A to Z, both upper and lowercase, the numbers 0 to 9, the underscore character _, the hyphen character -, and the space character. This could be represented in regex as ([a-zA-Z0-9_\- ]*). Names are limited to a length of up to 63 characters.

Internally names are represented as int values, which makes sense since names are used in many places and would take up a lot of space if represented as strings. At runtime, the first mentioned string representation of a name is stored in the global name table. Whenever a name value is to a string through typecasting, the string representation from the name table is used. This means that even though you could use the name literal 'cOnTrOlLeR' in your code, it would most likely be represented by the string Controller instead, because that's the spelling used for the name of the class with that name.

Newer builds of the Unreal Engine 3 provides an additional way for specifying values of type name via the NameOf() pseudo-function. Similar to the ArrayCount() pseudo-function, NameOf() is replaced with a name constant by the compiler. The parameter for NameOf() is either a variable or function name for use in ReplicatedEvent() or with the various Timer management functions.

Enum[edit]

Main article: Enums

An enum type is a named list of identifiers that act as literals for the values of the enum type. UnrealScript's enumerated types are a bit like "glorified integer values", similar to C++ enumerations. The first value of an enum type corresponds to 0, the second value to 1, and so on.

Reference types[edit]

Unlike variables of primitive types, variables declared as a reference type only contain a reference to the actual data. When assigning a reference type value to a variable or passing it to function calls, only the reference, not the referenced data, is copied. As a result it is possible that two reference type variables point to the same data and changes made to the data through one variable are immediately visible through the other.

Object[edit]

An object reference does not contain an object, it only points to (i.e. "reference") an instance of an object. That means the object reference's value actually is a pointer, not an object. Different object references may point to the same object. An object reference may also point to no object at all.

Object references can be restricted to instances of a certain class. For example, an object reference might only accept instances of the class WebApplication, which also includes instances of WebApplication subclasses like UTServerAdmin.

Object literals start with the name of the object's class, followed by the qualified or unqualified name of the object instance to reference, enclosed in single quotes. It is also possible to specify a literal for the empty object reference with the keyword None. Another special object literal is the keyword Self, which references the object instance executing the current function or state code. It is not available in static functions, because those functions are not executed in the context of an object instance but of an object class.

Actor[edit]

Actor references are basically the same as object references, just restricted to Actor or one of its subclasses. The only difference to non-actor references is, that the Actor class provides a Destroy method. This method not only gets rid of the actor instance it was called on, but also implicitly sets all references to that actor instance to none.

Most of your object references will probably be actor references, but apart from None and Self you will rarely encounter object literals of type Actor or one of its subclasses. In fact, Actor-type object literals are forbidden in UnrealScript code prior to Unreal Engine 3. Mappers sometimes see actor literals in the property window of various level objects, but UnrealScript programmers usually won't use them. Most actor literals in Unreal Engine 3 source code are archetypes in exported defaultproperties blocks.

Interface[edit]

Main article: Interfaces

Interface references are also object references, but restricted to an interface type. This kind of reference can point to any object instance of a class implementing that interface.

Class[edit]

Main article: Classes

A class reference is very similar to an object reference, except that it is restricted to the type Class. Class references can be further restricted to a certain meta class, that means the type of referenced class. Such a restricted class reference is called a class limiter and is denoted by the keyword Class followed by the name of the meta class in angle brackets. For example class<Info> denotes a reference that can point to the class Info or one of its subclasses.

Class literals are specified in the same way as other object literals. The type of reference, here class, followed by the class name, optionally qualified with the containing package name, and enclosed in single quotes. For example class'Info' or class'Engine.Info' references the Info class located in the Engine package. The special object literal None can be used for class references and means "no class".

One important restriction of class references is the lack of interface support. Classes implementing a certain interface can be anywhere in the class hierarchy, but class limiters only support direct inheritance. This means, that if you want a reference to classes implementing a certain interface, you need to use a generic class reference or the class limiter class<Object>. A reference of type class<Interface> would only allow references to the interface class itself (or any of its subinterfaces), but not to any class implementing the interface!

Delegate[edit]

Main article: Delegates

Delegates were introduced in Unreal Engine 2 and are function references. In Unreal Engine 2, delegates could only be declared using function syntax and replacing the keyword Function with the keyword Delegate. Unreal Engine 3 also provides a notation similar to class limiters or dynamic arrays that can be used as variable or parameter type. This notation starts with the keyword Delegate, followed by the name of a prototype delegate function declaration in angle brackets.

Function literals are only used for delegate assignments and look more like a variable access than a literal. Basically you reference the object instance containing the function you want to assign to a delegate property (unless, of course, the function is contained in the same object instance as the code doing the assignment), followed by a dot and the pure function name without anything afterwards. As with object references, the keyword None means "no function". For delegate function declarations this means the default body, if available, is executed when the delegate is called.

Pointer[edit]

Also starting with Unreal Engine 2, UnrealScript has a generic pointer data type, but it only serves as a placeholder for pointer variables in native code. UnrealScript itself provides no way to access or modify pointer properties.

Composite types[edit]

Unlike all the other types described above, a composite type can contain more than one value. The composite types available in UnrealScript all work similar to primitive types: assigning them to other variables or passing them in function calls creates a copy of the data.

Struct[edit]

Main article: Structs

Structs (or structures) are a composition of a fixed number of values that may have different types. Struct types are no reference types, that means they are stored directly in the variable and copied as a whole when assigned to variables or passed as function parameters or returned as function result. Struct values are always replicated as a unit, but for a few structs like vector or rotator replication is not accurate due to bandwidth optimizations. Struct values may not be allowed for replication if the struct type is too large to fit in one network packet.

Except for vectors and rotators, there is no way to specify a complete struct value directly in code.

Static array[edit]

Main article: Static arrays

Static arrays are a composition of a fixed number of values with identical type. Static arrays can be passed as a whole as function parameters, though this will cause all values to be copied. They can't be assigned to variables or returned as function results, though. For replication, each element is considered separately. It is not possible to declare a static array of type bool or of a dynamic array type. Static arrays of a struct type containing bools or dynamic arrays are no problem, though. There are no literals for static arrays.

Dynamic array[edit]

Main article: Dynamic arrays

Dynamic arrays are also a composition of multiple values of the same type, but the actual number of values may change over time. Dynamic arrays can be assigned to variables, passed as function parameters and returned as function results, but every time the entire array is copied. They do not support replication at all.

In Unreal Engine 1, dynamic arrays can be declared, but there's no way to access them. Only starting with Unreal Engine 3, dynamic arrays of type bool can be used. (You can declare dynamic bool arrays in Unreal Engine 2, but they don't work.) It is not possible to directly use a dynamic array type in other static or dynamic arrays. It is possible to wrap other arrays or bool variables in a struct type and create a dynamic array of that struct type, though. Function parameters that are dynamic arrays may not be optional. There are no literals for dynamic arrays.

Multi-dimensional arrays[edit]

Main article: multi-dimensional arrays

Multi-dimensional and jagged arrays are not supported in UnrealScript. You can work around that either by using an array of structs that contain an array or by performing index arithmetics on any kind of one-dimensional array.

Map[edit]

See Associative array, C++ Map and C# Dictionary.

In Unreal Engine 1 and 2 you cannot use this feature yet so says the compiler error (Error, Map are not supported in UnrealScript yet).

In Unreal Engine 3 you can declare maps however you cannot access them yet with UnrealScript.