| Home Page | Recent Changes

UnrealScript Quirks

This page lists all those little annoying things that you wouldn't expect UnrealScript to do, but it does. Especially those things that are unintuitive or cause very hard to diagnose problems.

Logging Rotators

When you log a rotator, its values automatically get wrapped to 0-65535, even if they're outside that range. Log lies!

Up is left Padawan

The Unreal World uses a Left-Handed Coordinate System. This means that the y-axis goes the 'wrong way'. Quite unreal.

Physics changes take a tick

If you decide to change a Pawn's physics, don't then write code assuming the change happens immediately. A tick? has to pass before the change registers.

Foxpaw: Can you elaborate on what exactly is meant by this?

dataangel: Sure. If you use SetPhysics on something (actually come to think of it this probably isn't just for pawn) the physics doesn't actually change until one game tick has passed (one iteration through the main game loop, look at the tick funtion in Actor/Methods on the wiki). I'm not sure if logging Pawn.Physics will show the new physics or the old one, but if you try and call some native function that only works when the pawn is in a certain physics, it'll treat the pawn as if it had the old physics until the next tick.

Simulated

The simulated keyword means that a function CAN run on a client, not that it will. This is not a magic fix, which will suddenly make your code run on the network. See simulated function.

UCC GPF

Making your class DependsOn a class that ucc can't find will cause it to fault. No, it does not give you a nice descriptive error. It crashes and laughs at you.

5 meters is 5 meters, except when it's not

The Karma functions and the rest of Unreal use completely different scales. Yes, even though it is the same engine. Be sure to convert between the two. See Unreal Unit.

Solid Snake: This has been noted many times before. All of the Karma references will also mention that the units used between Karma and Unreal are different on a linear scale.

There is no include

There's no way for you to add your own global functions without purchasing the engine and editing object.uc yourself. You can get very very ugly long static functions by declaring a class, making the functions static, then referencing them like so: class'myClass'.static.myfunc.

El Muerte: Actually, there is an include, but it does not work as you expect and it has some quirks. The include is a macro:

#include Path/Relative/To/Package.inc

This will include the file ../Package/Path/Relative/To/Package.inc AS IS. However, this will screw up the linecount, so if that file contains 6 lines the compile might claim a error on the n'th line you should look at the (n-6)th line in your code. Ofcourse this option doesn't solve the issue that you can't define global functions (you can't do that in Java either, so who cares). It's best to avoid the #include directive.

However, there is a way to create non static global functions. This requires you to create an class containing these global non static functions. Create an include file like this:

// include this file before the first function declaration
var MyGlobalActor mgo;

/** call this function in PreBeginPlay */
function InitGlobalObject()
{
  forearch AllActors(class'MyGlobalActor', mgo) break;
  if (mgo == none) mgo = spawn(class'MyGlobalActor', Level);
}

Ofcourse this won't solve all your problems, but in some cases it might help you a bit.

Note: when you are creating a new gametype, you're better of creating a new GRI class that contains your new global functions.

Initializing bloat

You can't declare a variable and initialize it in the same line, unlike most other programming languages. UCC is not very kind about this either. It will give you all sorts of cryptic errors depending on where you attempt this. I am almost certain there is code in ucc to explicitly prevent it from giving you a clear error message for this by selecting one at random.

Vectors and Rotators on the Fly... sort of

The builtin vect(x,y,z) and rot(Pitch,Yaw,Roll) operators for creating vectors and rotators on the fly may seem useful. But then try to pass anything but constants. rot(0, 200, 50) will work but rot(myvar, 300, 200) will not. Luckily, ucc will print out a random error message to assist you. Which will lead you for some arbitrary reason thought of at Epic to do this:

local rotator temp;

temp.Pitch = myvar;
temp.Yaw = 300;
temp.Roll = 200;

Foxpaw: The reason why Epic did this is very simple. Rot(100,0,0) is a constant, like "I love strings" or 5. It's syntax makes it look like a function, but it isn't one. Constants are considerably faster at runtime than evaluating a function with constant arguments.

dataangel: Nor though would it have been terribly difficult for them to make it a native function that works with variables and only optimize for constants when you specify all constants. Then it would act intuitively =) But you're right and that's not the point. I'll change the description above to explain that.

Solid Snake: I think it's like when you attempt to do this, dynamicarray.length++;. The syntax is correct and UCC will compile it, but you can't do that.

Log's Double Dishonesty

Not only does log report rotators incorrectly, it'll also truncate your float values. See also: Baudrillard.

DesiredRotation Undesirable

If you want to use DesiredRotation for actors with physics other than PHYS_Rotating or PHYS_Projectile, you're out of luck. No matter what you do the engine will not do the rotation for you. You'll have to come up with your own system.

Not all strings are in code

If there's a string for your mod you want to override, and you can't find it anywhere in the .uc files, chances are for localization reasons it's stored in the INT files. Search those.

Solid Snake: That makes no sense. You define the contents of the INT or other language files inside UC file. You can't randomly just put a variable definition inside a language file and get away with it. Thus, you need to say that rather than trying to find the definition of the variable string or whatever else, look in the language file, although the variable itself is declared in the UC file.

dataangel: Eh, when I say string I don't mean the variable declaration. I mean the actual string literal. When people see "The game will begin in 3..2..1.." and stuff like that they type that string in and search their .uc files and wonder why there are no results.

Related Topics

Discussion

dataangel: I'm sure I've missed a ton, but these were the quirks I remembered and had caused me the most time wasted today ;) Please add.

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In