UnrealScript

UnrealScript is the programming language that is used to create gameplay code in the UDK. It is similar to Java conceptually and syntactically. This section will serve as a very basic outline as to what you can expect from UnrealScript; it does not cover everything that UnrealScript has to offer. I encourage you to read the UnrealScript reference on your own time, especially the overview section; this will get you up to speed on exactly what you will get from UnrealScript. With that in mind, UnrealScript offers the following familiar features:

  • Basic types
    • byte
    • int
    • bool
    • float
    • string
    • enumeration
    • name
      • A name is effectively a special string, used to hold the name of a symbol, eg a class name (ie var name someName;)
    • object reference (more on this below)
    • class reference restrictors (more on this below)
  • Structs
    • Similar to C/C++ structs
  • Classes
    • Single inheritance (multiple inheritance not allowed)
    • Object class at the root of the hierarchy
    • No constructors!
    • Garbage collected
  • Member variables
    • Variables are fixed type (ie closer to Java as opposed to JavaScript)
    • Declared through var keyword (ie var int myVariable;)
      • May need to be declared at top of file
    • Initial values of variables declared in Defaultproperties block
  • Functions
    • Function local variables
      • Declared through local keyword (ie local int myVariable;)
      • Must be declared at top of function
    • Function return types
    • Function parameters
    • Member functions (default)
    • Static functions
  • Variable length arrays declared through the Array<type> keyword (ie var Array myArrayVariable;)
  • Fixed length arrays declared through the [] syntax (ie var int[6] myFixedArrayVariable;)

In addition, UnrealScript also has quite a few non-standard features such as:

  • Language is Case insensitive!
  • Actor states
  • Rich, typed, literal format
  • Class default properties and no constructor

Please look at the reference above for more information on those.

Classes

Classes in UnrealScript are part of packages. A package is a folder placed inside the UDK/UDK-xxxx-xx/Development/Src directory; the name of the folder is the name of the package. A folder named Classes must be placed directly inside the package folder. UnrealScript class files must be placed inside a Classes folder.

To cause the compiler to compile your package, your package name must be added to the EditPackages list in DefaultEngine.ini, under the UnrealEd.EditorEngine section. For example, to cause the compilation of an example package named Foobar we would update the following UnrealEd.EditorEngine section:

[UnrealEd.EditorEngine]
+EditPackages=UTGame
+EditPackages=UTGameContent

To the following:

[UnrealEd.EditorEngine]
+EditPackages=UTGame
+EditPackages=UTGameContent
+EditPackages=Foobar

Note the +. See Lab 5 part 1 for more information.

Technical Class Information

An UnrealScript class is stored in a .uc file. The name of the class must match the name of the uc file. For example: class Foo must reside in Foo.uc

A class must inherit from a single other class. The highest ancestor in the hierarchy is the class Object. It contains many useful functions. See Object.uc for more information. Another useful class is Actor. Actor directly derives from Object and it contains the functions and variable members required to represent a real object in the map (or otherwise) with such information as location, rotation, physical representation, graphical representation, etc...

For example, consider the following class declaration:

class Foo extends Object;

var int SomeInt;

function float GetFloatFromInts(int a, int b)
{
    local float ret;
    ret = a + b;
    return ret;
}

Defaultproperties
{
    SomeInt=5
}

Note some things:

  • Class is called Foo, declared with the class keyword, must reside in Foo.uc
  • Inherits from Object and is therefore the descendant of it
  • Has one member public integer variable, SomeInt
  • Has one function that returns float and accepts two ints
    • Contains a local float variable
  • Has Defaultproperties section containing default value for SomeInt
    • If SomInt was not mentioned in defaultproperties, default value would have been 0

Member Variables

To define member variables in a class, we use the keyword var and follow it with the type of the variable and then the name of the variable. The formal spec looks like: var [([property_group_name])] [specifier_1 [, specifier_2 [, ...] ] ] variable_name;

For example, we can declare some simple variables as follows:

var Actor A;
var(Important) const private int B;

Notice:

  • A is a simple variable. It is of type actor. No privacy specifier is provided so it defaults to public; this is different from most languages
  • B has a number of features:
    • An editor property window group name is specified, so this variable would appear underneath that category in the editor property window
      • Could have also been left empty, ie (), and it would have been placed in a category that adopts this class' name
    • It is const so its value cannot be changed after the object's construction
      • The value should be set in the default properties
    • It is private, so it cannot be read from or written to from any other classes, including children ie direct children

Class Reference Restrictors

An important type of variable is the class reference restrictor. This type of variable allows you to store a reference to a class. This is useful in situations when you need your code to use different classes under different circumstances or receive a class and work with it. The syntax for a class restrictor is as follows: var class<Controller> myClassReference;

The above code segment declares a member variable class reference restricted to classes that are descendants of the Controller class. For example, we can store the classes Controller, PlayerController, AIController, UTBot, etc... in this member. We can assign class literals to such a variable. For example: myClassReference = class'UTBot';

The syntax to the right of the = operator is known as a class literal. It allows you to obtain a reference to a particular class in the system. In this case, we are obtaining a reference to the class UTBot. We can assign UTBot to this class restrictor because UTBot is a descendant of Controller. The inheritance chain of UTBot looks as follows: UTBot > UDKBot > AIController > Controller > Actor > Object

Notice that Controller lies within the inheritance chain of UTBot which is why we can assign it to myClassReference. By contrast, the following snippet would cause a syntax error: myClassReference = class'Actor'; // This causes syntax error

The syntax error is because the class Actor does not inherit from Controller.

Uses of Class Reference Restrictors

We can use class reference restrictors for two things primarily:

  1. Passing the class reference to other functions
    • This is useful when you write functions that accept class references or when you need to pass a class to an engine function, for example spawn, which instantiates an Actor given a class of Actor to instantiate (more on this later)
  2. Retrieving static variables or default variables and for calling static functions

The first use case is very simple so it needs no explanation. The second use case should be elaborated. Given a class reference, we can do any of the following:

  • Retrieve the default values of all member variables
  • Call a static function

Let's look at each use case in turn. Consider the following class:

class RestrictorTest extends Actor;

var int IntMember;
var float FloatMember;

static function RestrictorTest InstantiateRestrictorTest()
{
    return Spawn(class'RestrictorTest');
}

static function int GetDefaultIntMember()
{
    return class'RestrictorTest'.default.IntMember;
}

static function float GetDefaultFloatMember()
{
    return class'RestrictorTest'.default.FloatMember;
}

DefaultProperties
{
    IntMember=10
    FloatMember=3.5
}

The above class has 2 member variables and 3 static functions. Note the three static functions:

  • InstantiateRestrictorTest
  • GetDefaultIntMember
  • GetDefaultFloatMember

Each one of these functions can be called without an instance variable. For example, we could have the following section of code:

var RestrictorTest myTest;

myTest = class'RestrictorTest'.static.InstantiateRestrictorTest();

This will call the static function InstantiateRestrictorTest which calls the spawn function returning an instance of the RestrictorTest class. Note the following:

  • Use of the class literal class'RestrictorTest' being passed to the spawn function inside the code of InstantiateRestrictorTest to indicate that this is the class that should be instantiated
  • Use of the suffix static in the above code segment to gain access to static functions in the class RestrictorTest

Similarly, calling GetDefaultIntMember and GetDefaultFloatMember will return 10 and 3.5 respectively due to the syntax used in those two functions. Note the use of the suffix default to gain access to the default value of all members in the class.

As Local References

Class reference restrictors can also be declared as local function variables. Simply change the keyword var for the keyword local, all other properties are exactly the same.

Functions

Like in other programming languages, functions can be declared and defined in UnrealScript. The basic syntax of function declaration is:

[function_specifier_1 [, function_specifier_2 [, ...] ] ]
function [<return type>]
function_name(
    [ [param_1_specifier_1 [, param_1_specifier_2 [, ...] ] ] <param 1 type> param_1_name
    [, [param_2_specifier_1 [, param_2_specifier_2 [, ...] ] ] , <param 2 type> param_2_name
    [, ...] ] ]
);

Function declarations can also be followed with a body as opposed to a semicolon. Here are some examples of common function specifiers:

  • exec
    • Function can be called from console or from key bindings
  • static
    • Function executed without a current object (Java/C++-style static function)

Return types can be any object type in UnrealScript.

Parameter specifiers include:

  • optional
    • Parameter can be omitted at call site. Parameter can be given default value with = operator
  • out
    • C++-style reference variable. When value is updated in function, value update is reflected at call site

For the full list of variable specifiers, see UDN UnrealScript Variables:Variable Specifiers

Function Body Variables

Like in other programming languages, a function can have a body wrapped in curly braces. While most statements are straight forward, variable declaration is slightly strange. Function variables are declared with the local keyword. This keyword works like a simplified version of the var keyword above.

The spec looks something like this: local <variable type> variable_1_name [, variable_2_name [, ...] ] ];

Some things to note:

  • Local variables, like instance member variables, cannot be initialized
  • Local variables must be declared at the top of the function, before ANY other statements!

Otherwise, local variables are similar to instance member variables.