Copyright: Copyright ©1998 Skarz
Citation: This is NOT the official UnrealED Manual!. This is just a temp thing to help out people who need a quick reference when using UnrealED.


AI and Physics

Unreal Creature Care and Feeding Guide

AI and physics notes

Steven Polge 5/5/98

NEW FEATURES SINCE LAST UPDATE:

n	BiterFishSchools have a fishcolor attribute.  0 to 6 makes all the fish in the school the same color, while a value larger than 6 gives them a random mix of colors.

n	Decorations, including carcasses, trigger their event when destroyed.

n	The Jumper trigger has a JumpZ variable which specifies how high the triggered creature should jump (giving you control over where it lands).

n	The FearSpot keypoint has a bInitiallyActive attribute, which can be turned on and off by triggering it.

n	When a player enters a TeleporterZone, he is teleported by the associated teleporter (specified by the TeleporterZone’s TeleporterTag).

n	SetDesiredFOV f sets your field of view to f (a value between 1 and 179).

n	For all the human corpses in your maps, be sure you used MaleBody,
MaleBodyTwo, MaleBodyThree, FemaleBody and Female2Body. Very recently (for
network performance) I added some new subclasses - MaleOneCarcass,
MaleTwoCarcass, MaleThreeCarcass, FemaleOneCarcass, and FemaleTwoCarcass.
These use the regular meshes, and therefore take up a lot of memory (plus
they don't have the extra poses). Check your maps, and make sure you
haven't put any of these in.

n	Added a new attribute to the Nali, bNeverBow.  This should only be used with Nali who have a homebase (and only in well tested situations).  When enabled, the Nali will not stop and bow while retreating.

n	The damagetype for SpecialEvent triggers and pain zones has changed (to allow translation).  To provide your own message, set the damage type to special, and type the message in the damagestring (the death message will read “Player was xxx”, where you fill in the xxx).

1. AI Attributes

Typically, you will use the default values for the parameters below, with the following exceptions:

Tag, Orders, Ordertag,TeamTag, bTeamLeader, AlarmTag  and sometimes Aggressiveness. AttitudeToPlayer, and Combatstyle.

Actor attributes menu:

OddsOfAppearing	Likelihood that creature (or other actor) will appear in relevant game modes.

Range is 0.0=Never to 1.0=Always (default is 1.0).

Pawn attributes menu:

Display attributes menu:

DrawScale:	If the drawscale of a creature is changed from its default value, its collision box

(collisionheight and collisionradius) and health will be scaled by the new value

at the start of gameplay.

Movement attributes menu:

JumpZ:	How far a pawn can jump.  If you don’t want a pawn to jump that can normally

jump (for example, you want to keep a specific Skaarj up on a ledge), set its

JumpZ to -1.

AI attributes menu:

bHasRangedAttack:  	specifies whether creature can attack from beyond melee range.

bMovingRangedAttack:	specifies whether creature can use his ranged attack while moving (assuming creature supports this mode).

bCanStrafe:	Specifies whether creature can strafe.

bFixedStart:	If true, creature always starts from where it was placed.  If false, then may start from alternate position depending on its orders (see below).

bQuiet:	If true, makes less noise when wandering around

bTeamLeader:	Leader of his team (as defined by the TeamTag).  There should be only one per team.

bIgnoreFriends:  	Default false.  If true, creature doesn’t react to friend's noises.

bDelayedPatrol:	If true, and creature’s orders are Patroling, then the creature will begin his patrol only when it is triggered.  However, it will break off this patrol and react to the player if it sees him.  To force the creature to continue to his destination, you can also specify the patrol destination in the creature’s alarmtag.

bHateWhenTriggered:	Creature will change its attitude to hate the player when triggered by the player.

TeamTag:	Creature team to which this creature belongs.  As long as the team leader is alive, creatures on the same team will coordinate with each other..  If the species can speak, then creatures on the team will talk to each other.

Skill:	Added skill of this creature.  Default is 0.  For example, if Skill = 1, then the creature will act like a difficulty 2 creature when the difficulty setting = 1.

SightRadius:	Maximum sight distance.  Creature’s likelihood of seeing other pawns depends 	on how far away the other pawn is relative to the creature’s sight radius. the other pawn’s visibility, and (soon) how well lit the other pawn is.

PeripheralVision:	The cosine of the maximum angle of peripheral vision.  A creature which can see 90 degrees to each side (180 degrees total) would have PeripheralVision = 0.0. How far another pawn is into the creature’s peripheral vision affects its chances of seeing it.

HearingThreshold:	Minimum scaled noise loudness which can be heard.  While the exact hearing range depends on the creature’s alertness, a good rule of thumb is that creatures can hear a typical loud noise if there is a line of sight to the noise location, and HearingThreshold < 200 / (distance to the noise in Unreal units).  For example, a creature with HearingThreshold = 0.4 could typically hear noises if they were no more than 500 units away.  A hearing threshold of  0.2 translates to a max hearing distance of 1000 units.  Creatures can never hear noises which are more than 2800 units away.

Orders:	See Orders section below.

OrderTag:	See Orders section below.

TimeBetweenAttacks:	Time in seconds between ranged attack barrages (which may include multiple shots).

MeleeRange:	Maximum distance from target  (not including collision radius of this creature or its target) to launch a melee attack.

Aggressiveness:	Typically in the range 0.0 to 1.0.  Primarily affects attitude changes (more aggressive creatures will continue to fight, even against a stronger player, less aggressive creatures will be more quick to flee).  May also have an effect on tactical combat decisions.  Note that creatures will only run away if they have a home base (except for Nali and cow)

Visibility:	How visible is this pawn to other creatures (note - does not affect rendering!) 0 = invisible, 128 = normal, 255 = highly visible.

AttitudeToPlayer:	Initial attitude to player (may change depending on player’s actions, and creature’s aggressiveness).

ATTITUDE_Fear - creature will try to run away

ATTITUDE_Hate - creature will attack player

ATTITUDE_Frenzy - Indiscriminate, berserk attack (no fear, lower accuracy)

ATTITUDE_Threaten - Creature will assume a threatening posture

ATTITUDE_Ignore - Creature will ignore player

ATTITUDE_Friendly - Creature will fight player’s enemies

ATTITUDE_Follow - Creature will follow player (not yet implemented).

Intelligence:	Creature’s intelligence

BRAINS_None - amoeba like - only reacts to immediate stimulus

BRAINS_Reptile

BRAINS_Mammal

BRAINS_Human

ReFireRate:	Likelihood of firing again immediately after a ranged attack (values from 0 to 1 with higher values indicating a higher probability).

CombatStyle:	Tactical decision making during combat.  Value between 0.0 and 1.0  Higher means the creature is more likely to charge, try to melee, etc.

AlarmTag: 	If  AlarmTag is set, when the creature sees the player, it will (at all costs) first go to the actor with the same Tag as its AlarmTag. Friendly creatures will wait for the player as they move towards this actor. This can be used either to have friendly creatures lead the player to some area or object, or for  unfriendly creatures to try to trigger events or set up initial attack formations.  For example, you could have three Kraal in a room. Two attack you, while the other runs for a button which will lock the door behind you and sound an alarm.  Alternatively,  you could have them spread out in formation, seeking cover or advantageous positions when they see you.  AlarmPoints (see below) are designed to provide extensive scripting control when used with the AlarmTag.

SharedAlarmTag:	For each group of creatures who have the same string in this field, one of them will choose it to be his alarmtag (overriding any existing alarmtag).  You can use this to provide some randomness in which creature performs some important action.

DropWhenKilled:	Creature will drop one of these when it is killed.

FirstHatePlayerEvent:	Creature will trigger this event the first time he decides to attack the player.

2. Orders

The following initial orders can be given to all creatures.  After killing an enemy, they will attempt to continue to execute these orders.  Some orders (patroling, guarding) are associated with other actors in the level.  For these, you should set the creature’s OrderTag to the tag of the associated actor.

n	Waiting

The default orders for all creatures.  Creature will wait in place, playing various waiting animations,

until it receives some external stimulus (sight or sound).

n	Patroling

Patroling creatures will patrol along a set of Patrolpoints (a subclass of NavigationPoint) specified by

the level designers.  The creature’s OrderTag should contain the tag of the first Patrolpoint in its

patrol.  When a creature reaches a Patrolpoint, it will pause for the PauseTime specified in the patrol

point, facing in the direction the Patrolpoint is oriented.  While pausing, it will play

waiting/patrolstop animations.  If a PatrolAnim is specified, the creature will play that specific

animation the number of times specified by NumAnims.  Each time it plays the animation, it will also

 play the PatrolSound if one is specified.  Note that the amount of time creatures playing a

 PatrolAnim pause depends on how long it takes to play the animation NumAnims times, and not the

pause time.  However, the PauseTime must still be set to a positive number.  It will then continue to

 the Patrolpoint specified in the current Patrolpoint’s NextPatrol.  If a creature cannot reach the next

 patrol point, it will wait at its current position.   If bFixedStart is false, the creature will start at some

random point along his patrol route (not yet implemented).

n	Guarding

Guarding creatures will guard the actor whose tag equals their OrderTag.  They will remain near, and

try to return the guarded actor after combat.  If their initial attitude is ATTITUDE_Threatening, they

will threaten the player, and try to remain between the player and the guarded object.  If the player

touches the object they will attack.

n	Ambushing

The creature is waiting, but more alert than in the waiting state (and possibly playing different

animations).  If bFixedStart is false and there are Ambushpoints  (a subclass of Navigationpoint)

with the same tag as the creature, the creature may randomly pick one of these as its starting point.

The orientation of the Ambushpoint determines the orientation of a creature using it.  Ambushpoints

may also be used by creatures that decide to ambush rather than pursue a player.

3. Swarm AI Pawns

Horseflies, biterfish, and blobs all use variations of swarm AI.  Do not place individual Horseflies and biterfish in your map.  Rather, place horseflySwarms and biterfishSchools, and specify in their properties how many individual creatures they should contain.  For blobs, add a parentBlob and a number of bloblets, and give them all the same tag.

4. PathNode placement

You can place pathnodes manually, or you can use PATHS BUILD LOWOPT from the console to get a first pass placement done automatically.  In any case, you must do a PATHS DEFINE from the console to create the connections between pathnodes.

To use the navigation system, a creature must first choose the best nearby node to "get on" the network. For performance reasons, creatures limit their search for path nodes to those within an 800 unit radius (see
FSortedPathList::FindVisiblePaths in UnRoute.cpp). This is because the test to determine if a creature can reach a path is very expensive. However, once creatures are "on the network", travelling from pathnode to pathnode, they use the reachspec tables in each pathnode to determine reachable nodes.  There is no distance limit for reachspecs, so paths may be defined between two pathnodes which are any arbitrary distance apart. For performance reasons, paths between distant pathnodes which have a suitable alternate
path using intermediate path nodes (with a low added cost) are culled from the path network.

I recommend that paths should be less than 700 units apart, so that creatures don't ever start off going in the wrong direction to get on the network. In addition, paths on stairs and ramps should be closer together (<350 apart) Given that, you should use the minimum number of paths needed to cover the area for which you want intelligent navigation. Note that all navigation points are equally used as paths, so there is no need to place pathnodes redundantly near patrolpoints, etc..

Paths should in general be placed at intersections, making sure that they have the maximum visibility in all potential directions. Paths need a line of sight to each other, clear to the width of the maximum width (2 *
collisionradius) of creatures which will use this path. You should also place paths on ledges, with a line of sight to paths below, so that creatures can intelligently navigate jumping off ledgest. Vertical line of sight has no extent requirement.

In UnrealEd, look at the Properties menu in the map view window. There is an option to show the path connections. These are best looked at using the overhead view. Note that a connection between two Navigation points indicates that at least some creatures can use this path. However larger creatures, or creatures which do not support certain movement modes (e.g. the bCanJump, bCanSwim, etc. attributes of pawns) may not be able to use these paths.

5. Thing Factories and Creature Factories

Creature and thing  factories may be triggered by a trigger whose event equals the creature factory’s tag, or will trigger themselves if a player touches it.  Since zone changes can cause an event, you could for example cause a creature factory to start producing razorfish as soon as a player enters the water.  The first creature spawns instantly.  Creature and thing factories use Spawnpoints ( a type of navigation point) as the locations to create actors.  Up to 16 spawnpoints can be associated to a given factory.  Spawnpoints and creature factories are associated by giving them the same tag.  If a Spawnpoint has a tag in its event field, that event will occur when a creature is spawned from that spawnpoint.  By default, creature factories are covert, which means they will only spawn actors at a spawnpoint no player can see.  A creature from a factory has its event set to the factory’s tag (so its death will trigger the factory).  Thing and creature factory properties are:

prototype:	The class of actors produced by this factory.

maxitems;	The maximum number of active actors from this factory at any time.  If it is

a creature factory, new creatures will only produced either initially, or when a creature dies, to get back up to maxitems until the factory capacity is reached.

Capacity:	The maximum number of actors this factory can ever produce  (-1 = no limit).

After reaching this limit, the factory shuts down.

AddedCoopCapacity:	Extra items to produce if the game type is CoopGame.

Interval:	The average time interval between spawns.

timeDistribution:	The distribution of the interval between spawns.

DIST_Constant - constant interval (always equal to Interval).

DIST_Uniform - uniform interval (random time between 0 and 2 x interval)

DIST_Gaussian - Gaussian distribution, with mean = interval

bOnlyPlayerTriggered:	Only a player can trigger this factory (true by default).

bCovert:;	Only do hidden spawns (true by default for Creature factories, false by default

for thing factories).

bStoppable:	Stops producing when untouched.

Orders:	(Creature factory only)  Creatures from this factory will have these orders

OrderTag:	and ordertag.  By default they will attack the instigator of the factory.

ItemTag:	Tag given to items produced by this factory.

AlarmTag:	(Creature factory only) AlarmTag given to creatures produced by this factory.

6. Navigation Points

All navigation points have a bPlayerOnly attribute.  If set to true, it means that only

Players (bots) will use this path for navigation.  Its not perfect, but if you put two in a row 	along a hallway with turns, it will probably keep the creatures from going through that

hall.  Exceptions are if the creature is close behind a player and in hot pursuit, or if he is

already very close to the path when he tries to use navigation.

Homebase:	Homebase of creatures whose tag is the same as the Homebase actor.  Creatures who fear

the player will flee to their homebase if they have one.  There, they will turn and fight.

When a creature reaches its homebase, it will face in the direction specified by the

homebase’s orientation.  Also, it will check for nearby ambushpoints whose tag = the

creature’s tag, and if any are found will go to them.

Ambushpoint:	See Ambushing orders.

InventorySpot:  	Automatically inserted during PATHS DEFINE to identify location of inventory (for    	bots.

Teleporters:

PlayerStart:

SpawnPoint: 	See Thing and Creature factories.

PatrolPoints:	See Patroling orders.

LiftCenter:	Place this Navigation Point at the spot on a lift you want the creature to stand while using 	the lift.  Its LiftTag should be set to the tag of the lift it is on.

LiftExit:	LiftExits should be place at the spots you want creatures to wait before getting on a lift.  	Their LiftTag should be set to the tag of the lift they are associated with.

AlarmPoints:	Alarmpoints are designed to be used in conjunction with the alarmtag to cause creatures

to perform complex actions upon seeing a player.  If the Alarmpoint’s event is set, it will

trigger all creatures with that tag when the alarm creature reaches the Alarmpoint. The

attributes are:

NextAlarm:  	The next alarmpoint to go to after this one.  If none, the creature will

revert to normal AI after completing the actions specified by this point.

PauseTime:	How long to pause at this alarmpoint.

DuckTime:	How long to pause after playing the AlarmAnim (only used if an

AlarmAnim is specified).  Its called ducktime, because a typical use

would be to have the creature duck, wait for ducktime, and then stand

up and shoot (if bAttackWhilePaused is true).  If you want to the

creature to track the player while ducking, be sure to set

bAttackWhilePaused.

AlarmAnim:	If specified, the creature will play this animation upon reaching the

alarmpoint, as well as the AlarmSound if specified.

bStrafeTo:	If true, and the creature can strafe, then the creature will strafe to this

AlarmPoint, facing the enemy player.  If the creature has a moving

attack, it will fire while strafing if it has a clear shot.

bAttackWhilePaused:	If true, the creature will shoot at the player while paused

(unless he has a ShootTarget).  If the player is not visible,

the creature will fire at where he last saw the player.

bNoFail:	If true, the creature will never give up trying to get to this

Alarmpoint (just as it never gives up trying to get to other

alarmtag actors).  If false, and the creature gets knocked off

its path, it may give up if it can no longer easily get to the

alarmpoint.

bStopIfNoEnemy:	If true, and the enemy is not visible, creature will stop at this

Alarmpoint until it sees the enemy again.  Otherwise, it will

continue progessing through the Alarm actions.

bKillMe:	Any creatures that are triggered by this alarmpoint (their tag

= the alarmpoint’s event) will hate and kill the triggering

creature, even if they wouldn’t normally.

bDestroyAlarmTriggerer	When a creature reaches this alarmpoint (and it is the

creature’s alarmtag destination), the creature is immediately

destroyed.

ShootTarget:	If bAttackWhilePaused is true and ShootTarget has the tag of

some actor, the creature will fire at that actor rather than the 	player.

AlarmSound:	If an AlarmAnim is specified, the AlarmSound will be played

in conjunction with the AlarmAnim.

7. Physics Notes

Creatures may be able to walk over any opening up to 3X their CollisionRadius.  If you want something to

definitely fall in, or not be able to cross without jumping, make it bigger than this.  Also, make sure that most hallways, and particularly intersections and corners are at least (4 x CollisionRadius + 10) of the largest creature you want to navigate it (so that two creatures won’t get hung up with each other.  Ideally, hallways should be at least 6x the CollisionRadius of the largest creature which may navigate it.  Also WarpZones should be at least 70 units deep ideally to allow the AI to handle them properly.

8. Triggering creatures

Creatures that have not engaged an enemy can be triggered by a trigger whose event equals the creature’s tag.  Creatures that are triggered will make whatever instigated the trigger their enemy.  You can use this to have creatures ignore the player until a certain event happens, such as crossing some threshold (using ATTITUDE_Ignore) - if bHateWhenTriggered is true,  the creature will change its attitude to hate the instigator.  Creatures will also trigger their event when they die.  You can use triggers in conjunction with bDelayedPatrol to cause a creature to start a scripted set of actions when triggered by the player (without noticing the player).

9. 	Triggers

Two new trigger types have been added.  TT_PawnProximity will allow any pawn, not just players to use the trigger.  TT_ClassProximity will only allow actors of the class ClassProximityType to use the trigger.  For example, you might make a certain switch only operable by a Nali.  Also, triggers with type TT_Shoot now also have an optional DamageThreshold value.  This is the minimum damage required for triggering (instantaneous, not cumulative).  The optional attribute ReTriggerDelay specifies the minimum time before a trigger can be triggered again.

RepeatTriggerTime, if  set to a value greater than zero, causes the trigger to send out its event at an interval of RepeatTriggerTime seconds while the triggering actor remains within the trigger’s radius.

EarthQuake:

The EarthQuake keypoint can be triggered to shake the player’s view for a specified duration, as 	well as possibly tossing players around. It has no effect on other actors.  To simultaneously toss

around other actors, use the ThrowStuff keypoint.  Earthquake attributes are:

magnitude:	Specifies the amount to roll the player’s view, and the amount to throw

him if bThrowPlayer is true.  A magnitude of 2000 is a pretty strong

quake.

duration:	Time in seconds quake lasts.

radius:	Radius for which players are affected.  A player who goes beyond the

radius will continue to have his view shaken for the duration of the

quake, but he will no longer get thrown around.

bThrowPlayer: 	If true, players are thrown around during the quake.

ThrowStuff:

The ThrowStuff keypoint can be used to cause actors whose tag matches the ThrowStuff

 	keypoint’s event to be tossed using the vector specified in throwVect.   If Numthrows is larger

than 1, the actors will be thrown again after the specified interval.  If bRandomize is true,

the throwVect will be randomly altered for every toss.  Having Numthrows > 1 and bRandomize

can be useful for making stuff get tossed around during an earthquake.  Other potential uses for

a ThrowStuff keypoint include launching a creature in a specified direction when triggered by the

player, or  turning the physics on of actors when a brush they are on tips and you want them to

slide/fall off (in this case, use a ThrowVect of (0,0,0), and they will just be set to falling).

MakeNaliFriendly:

When triggered, this keypoint makes all Nali in the level friendly.  This is useful for cases when the 	player may have scared the nali previously, or to set up situations where the Nali will reward the 	player after he does something (such as killing a skaarj which was threatening the Nali).

Jumper:

When triggered, this trigger makes the triggering creature jump in the direction it is pointing.  It can be limited to trigger once only, or to only affect a certain class of creatures. The Jumper trigger has a JumpZ variable which specifies how high the triggered creature should jump (giving you control over where it lands).

FearSpot:

This trigger causes creatures to avoid an area (not perfectly).If you use this, make sure there are also no paths going through the area you want them to avoid. The FearSpot keypoint has a bInitiallyActive attribute, which can be turned on and off by triggering it.

10. 	Movers

Two new booleans have been added to Movers.  bUseTriggered indicates that the brush is activated by a player doing a use (exec grab) on it.  BDamageTriggered indicates that damage to the brush will trigger it.  The optional attribute DamageThreshold specifies the minimum (instantaneous, not cumulative) damage needed to trigger a bDamageTriggered brush.

      Mover bump types are now supported, specifying which types of actors can trigger a mover by bumping it (for movers which are activated by bumping).

By default, all the movers with the same tag will return or stop if one returns or stops because of encroachment.  To prevent all the movers with the same tag from acting this way, you can divide them into sub-groups using the ReturnGroup attribute.

11. Special Creature Features

Mercenary:

The mercenary has several special sets of idle animations accessible through the following attributes - bButtonPusher, bTalker, and bSquatter.  If one of these attributes is set true, then these animations will play whenever the mercenary is stopped (waiting, or stopped on patrol, etc.).  Note that for bTalker and bSquatter, the mercenary should be talking to teammates (so that the conversation will be synchronized).

bHasInvulnerableShield, bCanFireWhileInvulnerable, and invulnerableCharge are parameters which can be used to adjust the Mercenary’s invulnerability capabilities.

Skaarj:

The Skaarj has a special set of animations accessible through the attribute bButtonPusher, which  work in an analogous fashion to the mercenary bButtonPusher animations.  Also, bFakeDeath tells the skaarj to remain laying down until a little after he sees the player.  Note that skaarj using bFakeDeath should be placed slightly above the floor, so they don’t adjust out of the floor on first seeing the player (thereby giving away the fact that they are not really a carcass).

Krall:

The Krall has a special set of animations accessible through the attribute bDicePlayer.  Krall using these animations should be teamed with several other Krall and closely arranged in a circle.  The bSleeping attribute will make a Krall play a sleeping animation and be very un-alert while waiting.

Nali:

A Nali with orders “Guarding” will play his praying animations.  A Nali with orders

“Ambushing” will play his meditating animation.

The bNeverbow attribute should only be used with Nali who have a homebase (and only in well tested situations).  When enabled, the Nali will not stop and bow while retreating.

Birds:

Although birds are flockpawns, they are added individually.  They have several different

selectable behaviours.  By default, they will fly around randomly in an area whose size is

determined by their CircleRadius attribute.  Note that this area should be relatively free of

obstructions, as birds are not smart.  If bCircle is set, they will soar around a circle with

radius CircleRadius.  If GoalTag is set, they will not move until triggered, and then quickly

fly to their GoalActor. Birds are now unlit by default.  If you want a bird to show off cool light/shadows, then set its bUnlit property to false.  Birds that you don’t see no longer cost anything.  However, be sure not to use birds in big open areas where they can be seen from far away, as the full cost of rendering their mesh still exists, even if they are smaller than a pixel.

Cow and Rabbit:

The bStayClose attribute (on by default) specifies whether the creature will wander around within

its WanderRadius, rather than wandering randomly anywhere.

 Pupae

Pupae can be placed and rotated onto any wall or ceiling initially.  When they see the player, they

Will drop off the wall/ceiling and go at the player.

Brute

The bTurret attribute when true will make the Brute stay in place and just fire at the player.

Warlord

The Mutilating orders are for hub one.   The Warlord has a new attribute, bTeleportWhenHurt, which causes him to teleport away rather than dying.

BiterFishSchool

The bNonAggressive attribute when true will make the fish ignore the player.

BiterFishSchools have a fishcolor attribute.  0 to 6 makes all the fish in the school the same color, while a value larger than 6 gives them a random mix of colors.

12. 	Carcasses

You can add permanent creature and player carcasses (they are a subclass of decoration).  If a creature has multiple death animations, you can select the death pose by changing AnimSequence in the Display properties.

Carcass management note:  Carcasses are destroyed more quickly in zones that already have reached their limit of carcasses.  In less cluttered zones, carcasses will never disappear or change forms before your eyes.  The MaxCarcasses attribute of zones sets the limit for “uncluttered” carcasses in a zone.  The default is now 3, which should be optimal for most situations.

13. Zones

The ZoneTag is used to tag a zone which is to be triggered by a ZoneTrigger.  WarpZones can be triggered to sequence through an array of destinations specified in their properties.  Other zones will toggle bPainZone when triggered.  The ZoneFog and ZoneFlash properties in ZoneLight allow you to change the player’s display color/fogging for a given zone.

The ZoneTerminalVelocity attribute changes the maximum falling speed of  players in the zone.

There are now also EntrySound, EntryActor, and ExitSound attributes for zones.  Zones with bWaterZone set will play these as pawns enter/leave the zone.  These are modified for special water zones, such as lava or slime.

When a player enters a TeleporterZone, he is teleported by the associated teleporter (specified by the TeleporterZone’s TeleporterTag).

14. Screen Flashes

There are two components used to create screen flashes.  ViewFog is used to color the screen.  It is a vector whose components are RGB values between 0 and 1.  As ViewFog increases the brightness of the screen, you need to use ViewFlash to keep it from over-brightening.

ViewFlash is a vector whose components should be between 0 and –1 (for example (-0.5, -0.5, -0.5).  It reduces the brightness of the screen.  Typically, all the components will have the same value, which should have a magnitude about the same as the average magnitude of the ViewFog components to keep the screen from changing brightness.

15. AI Difficulty Differences

16. Scripted Execs and Cheats

Execs

(used in normal gameplay - can be bound to a key in you Autoexec.mac file):

FeignDeath 	pretend to be dead

Grab	Pick up a decoration or “use” a mover

Say “xxx”	Send message “xxx” to all players

RestartLevel

ThrowWeapon	Toss out your current weapon.

Kick “name”	Kick player named “name” off of server (only from bAdmin)

Pause

SwitchWeapon n	Switch to weapon in weapon group n

Fire

AltFire

Jump

Suicide

AlwaysMouseLook b	If b=1, always mouse look (and turn off SnapToLevel and

LookUpStairs.  If b=0 turn off AlwaysMouseLook.

SnapView b	If b=1, snap view back to horizontal when MouseLook is

unpressed (and turn off AlwaysMouseLook).  b=0 turns it

off.

StairLook b	If b=1, turn on automatic view orientation up and down

stairs/slopes.

SetDodgeClickTime f	Modify the dodgeclicktime (time between button presses

for dodge move.  F must be less than 0.3.  A negative value

disables the dodge move.

SetName “xxx”	Change your name to “xxx”.

SetTeam “xxx”	Change your team to “xxx”.

PlayersOnly	Only players allowed in the level.

ViewPlayer “xxx”	View the game from the point of view of the player named “xxx”.

The view is only changed if you are allowed to see through this

player’s eyes (e.g. a teammate in team play or coop mode).

SetAutoAim f	Adjust autoaim.  Setting it to 1.0 disables it.

SetHand xxx	Set weapon hand to xxx= left, right, or center.

Taunt xxx	Play the taunt animation xxx (wave, victory1, taunt1)

NeverSwitchOnPickup b    Default is 0.  If set to 1, then you never automatically switch to a picked 	up weapon.

PrevWeapon	Switches to the next lower priority weapon.

NextWeapon	Switches to the next higher priority weapon.

InvertMouse b	Default is 0.  If set to 1, then your mouselook is inverted.

ShowScores	Toggles the display of the scoreboard in multiplayer games.

ShowMenu	Cause the menu to be displayed.

SetSensitivity f	Changes the mouse sensitivity scaling to f (a float).

SetBob f	Changes the bob value to f (default is 0.016).

AddBots n	Adds n bots to the level (game must be a DeathMatchGame or

Subclass).

Cheats

ViewClass xxx	View the game from the point of view of a member of class “xxx”.	Successive executions of this function will iterate through the class.	For example, ViewClass class’SkaarjWarrior’ will show you the

game from the point of view of a Skaarj in the level, if there is one.

KillAll xxx	Kills all actors of class xxx (including subclasses)

Amphibious	Makes you amphibious (no limit to underwater time).

Fly

Walk

Ghost

ListInv	Print a list of your inventory items to the log.

AllAmmo	Gives you 999 ammo for all the weapons you have.

Invisible b	b=1 makes you invisible. b=0 makes you visible.

TempStatus b	b=1 turns the temporary status bar ( at the top of your screen) on.

b= 0 turns it off.

God	Toggles god mode.

BehindView b

SloMo f	Changes the rate of time in the game.  1.0 is normal speed.  2.0 is

twice normal speed. 0.2 is one fifth normal speed…

Players	Prints a list of players and their current score.

JumpZ	Changes your jumping height (260 is default).

KillPawns	Removes all pawns from the game.

CheatAdd class’xxx’	Adds an actor of class ‘xxx’ right in front of you.  This can be anything

(a weapon, ammo, a creature, etc.), as long as an actor of that class

exists or is referenced in your level.

RememberSpot	Remember your current location (see ShowPath below).

ShowPath	Show recommended path back to location remembered by

RememberSpot.  Displays a beacon.  When you touch that beacon, it

shows the next one.

SetDesiredFOV f	Sets your field of view to f (a value between 1 and 179).


About This Manual
About This Manual - Version 0.3

Welcome. First off, I would like to make it clear that this UnrealED manual IS NOT the official manual that will be coming out by Epic with the full release! This is something I did (Skarz) in my spare time so that we could all have a quick reference when using UnrealED. By this I mean you will now be able to press the "F1" key in UnrealED and this manual will come up (if it was installed correctly).

I will be updating this manual as more information becomes available. Check back to my website often for updates. It's: www.skarz.com. If you wish to include information or a tutorial, please email me at: help@skarz.com. Enjoy!


About UnrealED

What is it?

This is a development tool for creating 3D game levels, with features for creating complex architecture using Constructive Solid Geometry, applying texture maps to levels, illuminating the levels, and placing actors.

Basically, it is a comprehensive self-contained editing platform which will be capable of creating an entire self-contained 3-D game.

Copyright 1995 Epic MegaGames, Inc.


Adding Special Brushes

Overview

This dialog, accessible via the Brush/Add Special menu choice, provides a convenient way for you to add special, non-solid or semi-solid brushes and brushes with special effects.

Adding Semi-Solid Brushes

When you add a semi-solid brush to the world, the polygons in the world around it are not cut up.  When adding decorations like pillars and stairways, it’s better to add them as semi-solid brushes than regular (solid) brushes.  Semi-solid brushes add less complexity to the world than do regular brushes.

Semi-solid brushes behave just like regular brushes when the player collides with them.

Semi-solid brushes may only be added to the world, not subtracted.

Advantages

Semi-solid brushes don’t cut up the world around them, so the resulting geometry is more efficient.

Semi-solid brushes should be used when you want to add brushes with masked or transparent textures which block the player, for example gates or prison cell bars.  Semi-solid brushes create the intended visual effect in these circumstances, but adding regular (solid) brushes with masked or transparent textures will enable the player to see through the brushes into the inside of the world - revealing areas that should be hidden.

Limitations

You must not add semi-solid brushes that overlap with other semi-solid brushes in areas where the player may be.  Player collision can fail if the player collides with more than one semi-solid brush at a time.

Don’t use semi-solid brushes in areas where you’re going to create new brushes by intersecting or deintersecting.  Though this will work, the resulting brushes are more complex than they would be if you had used regular brushes.

Adding Non-Solid Brushes

Non-solid brushes are ideal for creating things that you want to allow the player to walk through without colliding.

Non-solid brushes do not block the player, and they do not cut up geometry elsewhere in the world when you add them.  They may only be added, not subtracted.

Uses

You may use non-solid brushes to add special details to levels, like transparent cobwebs, torch holders on walls, water, etc.

One-Sided and Two-Sided Brushes

This option applies to brushes which are transparent or masked:

One-sided: One-sided polygons can only be seen from the front.  When the viewer is behind them, they are invisible.  This is the effect you’ll want to use for adding solid panes of glass to windows, because the player will always see one of the brush’s two faces (the front or the back).

Two-sided: Two-sided polygons can be seen from either side.  This is intended for materials such as water or sheaves of light, which the player can go through and thus will often see from both sides.


Advanced Importing and Exporting

Overview

The “file/import” and “file/export” functions of UnrealEd are useful for saving UnrealEd levels are text files, which have an easy-to-understand format and can be parsed by other programs.

The file format used by UnrealEd is custom, and is not documented here because it’s easy enough to figure out by exporting a map and looking at the resulting text file. (If anyone want's to write more on this subject, email me at: help@skarz.com)

There are two different ways to export maps:

File/export:  This method exports all of the brushes and actors in the map as separate entities.  If you export a level, you can later import it without losing any information.  Note that exporting doesn’t save the textures used by a level, and importing doesn’t load them.  For textures to be properly matched up during an import, they must already be loaded.

Brush/Intersect followed by Brush/export: This method exports all of the polygons on the interior of a brush.  To export all of the polygons in a level, create a huge solid rectangular brush (large enough to encompass the entire level), intersect it, and export it.  This only exports the polygons; importing it later results in a single, huge brush containing the entire level.


Ambient Sounds

Ambient Sounds - by Jon Renner

First, make sure you have a suitable area ready for this tutorial: A cube including a light and a playerstart should be fine. There is a special actor for Ambient sounds under "Keypoints" expand the Keypoints thread and highlite "AmbientSound". Now right-click in the 2D views or 3D view and click on add AmbientSound.

Double-click the AmbientSound actor you just created to edit it's properties. Expand the sound thread, and look for the header that indicates which sound file to use. under the Browser toolbar, select the "SoundFX" option from the scroll-down bar and load any of the Amb*.utx sound packages. Play the sounds until you find one you like, and make sure it is highlited. now click on the "Use" button under the sound properties of your AmbientSound actor. This should copy the filename of the highlited sound in the browser menu over to your AmbientSound actor. The other properties such as radius and volume should be obvious in how they affect the sound. The sound will originate from the point it is placed in the map.


Animating Real-Time Textures

Unreal ANIMATING REAL-TIME TEXTURES manual

PICTURES TO FOLLOW SHORTLY!

From Version 1.01.html (c) 1998 Erik de Neve - Epic MegaGames, Inc.

Last Updated: 06/19/98

Contents

Using Unreal A.R.T.

•	Introduction

•	Applications

•	Timing and frame rates

•	Performance and memory

Creating animating textures

•	Basics

•	Palettes and color

•	Fire textures

•	Wave textures

•	Wet textures

•	Ice textures

Using Unreal A.R.T.

Introduction

Unreal's 'Animating Real-time Textures' technology (working title 'fire engine’) enables users to create and apply realistic dynamic textures immediately from within the Unreal editor.

Applications

The real-time animating textures can be used almost anywhere in Unreal; on surfaces, moving brushes, and even actors. All of the animating real-time textures do not maintain mip-maps, which means they do not have special scaled-down versions to look good at various distances. Most effects however have a smooth appearance and scale really well even without mip-mapping.

Transparent surfaces provide one of the coolest uses for the fire and wave textures. Positioned in cross-, star- or more elaborate formations, fire can look almost volumetric. Microtextures can also benefit from animation in special cases.

The water, wet- and ice-textures can convey much more than realistic water surfaces; used as a general means of warping source art in a noisy pattern, force-fields, swirly energy bursts and convincing turbulent flames are just a few of the possibilities.

Timing and frame rates

Fire, wave-and wet-textures are updated iteratively; the new frame takes the state of the last frame as its input, and then updates the texture.

This means such textures may need some warming-up time in order to look the way they're supposed to; for this you can set the PrimeCount parameter in the texture's animation properties to an appropriate number of iterations. This does not apply to Icetextures, the speed of which can be made explicitly frame-independent - see the IceTextures chapter (below).

Each texture has two basic parameters that determine the update rate at game-time, as well as at editor-time: MinFrameRate and MaxFrameRate, in the Animation panel of a texture's properties window. By default, both are zero, and the texture's update code will be called whenever a new frame is rendered in the game, so it will follow the framerate of the game. The advantage of this is a consistently smooth animating effect, but this may be too fast or too slow depending on the design context.

If you specify nonzero values, the framerate at which the texture updates itself is forced to be anywhere between these two rates. As long as the framerate at game-time falls within these two limits, the resulting behavior is still one texture update each frame.

This is also useful temporarily when editing the dynamic texture in the editor on fast computers, where the rate of frame updates may be too high to get a realistic impression of in-game behavior. Regardless of these settings, a dynamic texture is never updated when it is out of view.

Fire and water textures may need some 'warming up' time to attain a stable appearance - e.g. a flame needs to fade out to fill a texture, and waves need some time to spread out. When it is essential for your level to avoid visible texture bootstrapping, you can set the PrimeCount variable to some (low) "warming-up" value, from the properties / Animation panel.

Performance and memory

Each frame of an animating texture is created in real-time. This has obvious memory benefits over storing pre-rendered sequences. While all the effects use highly optimized code, displaying scenes with a lot of different large animating textures can have some negative effect on the frame rate. However, animating textures are not updated when no part of them appears on the screen; so you can still use many (large) animating textures in a single level as long as most of them are not visible at the same time. It's also efficient to use the same texture for multiple objects, like torchflames.

Performance slowdown is directly proportional to the number of pixels in a texture, so don't use a large texture where a smaller one would suffice. If you like, play around drawing stuff on a large texture, but then re-create the final desired effect on a texture that's just big enough to encompass it. Some large, detailed, 256 by 256 pixel dynamic textures may be essential to your level design; but in other cases, try obtaining the same effect using a scaled-up or tiling smaller texture.

After the texture size itself, the second concern is the number of particle actors that make up all effects in the fire and water textures; these are a limited resource. You quickly run out of these if you use the ones that emit clouds and other stuff. Fire sparks have a special adjustable maximum limit SparksLimit. This amount of sparks is the actual space that gets allocated during game-time; by making this as small as possible after you finalize your fire design you achieve an optimal use of memory. This is not a big deal usually since each single spark or lightning bolt takes up only 8 bytes, but unless you really need it, the maximum of 8 x 8000 = 64Kbytes is best avoided.

When the number of sparks reaches the maximum limit, it forces certain spark-burst emitting types into regular feedback cycles. By adjusting the limit, you can prevent or fine-tune this effect. As fire textures are saved, all the transient sparks are erased first and only the source sparks are written to disk, regardless of the maximum spark limit.

Some effects present a bigger performance load than others; for example the lightning effects in a fire texture, and lines and clamped squares in the water textures are more expensive than most simpler drops and sparks.

Everything tiles in all directions. All stuff, sparks, drops, waves and flames that move off one side turn up at the opposite one. Animations look best if you avoid simple 'cyclic' schemes whenever possible - try to use some random moving sparks or oscillators with different frequencies, to drive home the fact the texture is being generated in real-time.

Creating animating textures

Basics

In the Unreal editor, you create a new animating texture by clicking the 'new' button in the texture browser.

Before clicking on 'Create', make sure you have the following set up correctly since it is not possible to change most of these later:

Name: Change this to a descriptive, unique name.

Package: This is the UTX package the new texture will sit in. Remember to always save the UTX using this exact same name, otherwise Unreal may not be able to find the correct textures. It is recommended to create and manage your animating textures for a level in one or more dedicated UTX packages, to avoid creating unnecessary dependencies and also because it is easy to lose them between lots of static textures.

Some types, like the 'Wet' and 'Ice' textures, refer to existing static textures; it is good practice to keep the static textures being referred to in the same dedicated UTX, again to avoid dependencies between UTX files.

Group: An optional classifier, very useful in the texture browser to display special groups of textures within a single package, e.g. 'skins', 'base', 'trim', 'floor'.

Class: Selects one of the four types available:

•	FireTexture

•	IceTexture

•	WaveTexture

•	WetTexture

Size: Choosing the proper size for a texture is essential. In most cases it's nice to experiment on a 256x256 texture, delete it and recreate your finalized effect on a smaller texture that's just big enough.

When a texture's editing window is visible, you can edit it directly using the mouse, in combination with the parameters in a special panel of that texture's properties window called FirePaint, WaterPaint, or IceLayer.

All the "FX_" drawing parameters affect what you draw when you draw it, so within any one type, for example lightning, you can draw multiple bolts on the screen with varying intensity and frequency characteristics. All other parameters affect the whole texture or certain types of sparks globally, like renderheat.

For the fire and water effects, the left mouse button draws whatever actor is the currently active type, and the right button erases. Some effect types are drawn as you move the mouse, others need consecutive mouse clicks. Erase large objects like lightning bolts or line segments by moving the mouse over the starting point and clicking the right button. Erasing the swarming spark types can be tricky, usually it is be easier to clear the texture and start again.

Palettes and color

Coolness of any fire or water depends almost entirely on the color palette. For the Fire and Wave textures, change the palette by referring to any other texture using the palette option in the texture panel of a texture's properties window. Clicking 'use current' will explicitly copy the palette data from the currently selected texture to the fire or wave texture being edited. Note that, to avoid dependencies, this behavior differs from the usual case in the texture browser, where textures which refer to other textures and/or their palettes - notably the Wet and Ice texture types - become dependent on those textures and require their presence in order to run.

Unreal's software transparency (and its texture masking in general) uses a form of masking with holes for all color 0 pixels, so generally you would use a ramped palette that fades to black at color 0. For most applications however, the palette is not limited in any way.

Fire textures

Examples of "custom clouds" and "eels" using non-trivial color palettes

The size of the flames can be tuned over a broad range using the RenderHeat slider. Two different fire algorithms exist; bRising = false produces fire that doesn't move up as much as bRising = true. The appearance of the fire effects depends heavily on these two parameters. FX_Heat determines the overall or initial brightness of most spark types. The maximum number of sparks can be adjusted using SparksLimit, for details read the above chapter on performance and memory.

It is recommended to combine sparks of different types, or the same type with different FX_xxx settings to obtain unique effects; for example fountain sparks at different angles, ramped lightning, etc. can combine to amazing scenes.

Usually FX_Frequency, FX_HorizSpeed, and FX_VertSpeed are interpreted as signed values centered around value 128 being zero; lower values move sparks at negative speeds, i.e. they move or circle in reverse directions.

The SparkType selects the effect you're drawing onto the texture. Not all of these are terribly useful, some were left in simply to facilitate backward compatibility during Unreal's development process. The following types are available:

SPARK_Burn

Simple, nonmoving sparks of random intensity. Looks best with bRising = true.

SPARK_Sparkle

Sparks with random positional jitter over an area of horizontal size FX_Size, vertical size FX_AuxSize, with intensity FX_Heat.

SPARK_Pulse

Great for pulse-trains, FX_Frequency sets the time frequency, and FX_Phase is the spatial frequency: 0=pulsed fire, use higher values for moving trains of sparks.

SPARK_Signal

Like the _Burn spark, but this has several options to customize the graininess, brightness and intensity distribution to any desired output, providing a versatile base fire effect.

FX_Frequency sets the average pattern frequency, FX_Heat determines the ratio of bright patches to dark ones, i.e. a medium setting increases the contrast of the overall effect.

SPARK_Blaze

Emits sparks in all directions.

SPARK_OzHasSpoken

Simple up-moving, fading-out sparks.

SPARK_Cone

Like _Blaze, but with gravity acting on the sparks. A nice sparse effect to put at the center of complex ramped lighting bolt scenes, for example.

SPARK_BlazeRight

SPARK_BlazeLeft

Simple eruptions to the right and left, falling down.

SPARK_Cylinder

Sparks moving in horizontal, 'cylindrical' orbits, with angular velocity FX_HorizSpeed. FX_Heat determines the minimum intensity, which always varies along a spark's orbit - this means that a low FX_Heat setting gives a collection of sparks a 3d-appearance, as if the 'backfacing' sparks are removed. FX_Size sets the amplitude of the orbits.

DrawMode influences the FX_Size dynamically; when set to any of the 'Lathe' options, as long as you keep the mouse button pressed while drawing, all sparks will be aligned around an invisible vertical axis so it's as if you're using a lathe. Lathe_2, _3 and _4 draw multiple sparks at regular spacings around the cylinder, instead of just one.

The way the initial position of sparks wind around the cylinder as you draw is influenced by FX_Frequency.

SPARK_Cylinder3d

Like the Cylinder spark, but this type makes all the 'backfaced' sparks disappear completely.

SPARK_Lissajous

FX_Size determines the amplitude of the orbits, at FX_Frequency.

FX_HorizSpeed and FX_VertSpeed determine the horizontal and vertical frequencies independently. Like the Cylinder type, individual spark intensity depends on the phase of the horizontal movement and this is always offset by FX_Heat.

SPARK_Jugglers

FX_Size sets the amplitude of these, moving on a simple vertical sine wave pattern at FX_Frequency. As with Cylinder, the 'back-facing' effect depends on the FX_Heat setting.

SPARK_Emit

Moving in the directions set by FX_HorizSpeed and FX_VertSpeed, these glow out as they progress over straight trajectories of determined by both FX_Size and the initial heat FX_Heat.

With the speeds set to extremes ( 0, 128, 255 ) the trajectories become clean straight lines.

SPARK_Fountain

Like Emit, but the sparks have gravity acting on them. A great effect for stuff like streaming lava, steam or water. Setting initial speeds to zero (128,128) makes the sparks oozing down.

SPARK_Flocks

A random moving flock of sparks drawn at FX_Heat, jittering in circular orbits of size FX_Area, with FX_Size being the lifetime of individual sparks.

SPARK_Eels

Random cloud of straight moving sparks drawn at FX_Heat with lifetime FX_Size.

SPARK_Organic

Fast moving sparks going upward at V-shaped angles.

SPARK_WanderOrganic

Wandering Organic sparks.

SPARK_RandomCloud

A wandering cloud of double-speed upward moving sparks.

SPARK_CustomCloud

Completely customizable clouds using FX_HorizSpeed and FX_VertSpeed. While moving, sparks glow up to the maximum brightness and then disappear. FX_Area determines the spark's lifetime by setting

their initial brightness; a high FX_Area value makes sparks start at a lower heat so they take longer to reach full heat. Set the speeds at or around zero (128,128) to create a nice sparkly effect.

SPARK_LocalCloud

Like CustumCloud, but the spawning points of these are random within an FX_Area sized square, the upper left corner of which is the mouse position where you draw the effect.

SPARK_Stars

Unlike any other sparks, this one doesn't get washed out by the fire algorithm, but consists of single pixels of brightness FX_Heat, which get obscured by any fire passing across it, unless the flames have a very low intensity.

SPARK_LineLightning

Click, stretch out the lightning to the desired end location, and release it. A low setting of FX_Frequency gives continuous lightning bolts, while a high setting makes it flash more intermittently. Most lightning looks coolest when it's kind of sparse, achieve this by either adjusting the RenderHeat or setting a higher FX_Frequency.

SPARK_RampLightning

Like LineLightning, but with intensity diminishing towards the endpoint of the bolt.

SPARK_SphereLightning

Spherically symmetrical lightning, with diameter FX_Size. Sparse by default, to get more coverage put a few of them on top of each other.

An example of SphereLightning

SPARK_Wheel

Sparks move outward in circular orbits the size of which is determined by FX_Area, over a path of length FX_Size. They are emitted at an initial angle PX_Phase, FX_Frequency sets the rotation speed.

SPARK_Gametes

Random cloud of straight moving sparks drawn at FX_Heat with lifetime FX_Size.

SPARK_Sprinkler

Spawns upward wavy streams, FX_Frequency determines the speed at which the initial angle changes. FX_Phase controls the relative phase. On a low FX_Heat setting, a few of these can be combined together or with other effects to design smoky whirls.

Lightning with some cone sparks at the center; some rotating cylinder sparks applied using the Lathe drawing modes to obtain a pseudo-3d look; and a swirl made with 'wheel' sparks.

Wave textures

A funky water effect using a special 2-hue palette, with some static diagonal lines creating the depressions.

The wave effect creates a pseudo-phong-shaded rendering of a physically simulated water surface.

All effects described here push, pull or clamp the height of a point or line of the surface. The default water surface level 'at rest' is 128 units high and can extend from 0 to 255. Keep this in mind when using the static effects like lines, FixedDepth and AreaClamp, which can be made (deliberately) invisible with an FX_Depth of 128.

Simply throwing in some PhaseSpots is the quickest way to get a wavy water surface, but do remember to explicitly put in some with three or more slightly different FX_Frequency values; that way, the total ripple effect never repeats and will look more random.

While some of the actual wave sources you place on a texture may look artificial, you can hide these by custom-aligning the texture on the architecture, so only the resulting waves are visible. Placing a few line segments to clamp the surface into a beveled shape can give most effects more depth. BumpMapLight defines the incident light angle in an intuitive way: moving the slider away from the middle position brings out the depth in the image, but at the same time darkens it.

BumpMapAngle defines the viewer angle, which determines the position of the highlight. PhongRange determines how much of the palette to reserve for the highlight, as opposed to regular shading. The same result could theoretically be achieved using custom palettes.

PhongSize scales the size of the highlight.WaveAmp scales the amplitude of the waves up or down at rendering time.

The DropType selects the effect you apply to the texture:

DROP_FixedDepth

Clamps a small static spot to FX_Depth.

DROP_PhaseSpot

Shakes the surface at FX_Frequency with relative phase FX_Phase. Use PhaseSpots with slightly varying frequencies placed close together to create non-repeating random looking waves.

Putting spots of the same frequency in a circle with a carefully tuned range of phases can make vortex-like waves.

DROP_ShallowSpot

Like PhaseSpot, but half as shallow.

DROP_HalfAmpl

Like PhaseSpot, but only moves below the 128-average surface level.. Useful for specific local distortions.

DROP_RandomMover

Creates jittery waves from a randomly moving position.

DROP_FixedRandomSpot

A fixed spot with random jittery output.

DROP_WhirlyThing

Moves in small circles at FX_Frequency, pushing at FX_Depth.

DROP_BigWhirly

Moves in bigger circles at FX_Frequency, pushing at FX_Depth.

DROP_HorizontalLine

DROP_VerticalLine

DROP_DiagonalLine1

DROP_DiagonalLine2

Static lines of size FX_Size, clamping the surface to FX_Depth.

When FX_Depth is 128, these provide invisible barriers to waves. At other values they create nice meniscus-like beveled surfaces, useful for matching up with features placed onto the water surface in the level. When set up right these features can stop or reflect waves on the surface in realistic ways.

DROP_HorizontalOsc

DROP_VerticalOsc

DROP_DiagonalOsc1

DROP_DiagonalOsc2

Lines of FX_Size, oscillating at FX_Frequency.

DROP_RainDrops

General-purpose raindrops. Pushes the surface to FX_Depth at a random point within in a rectangular area of size FX_Size.

DROP_AreaClamp

Clamps down a rectangle of size FX_Size to FX_Depth.

DROP_LeakyTap

Drops of FX_Depth falling at a fixed position, within a regular time interval controlled by FX_Frequency, and phase FX_Phase.

DROP_DrippyTap

Like LeakyTap, but the intervals are irregular.

Wet textures

Edit this just like the wave effect, but instead of using a palette to simulate light striking the surface, the image of the source texture is distorted by the waves, suggesting refraction. The distortion is horizontal only, which is not an issue in most cases unless your texture has large, straight horizontal features that you want to distort. Make sure you select the right texture dimensions at the start of creating a new wet-texture; unless the sizes exactly match those of the SourceTexture you want to distort, this will not work.

Small values of WaveAmp are useful for a hot-air shimmering effect. To create realistic, natural looking pools and puddles, choose an appropriate texture with enough structure on it so that distortions will be clearly visible. If the texture has dark patches on it, drawing localized water in approximately these areas will give the impression of an irregular shallow pool of clear water.

Images suggesting water or shallow depths are useful as source textures for realistic WetTexture animations.

Ice textures

A source texture, its displacement texture, and the resulting Ice texture.

Similar to the wet-texture effect, 'ice' displays a source texture with distortions, but these are taken from ‘GlassTexture’, which is interpreted as an 8-bit distortion vector field. Both the SourceTexture and GlassTexture dimensions should match the Ice texture. In the texture window, moving the mouse with the left button pressed drags the displacement 'ice layer' texture to the desired position. By setting its TimeMethod parameter to TIME_RealTimeScroll, the animation speed you see in the editor matches the in-game speed exactly regardless of the frame rate; it will skip intermediate panning positions if necessary.

Using specially constructed displacement textures, coupled with carefully tweaked panning directions, the potential range of original effects using Ice textures is enormous.Oily swirls, fluid streams spiralling around each other, and effects that look like bump-mapping are all possible.

The default setting of TIME_FrameRateSync will not give framerate-independent animations, but is still a good choice if you need smoothness, since a once-per-frame update will ensure the texture moves a little bit every frame without big skips. The MoveIce switch selects movement of either the GlassTexture or SourceTexture.

HorizPanSpeed and VertPanSpeed determine the movement in the Linear and WavyX/Y modes, with a zero-point of (128,128). Frequency and Amplitude act on the speed and size of the circular and wavy parts of a texture's movements.

There are five modes of movement. All share the linear panning speed as set by HorizPanSpeed and VertPanSpeed

SLIDE_Linear

Move a texture with speed settings HorizPanSpeed and VertPanSpeed.

SLIDE_Circular

Circular movement using Frequency, around a radius equal to Amplitude.

SLIDE_Gestation

Irregular movement using Frequency and Amplitude.

SLIDE_WavyX

A wavy horizontal movement of Frequency and Amplitude.

SLIDE_WavyY

A wavy vertical movement of Frequency and Amplitude.

Enjoy !

- Erik de Neve


Audio Subsystem

Unreal Audio Subsystem

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

Audience: Level Designers, UnrealScript Programmers, C++ Programmers.
Last Updated: 06/11/98

Audio-related classes

UAudioSubsystem is the abstract base class of the sound subsystem.

The actual sound subsystem is implemented in a subclass of UAudioSubsystem. The reference implementation is UGalaxyAudioSubsystem, which supports the Galaxy music and sound system. However, UAudioSubsystem is general enough that it can be ported to other sound systems fairly easily.

USound contains a sound sample with the following characteristics:

•	.WAV format.

•	8-bit or 16-bit format.

•	Monaural.

•	Either one-shot or looped.

UMusic contains a digital music file with the following characteristics:

•	32 or fewer channels maximum (16 or fewer recommended).

•	.MOD, .STM, .S3M, .IT format.

UnrealScript interface

PlaySound (Actor class): plays a simple, non-looping sound effect emmanating from the actor. Use this for all normal game sound effects. You can specify the following parameters:

•	Sound: A sound effect; should be a one-shot (non-looping) sound.

•	Slot: One of the eight "slots" to play the sound in. This enables you to prevent more than one sound from playing on a particular slot. For example, when an enemy is shot several times in rapid succession, you want the successive sound effects to cut each other off, rather than hearing a chorous of simultaneous, overlapping screams.

•	Volume: Sound volume multiplier. 1.0 means "normal volume", 0.5 means "half volume", 2.0 means "double volume", etc.

•	bNoOverride: Whether this sound effect should override another sound playing on the same slot, or be ignored.

•	Radius: Radius of the sound in world units, defaults to 4096.0.

•	Pitch: Pitch multiplier. 1.0 means "normal pitch", 0.5 means "half pitch".

ClientHearSound (PlayerPawn class): called when a particular PlayerPawn actor hears a sound effect. This is how sounds are sent to clients in a network game. You may call this function directly (in a particular PlayerPawn) to have only that one player hear a sound.

ClientSetMusic (PlayerPawn class): Sets the music for a particular player.

UnrealEd music tips

In UnrealEd's music and sound browsers, you can listen to music and sound effects by double-clicking on them, or with the Play/Stop buttons. You can hear the level's ambient sounds while editing by clicking on the realtime button in the 3d view (it looks like a joystick icon).

Any actor in Unreal can emit an ambient sound. The properties to check out are AmbientSound, SoundRadius, SoundVolume, and SoundPitch. When you turn on UnrealEd's "Show Actor Radii" option in a 2d view, you can see the ambient sound radii as blue circles.

In Options/Level, you can set the default music, music section, and cd track for the level.

MusicEvent actors work similarly to SpecialEvent actors, in that they let you cause music changes in response to any event, such as the player touching a trigger, killing a monster, etc. In multiplayer games, MusicEvent actors only cause a music change in the player which caused the event, not all players in the game. MusicEvents have a "Song" variable which you can set to "None" if you want to use the song you set for the level in Options/Level.

3D positioning

A sound is positioned in 3d space, positioned at the Location of the actor who played the sound effect or ambient sound.

As the actor that played the sound moves around, the actor's sound is repositioned. The affects the following properties:

•	Distance attenuation.

•	Doppler shifting.

•	Stereo panning (if UseStereo is enabled).

•	Dolby Surround Sound positioning (if UseSurround is enabled).

Doppler shifting is based on the emitting actor's Velocity. Note that it is possible for actors to move around directly with SetLocation or MoveActor without having a valid Velocity, thereby causing no doppler shifting.

Dolby SurroundSound software encoding requires a Dolby decoder and four speakers, but it works on all stereo sound cards. It simply pans sound effects and ambient environment sounds between the four Dolby channels (center, rear, left, and right).

Sound slots

Each actor in the world has eight "sound slots", so it can play up to 8 simultaneous (overlapping) sound effects.

When an actor plays a sound in a slot where an old sound is already playing, the old sound can either be cut off and overridden, or the new sound can be ignored (see the bNoOverride parameter in PlaySound).

Sound slot zero (SLOT_None) is special: it indicates that a sound should not interrupt any other sounds. For sound effects like rapid-fire gunshots, use SLOT_None to allow multiple instances of the sound to play simultaneously.

In Unreal, there is a hard limit to the number of sound effects which may be playing simultaneously. This limit is set in the Unreal.ini file, and can vary from 16 to 32. During gameplay, the sound engine prioritizes each sound effect according to its volume and its distance from the listener, and culls the least important sounds. High-volume sounds override low-volume sounds, and sounds near the listener override sounds far away from the listener.

Sounds

Sound effects can be either 8-bit or 16-bit, and can be sampled at any reasonable rate (4kHz-44kHz). What rate and bit depth to use is entirely a quality vs. memory usage tradeoff. In general, use the lowest bit depth and sampling rate which gives you acceptable sound quality.

For best sound quality, make sure your sound effects are not clipped, i.e. sampled at so high a volume that the tops or bottoms of their waveforms are truncated.

Ambient sounds

Each actor in the level can have one ambient sound effect, which is specified in its AmbientSound property. This should refer to a sound effect which loops. If a non-looping sound effect is used as an AmbientSound, it will not play properly (it will only play once).

Persistence and correctness

Sounds have a radius. They diminish linearly according to distance and are culled when too far away to hear. Culling distance is a linear function of the sound's volume.

Ambient sounds persist across loads and saves.

Regular sound effects do not persist across loads and saves. A regular sound effect can only be heard by players (local and network) who can hear it when it begins playing. For example, if you have a 10-second sound effect and you start playing it in a room, then five seconds later a far-away player teleports into the room 5 seconds later, he will not hear the sound at all.

Looping sound effects

To create a looping sound effect in a .wav file, you need a sound editing program like SoundForge (http://www.sfoundry.com) which supports looping sound effects. In Sound Forge, follow these instructions:

Run SoundForge.

Load your .wav file (either 8-bit or 16-bit).

Bring up the "Special/Edit Sample..." dialog.

Click on the "Sustaining" choice (as opposed to "One shot").

Select "File/Save As...".

Make sure that the "Save Sampler Information in file" option is checked.

Click on the "Save button".

Limitations

Software-mixed sound:

•	3D sounds are only stereo panned, but not fully spatialized (i.e. phase shifted and bandpass filtered based on sound absorption in the ear as a function of position).

•	The sound system is limited to a maximum of 64 channels of music and sound. By default, 16 sound effects channels are allocated, leaving 48 for music. You can change this from the Unreal.ini file.

•	Each playing sound effect, ambient sound, and music channel uses CPU time. Therefore, we recommend keeping the number of sound effects audible to the player fairly low, and keeping music channel usage "lean and mean".

Hardware-mixed sound:

•	3D sounds are spatialized by whatever the hardware supports. For example, Aureal pans it, phase shifts it, and applies a complex convolution and bandcap filter to model positional modulation of the sound by the head and ears.

•	The sound system is limited to X channels of hardware mixed sound (where X depends on the kind of hardware, and can be from 6 to 64 for existing sound hardware). Any sounds for which hardware acceleration is unavailable are emulated in software using the software mixer, and thus may sound different (less spacey) than the same sound played on hardware.

Dynamic music

Each level has a default song and CD track which is played throughout the level. You can specify the song in UnrealEd in "Options/Level" in the "Audio" tab.

Music can be transitioned dynamically via a SpecialEvent object hooked up to a trigger or any other event source.

Music is not zone based, because that would become annoying when backtracking through maps and in network play.

Music is tracked per player so it can be used equally well in single player and network play.

Zone-based echo and reverb

The audio subsystem includes a six-tap sound reverberation filter which enables you to customize the echo and reverb effects on a per-zone basis (there can be up to 64 zones in a level, so you can have quite a bit of variety in the audio postprocessing within a level). When you add a ZoneInfo actor into a zone, you can set the following properties:

•	bool bReverbZone: True to enable reverberation effects in the zone; False to disable them.

•	[this is outdated, but the quick version is: the other properties are 6 reverb tap delays and gains]

You can experiment with reverberation filters quickly by going to Options/Level, setting the reverb effects for the entire level, then double-clicking on sound effect names in the sound browser.

Music formats

Unreal supports two major kinds of music:

•	CD audio. You can compose your game's sound track, record it on CD, and specify in-level music by CD track. Advantages of CD audio include highest possible music quality, no CPU overhead, and giving composers the freedom to create music however they want. The major drawback is that you can't do dynamic music very well since switching between CD tracks isn't instantaneous, and you can't distribute it via the Internet.

•	Digitally mixed music (.mod, .s3m, .it, etc). These are special music formats which include digitally recorded instruments as well as sequencing data. Advantages: Easy to distribute on the Internet, and more amicable to dynamic music. Disadvantages: somewhat CPU intensive to mix (3%-5% of CPU time), lower sound quality than CD.

Windows platform implementation notes

We only support 16-bit sound output. We tested 8-bit sound output and the quality was unacceptable low: when you mix 64 channels of sound into an 8-bit output stream, you effectively get 2-bit sound effects. 2-bit sound effects are Not Good.

The sound system supports both the legacy WinMM sound support, and DirectSound. DirectSound generally achieves the lowest latency, while WinMM works on Win95 machines which don't have DirectSound, and WinNT.

The sound code makes heavy use of MMX to improve mixing quality and speed. You get about a 2X performance and quality boost on Pentium processors with MMX technology.

On non-MMX machines, the sound code makes some quality/speed tradeoffs by limiting sound effects to having only 64 volume levels. You can hear this limitation by setting up an ambient sound effect with a high radius in an otherwise quiet area: the discrete steps between volume levels are quite audible.


Brush Overview

Overview

Basically, you create the world by adding and subtracting brushes, 3-D objects highlighted in the camera views by the red lines.  There are a number of functions which allow you to resize brushes, work with generic shapes, import shapes, rotate them, and so on.  When you are satisfied with the placement of the brush in the map, you can add it to the level, which gives it a physical existence within your world.  All brushes added to the world have real physical shape and form.  So, when you take away a piece of a shape by subtracting another brush from the world (subtracting basically means to create a void - a 3-D region of space), the brush will now have a hole or just a piece missing from it.  This is the key to the Unreal editor.  With this system, you can piece together and remove any 3-D solids in any way you want, giving you unparalleled flexibility to add and remove anything you want from anything else.

Imagine you are Michaelangelo, and you have created a block of granite in front of you by adding a cube to the map.  Now, by taking away (subtracting) pieces, you can chisel away parts of that granite until you are left with your masterpiece.  While you’ll have a problem recreating David, you shouldn’t have too much of a problem creating, say, a 3-D doughnut.

One way to create a room is to build its walls by adding brushes to the world.  Another way is to add a big cube to the world, then subtract a smaller cube from it.  The second way tends to be easier, for most level designers tend to build levels by adding huge, solid brushes to the world then subtracting out all of the rooms and interconnecting halls and doorways.  This helps to reduce the polygon count, which reduces the complexity of the level file and increases game speed.  If you had four separate walls, all the surfaces you cannot see are still there and take up memory, but if you have a hollow square, all you need to save is the inner and outer faces.  The inside of the walls of the square are a single, solid shape.

The brushes you use can come from a number of sources:

1.	Create a brush with one of the built-in brush generators.  These are the tools which let you build commonly-used brushes by setting their sizes and properties.  Complex brushes can be made using linked-in Visual Basic functions to allow you to easily create complex stairways, cones, and other geometric objects.

2.	Create a new brush by combining the current brush with the world with the intersect and deintersect operations.  This is a very important operation to learn.  After you have, say, created a doorway you want to use elsewhere, you wrap another 3-D brush around the object you want (all you have to do is make sure the object you want is inside the 3-D) and use the intersect operation.  You will now have a brush with the exact shape of that doorway, with even the textures you defined still encoded within the brush.  Now, you can save that doorway to your disk to load into another level again and again.

3.	Create a new brush by scaling, sheering, or otherwise resizing the current brush.  A number of tools allow you direct modification of the brush you are using.  While Unrealed does not allow vertex operations, you can freely change the size and angle of the brush you are using.

4.	Import a brush from another program.

Adding

Clicking on the “Add” toolbar icon, or selecting “Brush/Add” from the menu adds the brush to the world. This affects the world but not the brush.  Special effects can be used with your new brushes, as well.  For example, you may wish to make them semi-solid.  This is very useful when you want to simply make decorations like windows, bars, or columns because it adds less complexity to the world.

Some uses of adding include:

·	Building large solid objects which you’ll later subtract rooms from.

·	Adding pillars or stairways to levels.

·	Adding walls to levels.

Subtracting

Clicking on the “Subtract” toolbar icon, or selecting “Brush/Subtract” from the menu subtracts the brush to the world.  This affects the world but not the brush.

Some uses of subtracting include:

·	Removing interiors of rooms from large solid objects.

·	Creating doorways between existing rooms.

Intersecting

Clicking on the “Intersect” toolbar icon, or selecting “Brush/Intersect” from the menu intersects the brush with the world.  This affects the brush but not the world.

“Intersect” replaces the brush with all of the material that is inside both the brush and the world.  For example, you can create a large solid rectangular brush to encompass part of a level, then intersect the brush to “grab” that part of the level into the brush.  Then, you can move the brush around and add it to the world elsewhere, replicating that entire part of the level.

The Intersect operation preserves the original textures that were in a level.  So, you can use Intersect to copy part of a level elsewhere, and the textures will be copied as well.

Some uses of intersecting include:

·	Grabbing objects that already exist in a level, and copying them elsewhere.

·	Grabbing objects or sections of levels and saving them (as brushes) for later use.

·	Creating new brushes by chiseling pieces out of existing brushes, using a convenient area of a level as a chisel.

Deintersecting

This operation is the opposite of intersecting -- it replaces the brush with everything that’s inside the brush but outside of the level.  While less obvious, this operation is extremely useful for copying interiors.  For example, if you have created an interesting looking passageway, you can deintersect a brush with it and you’ll have a “negative” copy of the passageway which you can move around and subtract from other parts of the level, creating new passageways.

Resetting the brush

This restores the brush to its default settings.  You are presented with several options for resetting the brush’s rotation, scale, and position.

Loading and Saving

You can load and save brushes with the “Brush/Load” and “Brush/Save” options in the main menu.  These are useful for saving custom brushes you have created, then loading them later.  All of a brush’s properties are saved and loaded, including its current scaling, sheering, and position properties.  Since loading a brush sets the brush’s location, you may have to do a bit of searching for it upon loading.

Advanced CSG Operations

(unwritten)

Copyright 1995 Epic MegaGames, Inc.


Camera Move Mode

Camera Move Mode

This is the first thing you need to know in order to use the Unreal Editor.  The mouse is used for all movement commands.  Normally, you will simply move the currently selected view around in a certain direction.  However, by holding down the Ctrl, Alt, or Shift keys, you can manipulate the current shape (the red-lined object).

Note:	If you have a 3-button mouse, the middle button has the same effect as Ctrl.

Movement

Movement of the 3-D camera view:	[You / Camera]

Left button 	Moves the view forward/backward and yaws it.

Right button 	Looks around - pitches and yaws the view.

Both buttons 	Moves sideways and vertically.

Movement in the 3-D camera view:	[Shape]

Left Button 	X axis

Right Button	Y axis

Both Buttons	Z axis

Shift	This moves both the shape and the camera view at the same time.

Ctrl	This moves the shape independently of the camera view.  Use this to move the shape around inside the window without moving the view around.

Movement in the other 2-D views:

Since the movement direction is already limited to the 2-D plane you are viewing, you are limited to use of the left mouse button for movement.  The Shift and Ctrl keys will move the shape around the view the same way as above.

Tips:

Tab	Hold this down while moving the brush to update all of the camera views as you move.  Normally, only the current camera view is updated.

CameraZoomMode	This will allow you to maintain continuous camera movement.

Change Movement Speed	You can change the current camera movement speed.

Polygon/Texture Manipulation

Polygon Selection	[3-D view only]

Within the 3-D view you can choose the polygon faces which are showing onscreen (and also those that have been marked invisible but are still in front of you).  Simply move the mouse pointer over the polygon you want to affect and press the left or right mouse button:

Left Button	Toggles selection of the polygon you are pointing to.

Right Button	Deselects all other polygons and selects the polygon you are pointing to.

Note:  It is very easy to forget to deselect textures.  Keep in mind that if you do not deselect a texture, it will be affected by any later polygon commands you use!  For that reason, you should make a habit of deselecting all textures when you are done with what you are currently working on.

Texture manipulation	[3-D view only]

Point to the polygon face you want to use, hold down the Alt (and possibly Shift) keys, and click on the polygon face.

Left Button	Alt	Applies the active texture to the polygon you selected.

Left Button	Alt+Shift	Applies the active texture to all currently selected  polygons.

Right Button	Alt	The texture on the polygon you are pointing to becomes the active texture.

Keyboard Shortcuts

Shift-A	Selects all polygons.

Shift-N	Selects no polygons.

Advanced Selection Commands

These shortcuts are extremely powerful, in that they let you select just one polygon in the world, then use a shortcut to select “similar” polygons elsewhere in the world.  Thus you can select and texture map large areas without a lot of clicking.

Shift-G	Selects all polygons with the same group name as the already-selected ones.

Shift-I	Selects all polygons on the brush with the same item name as the already-selected ones.

Tip: Shift-I is especially useful because it enables you to select similar parts of an object with just one command.  For example, if you select one floor polygon on a stairway and press Shift-I, all other floor polygons on the stairway will be selected.  Then, you can apply and align textures on all of those polygons at the same time.

Shift-B	Selects all polygons on the same brushes as the already-selected polygons.

Shift-T	Selects all polygons that use the same textures as are already selected.

Shift-J	Select all polygons adjacent to the already-selected polygons.  This is like a flood fill, in that it continues until all attached polygons are selected.

Shift-C	Select all adjacent polygons that are coplanar the selected polygons, i.e. lying in the same plane as the selected polygons.

Shift-W	Select all adjacent walls.

Shift-F	Select all adjacent floors.

Shift-S	Select all adjacent slants (polygons at odd slopes that don’t qualify as walls or floors).


Class Reference

Unreal Classes

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

Audience: Level Designers, UnrealScript Programmers, C++ Programmers.

About this document

This is a quick attempt to describe the most important classes and variables in Unreal. It is currently very sparse but will be expanded over time.

Engine.Object

Purpose:

Serves as the base class of all objects in Unreal. All objects inherit from Object.

Variables:

•	Parent: The object's parent object (for scoping).

•	ObjectFlags: The object's flags, described in the •	Packages document.

•	Name: The object's name.

•	Class: The object's class.

Functions:

•	Log: Writes a message to the log file, usually \Unreal\System\Unreal.log.

•	Warn: Writes a script warning to the log file, including the current script and function.

•	Localize: Returns a localized (internationally translated) string from a package's .int file.

•	GotoState: Sets the object's current state, None means no state. If no label is specified, the Begin label is gone to.

•	IsInState: Returns whether this object is in the specified state.

•	GetStateName: Returns the name of this object's current stae, None if none.

•	Enable: Enables a probe event. The only functions which work with Enable and Disable are: Spawned, Destroyed, GainedChild, LostChild, Trigger, UnTrigger, Timer, HitWall, Falling, Landed, ZoneChange, Touch, UnTouch, Bump, BeginState, EndState, BaseChange, Attach, Detach, ActorEntered, ActorLeaving, KillCredit, AnimEnd, EndedRotation, InterpolateEnd, EncroachingOn, EncroachedBy, FootZoneChange, HeadZoneChange, PainTimer, SpeechTimer, MayFall, Die, Tick, PlayerTick, Expired, SeePlayer, EnemyNotVisible, HearNoise, UpdateEyeHeight, SeeMonster, SeeFriend, SpecialHandling, BotDesireability.

•	Disable: Disables a probe event.

•	GetPropertyText: Converts the value of an arbirary variable to text.

•	SetPropertyText: Sets the value of an arbitrary variable from text.

•	SaveConfig: Saves the current values of all "config" variables to the Unreal.ini file.

•	ResetConfig: Resets the values of the "config" variables to the originals in the Default.ini file.

Static Functions:

•	ClassIsChildOf: Returns whether one class is a subclass of another class.

•	GetEnum: Returns the nth element of an enumeration.

•	DynamicLoadObject: Tries to load an object from a file, and returns it.

Events:

•	BeginState: Called when a new state is entered.

•	EndState: Called when the current state is ended.

Engine.Actor

Functions:

•	Error: Causes a critical error; exits the engine.

•	SetCollision: Changes the actor's collision flags.

•	SetCollisionSize: Changes the actor's collision size.

•	Move: Moves the actor by the specified displacement vector, handling collision (based on the collision flags), Touch and Bump notifications.

•	MoveSmooth: Like move, but smoothly brushes against walls.

•	SetLocation: Teleports the actor to a new location.

•	SetRotation: Sets the actor's new rotation.

•	SetBase: Sets the actor's Base. A base of None means that the actor moves alone; setting the base to another actor in the world causes this actor to move and rotate along with its base. An example of using a base is standing on a moving platform.

•	SetOwner: Sets this actor's owner.

•	IsA: Return whether this actor belongs in a named class.

•	PlayAnim: Plays a named animation sequence in the actor's Mesh once (use the Mesh Viewer in UnrealEd to see the animation sequence names for a given mesh). The optional Rate scales the animation's default rate. If a nonzero TweenTime is specified, the animation is first tweened from whatever is currently displayed to the start of the named animation sequence, before the animation sequence plays. When the animation playing completes, it stops and calls your optional AnimEnd() event and causes any latent FinishAnim() calls to return.

•	LoopAnim: Like PlayAnim, but loops the animation sequence over and over without end. As with PlayAnim, the AnimEnd() is called at the end of the sequence, and FinishAnim() calls return at the end of each iteration of the loop.

•	TweenAnim: Tweens from whatever animation is currently being displayed, to the start of the specified animation sequence, then stops and calls AnimEnd() and releases any latent FinishAnim() calls.

•	IsAnimating: Returns whether the actor's mesh is currently animating.

•	GetAnimGroup: Returns the group name of the specified animation sequence.

•	SetPhysics: Sets the actor's current physics mode.

•	BroadcastMessage: Sends a text message to all players.

Latent Functions:

•	Sleep: Waits for a certain (fractional) number of seconds to pass, then continues.

•	FinishAnim: Waits for the currently playing or looping animation to reach the end of the sequence.

•	FinishInterpolation: Only relevent with the physics mode PHYS_Interpolating. Waits until the next interpolation point is reached.

Iterator Functions

•	AllActors: Iterates through all actors in the level with the specified tag; if you don't specify a tag, it iterates through all actors in the level. This is pretty slow if you specify a tag, and very slow if you don't.

•	ChildActors: Iterates through all actors owned by this actor.

•	BasedActors: Iterates through all actors directly based on this actor.

•	TouchingActors: Iterates through all actors touching this actor. This is fast.

•	TraceActors: Iterates through all actors hit by a trace along a line with an optional collision extent. This is pretty fast.

•	RadiusActors: Iterates through all actors within a specified radius. This is fast.

•	VisibleActors: Iterates through all actors visible to this actor (using a simple line trace, rather than exact mesh-to-mesh visible). This is very, very slow.

•	VisibleCollidingActors: Iterates through all actors visible to this actor which have collision enabled; this is much faster than VisibleActors.

Events:

•	AnimEnd: Called when the currently playing or looping animation reaches the end of the sequence.

•	Spawned: Called when an actor is spawned during gameplay. Never called if the actor is preexisting when a level is loaded.

•	Destroyed: Called immediately when an actor is destroyed. This event is not delayed like Java's Finalize() event is.

•	Expired: Called immediately before Destroyed() when an actor's LifeTime has counted downward past zero.

•	GainedChild: Another actor has done a SetOwner() to this actor.

•	LostChild: An actor owned by this actor has been destroyed or done a SetOwner() to another actor.

•	Tick: Called each iteration of the game loop; varies depending on frame rate. DeltaTime indicates how much time has passed.

•	Trigger: This actor has been triggered by another actor Other, optionally caused by a pawn EventInstigator.

•	UnTrigger: This actor has been untriggered by another actor Other, optionally caused by a pawn EventInstigator.

•	BeginEvent: A simple protocol to indicate that this actor called a Trigger() function that began a complex chain of events. This enables switches to be coordinated with doors intelligently, i.e.: You press a switch. The switch moves in. It triggers a door which calls your BeginEvent() then slowly opens. The door then calls your EndEvent(). Now you move the button back out to give the user feedback that the button is finished with what it was doing.

•	EndEvent: The event specified by BeginEvent has ended.

•	Timer: If you call SetTimer, this Timer() function is called each time the timer has counted down from your time value.

•	HitWall: This actor ran into a wall while moving.

•	Falling: This actor has transitioned into PHYS_Falling.

•	Landed: This actor has transitioned out of PHYS_Falling.

•	ZoneChange: This actor has entered a new zone.

•	Touch: This actor has begun touching (interpenetrating) another actor.

•	UnTouch: This actor has stopped touching (interpenetrating) another actor.

•	Bump: This actor has bumped into an impenetrable actor.

•	BaseChange: This actor's base has changed.

•	Attach: Some other actor has set its base to this actor.

•	Detach: Some other actor based on this one is no longer based on this actor.

•	KillCredit: This actor has successfully killed another actor.

•	SpecialHandling: ?

•	EncroachingOn: This actor is now encroaching on (overlapping with) another actor as a result of moving and it may return true to abort the move, or false to continue the move.

•	EncroachedBy: This actor has been successfully encroached by (overlapped by) another actor. This is where players may opt to telefrag themselves or ignore the encroach.

•	InterpolateEnd: Called when Physics==PHYS_Interpolating and the next interpolation point has been reached.

•	KilledBy: Called when killed by another actor (killed just means dead, it doesn't mean destroyed).

•	TakeDamage: A certain amount of damage has been imparted on this actor.

•	PreTeleport: Called before this actor is teleported by a teleporter.

•	PostTeleport: Called after this actor is teleported by a teleporter.

Physics Modes:

•	To be written.

Game Startup:

When programming new actor scripts, you need to be wary of the order in which actors that pre-exist in a level (at load time) are initialized, and the order in which new actors are initialized when they are spawned. The exact order of initialization is:

The actor object is created and its variables are initialized to their default values (if spawning an actor), or loaded from a file (if loading a pre-existing actor).

The actor's location, rotation, and owner are set.

If the actor is being spawned, its Spawn() event is called.

The actor's PreBeginPlay() event is called.

The actor's BeginPlay() event is called.

The actor's zone is set, and any ZoneChange messages are sent to the actor, and any ActorEntered messages are sent to its zone. Prior to this point, the actor is not in a valid zone, and you must not call the Move, MoveSmooth, SetLocation, or SetRotation functions, or any functions which call them.

The actor's PostBeginPlay() event is called.

The actor's SetInitialState() event is called.

If the actor hasn't set its base yet, its base is set.


Console Commands

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

Audience: Advanced Users, Server Administrators, Programmers.

Command Line Parameters

•	-profile: When C++ is compiled with DO_SLOW_GUARD=1, generates an UnrealScript function profile using the timings in the most recently played level only.

•	-nosound: Disables sound.

•	-nodsound: Disables DirectSound support.

•	-noddraw: Disables DirectDraw support.

•	-nohard: Disables 3d hardware support.

•	-log: Runs with the log window initially visible.

•	-firstrun: Re-asks the "First Run" questions in Unreal.

•	-nologwin: Don't output to log window, useful for debugging when printing so many log messages that performance is slowed down by window updates.

•	-conflicts: Show objects of different classes whose names conflict.

•	-nok6: Disable AMD K6-3D support.

•	-nommx: Disables MMX support.

•	-noreplace: Don't automatically replace textures, sounds, and music if they are not found.

•	-make: Rebuilds all .u files from their source .uc files.

•	-make -h: Rebuilds all .u files from their source .uc files and generate a C++ header for each package.

•	-editor: Runs Unreal for editing.

•	-server: Runs as a dedicated server.

•	-strict: Treat all script warnings as critical errors; useful for tracking down the call stack when debugging scripts.

•	-nobind: Don't treat UnrealScript/C++ binding errors as critical, for rebuilding scripts and avoiding the chicken-and-egg binding problem.

•	-showdep: Causes script compiler to log dependency information when recompiling scripts.

•	-nogc: Disables garbage collection.

•	-alladmin: Enable all players administrative access to the server.

•	LOG=logfilename: Uses the specified log file instead of Unreal.log. Useful when running multiple copies on the same machine.

•	INI=inifilename: Sets the .ini file to use for configuration, normally Unreal.ini.

•	READINI=inifilename: Sets the .ini file for reading only (not for writing); overrides the INI= option.

•	PORT=num: Sets the UDP port number for the Internet server.

•	MULTIHOME=12.34.56.78: Sets the "home" ip address (in numerical format) for Unreal of a machine with multiple network cards.

C++ Console Commands (Only works on the local machine)

•	BRIGHTNESS: Cycle through 10 screen brightness values.

•	CHAT: Brings up a prompt to type chat text.

•	CANCEL: Cancels an "open" command in progress that is trying to connect to a network server.

•	CDTRACK num: Play the specified CD track.

•	CONSOLE FULL: Make the console fullscreen.

•	CONSOLE HIDE: Hide the console.

•	CONSOLE SHOW: Show the console.

•	DEBUG CRASH: Test crashing the game by appError.

•	DEBUG EATMEM: Test allocating memory until it fills up.

•	DEBUG GPF: Test a general protection fault.

•	DEBUG RECURSE: Test crash by infinite recursion.

•	DUMPCACHE: Display the contents of the memory cache GCache.

•	DUMPINTRINSICS: Display a list of unused intrinsic function ids.

•	EDITACTOR CLASS=classname: During game play, edits the properties of the nearest actor belonging to that class. Cool for debugging.

•	ENDFULLSCREEN: Go back to playing in a window.

•	EXEC filename: Execute the console commands in the filename, default is in the System directory.

•	EXIT: Exit the program.

•	FLUSH: Flush all caches. Regenerates all lighting, 3d hardware textures, etc.

•	HIDEACTORS: Hide actors during game play.

•	JUMPTO x y z: In UnrealEd, move the viewport to a certain X,Y,Z location, useful in conjunction with tester reports generated with the REPORT command.

•	LOADGAME num: Load a game in position 0-9.

•	MARK: Mark all objects that are in memory (for garbage collection debugging in conjunction with MARKCHECK).

•	MARKCHECK: Display a list of all unmarked objects that are in memory (for garbage collection debugging in conjunction with MARK).

•	MEM: List memory usage; only works when Unreal is compiled with the memory-tracking option (it's usually not).

•	MEMSTAT: Show Windows overall memory statistics.

•	MUSICORDER num: Change to a certain track in the song (0=ambient, 1=action, 2=suspense).

•	OBJ CLASSES: Prints a list of all loaded classes.

•	OBJ DEPENDENCIES PACKAGE=pkgname EXCLUDE1=otherpackage EXCLUDE2=otherpackage...: !!

•	OBJ GARBAGE: Collect and purge garbage ("garbage" means objects which are no longer in use).

•	OBJ HASH: Show object hashing statistics.

•	OBJ LIST CLASS=objectclass: List all objects belonging to the class (if the class isn't specified, lists ALL objects). Gives a summary of memory usage. This is very useful during game play for figuring out how much memory is being used. In UnrealEd, this statistic isn't useful because a huge amount of extra stuff is loaded which might not be used by your map.

•	OBJ REFS CLASS=objectclass NAME=objectname: Show a list of objects which reference the object you specify. When trimming memory usage, this is useful for figuring out why some object is being loaded.

•	OPEN url: Opens a local map (i.e. "unreal.unr") or an Internet server (i.e. "200.0.1.16" or "unreal.epicgames.com").

•	PREFERENCES: Displays the preferences in a window.

•	REPORT: Copies a report of the current gameplay situation to the clipboard. You can then paste the resulting text into an email program, Notepad, etc. Extremely useful for beta testers, because it dumps the player's X,Y,Z location, the difficulty level, etc.

•	RMODE: Set the rendering mode. 0-9.

•	SAVEGAME num: Save the game in a specified position, 0-9.

•	SHOT: Take a screenshot and save it in the System directory with a consecutive name like Shot0001.bmp.

•	SHOWACTORS: Shows actors during gameplay.

•	SOCKETS: In network play, shows a list of network sockets (UNetConnection's) in use.

•	STAT ACTOR: Shows various statistics.

•	STAT CACHE

•	STAT CLIP

•	STAT FILTER

•	STAT FPS

•	STAT GAME

•	STAT GLOBAL

•	STAT HARDWARE

•	STAT ILLUM

•	STAT LIGHT

•	STAT MESH

•	STAT POLYC

•	STAT POLYV

•	STAT REJECT

•	STAT OCCLUSION

•	STAT SOFT

•	STAT SPAN

•	STAT ZONE

•	TOGGLEFULLSCREEN: Toggles fullscreen mode on and off.

•	TYPE: Types text on the console.

•	URL urlname: In network play, parses a URL and displays its components.

•	VIEWUP: Sizes the view up.

•	VIEWDOWN: Sizes the view down.

UnrealScript console commands (Can be used by remote administrators)

•	ADDBOTS <number>: Adds more bots to the game.

•	ALLAMMO: Gives you all the ammo for your current weapons.

•	GOD: Makes you invincible.

•	INVISIBLE: Makes you invisible.

•	KILLALL <class name>: Kills all actors of a certain class, for example "KILLALL UNREALI.BRUTE".

•	KILLPAWNS: Kills all monsters.

•	PLAYERSONLY: Pauses all non-player actors in the game. Cool for debugging scripts, taking screenshots.

•	SAY <message string>: Broadcast a message to other players in the game.

•	SLOMO <number>: Sets the game speed, 1.0 is normal.

•	SUMMON <class name>: Spawns an actor of the specified class (for example, SUMMON UNREALI.BRUTE) in front of the player.

•	SWITCHCOOPLEVEL <new level URL>: Causes the server (or local machine, in a single-player game) to switch to a new level with coop-style weapon carrying between levels.

•	SWITCHLEVEL <new level URL>: Causes the server (or local machine, in a single-player game) to switch to a new level.

Console configuration commands

•	GET <classname> <variablename>

Gets a configurable class parameter. <classname> may be a partial classname, such as "playerpawn", or a qualified classname such as "engine.playerpawn". The class must be loaded in memory, otherwise GET returns an empty string. <variablename> must be the name of a variable that is designated as configurable (either in UnrealScript using the "config" keyword or in C++ using CPF_Config). This returns the value of the configured variable, converted to a string. The value returned by GET reflects the class's default value (for scripted classes, this is the default value that was set for the class using its property sheet). At any time, zero or more instances of objects belonging to <classname> may be in memory, and may have modified values of <variablename>, and they don't affect the value returned by "GET".

•	SET <classname> <variablename> <value>

Sets the default value of a class's variable. If the class is designated as configurable (using the "config" keyword in UnrealScript or CLASS_Config in C++), and so is the variable, this function updates the Unreal.ini file to reflect the new default value. If any instances of objects belonging to <classname> are in memory, all of those objects are updated. When an object's config variables are updated, they are notified as follows:

The object's PreEditChange() function is called, basically saying "Get ready to be modified!"

The object's configurable variables are updated with the newly configured values.

The object's PostEditChange() function is called, saying "You've been modified, so validate and update yourself".

This procedure enables objects to validate their configurable properties and update themselves. For example, the audio subsystem's PostEditChange() function clamps the sound volume to a safe range of 0.0 - 1.0 (because the SET command enables users to set it to ridiculous values) and then updates the actual volume of the sound effects that are playing.

Unreal Key Bindings

In the Unreal key bindings (under Advanced Options / Advanced / Raw Key Bindings), you can associate console commands and other special input commands with key presses and releases. In the text box next to a key name, you can type in one or more console commands, separated by the "|" character. For example, to bind the "S" key to the "Jump" alias, type this:

    Jump

That causes the "Jump" alias to be executed when th user presses the "S" key. For another example, if you want to bind a chat message to a key, use this:

    Say "Come get some!"

In addition, you can bind multiple actions to a keypress like this, to make the "S" key both jump and say a message.

    Jump | Say "Come get some!"

You can also bind an action to the release of a key by using the OnRelease keyword. For example, you can make the "S" key fire when it's released:

    OnRelease Fire

Or you can make the key jump when pressed, and fire when released:

    Jump | OnRelease Fire

Keys can be bound to any of the following kinds of things:

•	Any console command in the above lists.

•	Any key alias (explained below).

•	Any special input command.

"Special input command" refers to console commands which only make sense in conjunction with the press or release of a key, or the movement of the mouse or joystick along an axis. The special input commands are:

•	BUTTON <UnrealScript boolean variable name>, for example "BUTTON bFire": Maps a button to an UnrealScript variable stored in the Pawn class or any subclass. This tells the input system to automatically set the variable to True when the key is held down, and False when it's not pressed. For example, the Pawn script looks at bFire to tell whether the fire button is being held. The setting of bFire is not some hardcoded behavior of the engine, rather it is propagated into UnrealScript code by the input system, as a result of binding a key to "BUTTON bFire".

•	TOGGLE <UnrealScript boolean variable name>, for example "TOGGLE bLook": Like the BUTTON command, but simply tells the input system to toggle the boolean variable's value when the key is pressed.

•	AXIS <UnrealScript floating point variable name> <SPEED=some number>, for example "Axis aStrafe Speed=-300.0". Maps an analog input axis movement to an UnrealScript variable, scaling it by some factor. The current axis keys listed in the Advanced Options menu are: MouseX, MouseY, MouseW (Intellimouse wheel), JoyX, JoyY, JoyZ, JoyR (joystick rudder), JoyU, JoyV (joystick alternate axis for example the Panther XL trackball). Supported PlayerPawn axes are aBaseX, aBaseY (base movements which are translated to rotating, strafing, looking, and forward movement based on context), aMouseX, aMouseY, aForward, aTurn, aStrafe, aUp (not used), aLookUp, aExtra0-aExtra4 (not used). To see how the game code processes movement, see the PlayerPawn class's PlayerInput and PlayerTick functions.

In addition to the Advance Options menu, you can also bind keys from the console using the following command:

SET INPUT <keyname> <binding>

For example:

SET INPUT X Fire

SET INPUT Enter Fire

Unreal Key Aliases

Key aliases are listed in Advanced Options / Advanced / Input Aliases. Aliases provide a convenient way to map one word (for example, "Jump") to a complex series of console commands that carry out a particular action. For example, the "Fire" alias is defined as: "Fire | Button bFire". This has the effect of calling the UnrealScript "PlayerPawn.Fire" function (aliases are not recursive), and then causing the input button bJump to be set to True as long as the key is held.


Contact Information

This area is to help you contact the people who made some of the tutorials in this manual:

Skarz	-	www.skarz.com	-	help@skarz.com

Jon Renner	www.unrealism.com/design/	jonr@telefragged.com


Contents

About This Manual

Installing This Manual

AI and Physics

Packages

Zones

Tutorials

References

History

Links


Creating A Basic Room

Basic Information - by Jon Renner

This tutorial will guide through the process of making a room, adding a light, and adding a PlayerStart. But before we start, it may be a good idea to look at the User Interface Guide. This will explain what all the buttons, menus, and scroll bars do.

We'll start by making the area for the player to walk around in. The Unreal World is made up of a giant block of matter. So unlike quake, it is not a void with you fill, it's a mass which empty or "carve" rooms out of. The basic tool used to make rooms is called your building brush. It is the red wire-frame object that appears in your World view windows. press the Cube, Sphere, Stairs, etc. buttons to change the basic shape of the building brush. The scaling tool and the constricted scaling tool can change the size of the building brush, while the shearing tool can deform the brush. Once again, take a look at the Interface Guide if you don't know where those tools are. At any time, you go under the "Brush" menu at the top of screen and click on Reset->All to put your brush back into a normal shape.

Now, click on the cube button to get our building brush ready. Press CTRL and left click+drag in the 2D or 3D views to move the brush around. At this time we should select a texture. Make sure the "Browse:" scroll-down bar on your right-hand toolbar is set to Textures, and click on the Load button at the bottom of the screen. You can load any sey you want, they are somewhat self-explanatory as to what they contain. The selected texture will define the interior of the areas you subtract from the "world mass" but the textures can be changed at a later time by selecting the surface and clicking on a different texture in the browser. When you are satisfied with your brush position, press CTRL-S or click on Subraction Toolbar icon in the left window to subtract the area from your world mass. At this point press F8 an rebuild your level. It should turn dark. To stop it from turning dark you can turn off the "auto bsp" checkbox and only rebuild the geometry.;

It's time to add a light, this is incredibly easy fortunately. hold down L and left click to place a light. you can then use CTRL Left click+drag to move the light around in any view. Double click on the light to edit it's properties. The properties that affect lighting are under the "Lighting" and "LightColor" menus. If you turn on real-time updating you can see how these properties change the way your room is lighted.

Now we will add the PlayerStart. Change the "Browse:" menu that we used to load texture to "Classes" and expan the "Actors->Navigation->PlayerStart" thread. Don't double click on the words, because this will bring up the UnrealScript editor. Instead click on the plus and minus icons. Once the "PlayerStart" is highlited right click in any 2D or 3D view and click on "Add PlayerStart" here (this same method can be used for adding any other actor).

Rebuild your level and check it out. (Note: If something seems strange in your level - try rebuilding, this often fixes and updates your level geometry and lighting.)


Creating Optimized Levels

Overview

This is a quick overview of how to create levels in UnrealEd that will play as quickly and smoothly as possible.

Reducing Polygon Count

The two main factors in Unreal’s frame rate are the number of polygons visible at a given time and the total number of polygons in the world.  The more polygons there are, the slower Unreal will be.  So, one of your prime directives as a level designer is to create interesting levels with as few polygons as possible.  Here are some tips for reducing your polygon count:

1. Put the camera into “PolyCut” view from time to time.  This will show you the actual polygons that Unreal is dealing with, along with all of the cuts that it had to perform to sort them properly.  Check out the PolyCut view to get a feeling for how badly your world is cut up, and use it as a guide in reducing cuts.

2. Align your brushes carefully.  Well-aligned brushes tend to fit together without creating unnecessary cuts in the world.  Slightly misaligned brushes, for example subtracting a doorway out of a wall but embedding it slightly into the floor, often creates 2-3 times more polygons than you need.  Check your alignment in the 2D camera views carefully before performing an add or subtract.

3. Use semi-solid brushes for adding decorations like pillars.  Semi-solid brushes look like regular brushes, but they have the added benefit of not cutting the polygons in the world around them.  They are especially useful for decorations that penetrate the floor, like pillars, because they don’t chop up the floor like regular brushes do.  However, only use Semi-Solid brushes for decorations, not large objects in levels.  Player collision won’t work properly if a player collides with more than one semi-solid brush at a time.

4. Go into Map Edit mode and move all of your large, subtractive brushes to near the front of the order.  They should be ahead of only the large additive brushes that they are intended to subtract from.  This gives UnrealEd a useful hint on how to subdivide your level efficiently.  In addition to reducing polygon count, this technique also speeds up your geometry rebuild times considerably - often up to twice as fast.

5. Go into Map Edit and move all of the small “decoration” brushes to the back of the order.  They should be behind all of the large additive and subtractive brushes that your level is made of.  This helps to prevent small decorations from cutting large objects.

Other Performance Improvements

1.	When you want a room to look like it has an open ceiling, use “Fake Backdrop” instead of cutting the ceiling out of the area.  This creates a significant speed improvement in complex levels, because it lets Unreal deal with a small visible area (the room you’re in) rather than the huge visible area that goes from where the player is off into the far-away backdrop.  You should only make truly open, outdoors areas when the “fake backdrop” effect can’t handle what you want to do.

2.	If you create complex architecture, it’s best to put it in a highly-occluded area.  The ideal Unreal level contains a lot of areas containing interesting, detailed architecture, connected by sets of relatively small, simple passageways.  That way, you’ll never suffer from the awful performance hit that will result from the player seeing into several complex areas at the same time.

3.	Unreal performance is determined by one main factor: The number of polygons immediately visible to the player.  The relative sizes of the polygons don’t matter too much.  Your mission is to create as detailed architecture as possible, while making sure that the player can’t see too many polygons at any time.

Practical limitations

An UnrealEd level has a practical limit of 15,000 BSP nodes and 7,500 polygons.  You can see these statistics in the Rebuilder dialog.  Though you may be able to create larger levels than this, they will perform badly.  In general, smaller is better - a 5000-node level will be significantly faster than a 15,000 node level.


Dealing with Map Corruption

Overview

UnrealEd’s fast constructive solid geometry method is imperfect in that it’s possible to corrupt a level’s geometry by adding and subtracting brushes in certain configurations.  For every 20 hours you work with UnrealEd, you will probably run into corrupt geometry once.  Fortunately, it is easy to recover from this problem.

One easy way to corrupt UnrealEd’s geometry is to create a sphere with 100 or more polygons, add it to the world, rotate it very slightly, then subtract it.  Repeat this process several times.  The resulting mess contains thousands on sliver polygons (described below), which tend to destabilize CSG operations.

If you follow the guidelines below, you should be able to create very large levels (over 20,000 polygons) without running into any corruption problems.  If that fails, methods of cleaning up corrupt levels are described below.

Identifying corrupt level geometry

When a level’s BSP has become corrupt, you will notice one or more of the following symptoms:

·	Polygons are missing or out-of-place, for example dangling in mid-air.

·	Adding or subtracting brushes in a particular area yields missing or incorrect polygons.

·	When walking through a level during play, the player gets hung up or trapped for no apparent reason (this can also happen when the geometry is not corrupt; see Unreal Metrics for more information).

Avoiding corrupt geometry

The best way to deal with corrupt geometry is to design levels in such a way that you avoid it.  The following design methods will help greatly:

Avoid tiny polygons: Avoid operations that result in very small polygons (less than 4 units by 4 units).  In addition to cluttering the map, small polygons tend to interfere with correct CSG operations.

Avoid sliver polygons: UnrealEd can choke on long, skinny polygons that look like splinters.  These polygons are often confused with straight lines and they cause UnrealEd to lose track of the level’s continuity.

Avoid sharp angles between brushes:  For example,  avoid creating wedge shapes.  In addition to causing player-movement difficulties, extreme wedges are unstable.

Try to overkill when adding and subtracting brushes:  For example, if you’re adding rafters to the top of a room, make them slightly wider than the room.  If you’re adding a stairway onto a floor, stick it slightly into the floor.

Cleaning up corrupt geometry

If you do encounter corrupt geometry in your level, chances are that the corruption is due to one of the problems described above, and it most likely occurred near the area where you see the problems.

To clean it up, turn on Map-Edit mode and examine the brushes around the area where the corruption occurred.  Move them around a bit, making an effort to lessen the tiny-polygon, sliver-polygon, and sharp-edge problems described above.

Also, if you created any large brushes via intersect or deintersect, make sure that the brushes aren’t corrupt as described above.


Design Tips

(Mostly from Cliff Bleszinski)

* As of the current game collision, you cannot make a (sewer) grate out of polygons (rods, beams, whatever) and walk over it without getting stuck. Well, I found a way around this. First, create your grate like you normally would (adding skinny rectangles works. <G>) Second, add a special brush over the top of the grate- set the properties to MASKED, SEMI-SOLID, 1 SIDED and use the NOTHING texture in the DECO.UTX group (Skarz Note: I think he ment the in the SkyCity.utx file sub-group). This creates an invisible wall over the grate that prevents the player from getting caught in the tiny holes.

* You can cut _brilliant_ spiral/curved staircases out of any solid section using the spiral staircase brush. Take a look at the MALYMAL map (on the epic FTP site) to see an excellent example of using curvy stairs well. Most (if not all) of these staircases were done with the spiral staircase feature instead of the curving stair feature. Simply make the step height 128 or so and don't fill the interior/exterior, and you can cut a nice staircase out of anything.

* Right now we all seem to enjoy making large, gorgeous, and panoramic rooms. Remember that smaller, more compact areas run faster and can look just as cool and usually feel scarier.

* Try to not set up your levels so that the player will have to do a lot of direct backtracking/errand boy BS. This was frequent in a lot of Doom levels, and I kept getting lost because of it. Basically, the wrong way (IMHO) to set up a 1 player game map is to have 90% of the level instantly accessable from the start and then send the player off on a wild goose chase to find 4 keys that are planted in 4 remote locations that all look similar. The way that I'd like to see these levels work is a steady progression of difficulty/exploration that allows the player to enter one area of the map, explore/kick ass/collect, and move onto the next.

* Also, since we can do anything in this engine, take advantage of putting "stuff over other stuff." Make bridges whenever you can, make rooms above other rooms.  Try making a room that's pretty tall, then have the player eventually walk across a bridge that spans the room. Since we're taking the time to make all of

these cool/detailed rooms, have the player return to them but in a different position (below the room, above it, crossing it on a bridge, seeing it through a window again later on, etc.)

More later.


Fog

Fog Tutorial - by Jon Renner

Download the map for this tutorial - fog.unr   (http://www.unrealism.com/design/files/fog.unr)

Fog is surprisingly easy to create. Before you start this tutorial, you'll want to have a room with a playerstart and a light inside it, this is all you will need.

Find the Actors->Info->ToggleZoneInfo thread under the Classes menu. Select the ToggleZoneInfo and add one to your room. Now double click on the ToggleZoneInfo and look for the header titled "ZoneInfo". Open this header and change "bFogZone" to "True".

Now, double click on your light and expand the "Lighting" header. There are three properties that will affect your fog. "VolumeFog" "VolumeBrightness" and "VolumeRadius".

•	VolumeFog changes size of the fog cloud.

•	VolumeBrightness changes the brightness of the fog. A higher setting makes the fog appear more dense.

•	VolumeRadius has to do with how close the fog appears to the player. There is a natural "bubble" around the player in which he/she does not see fog, VolumeRadius affects the size of this bubble.

Finally, Rebuild (F8) your level and check it out.


Getting Started with the Unreal World Editor

World map

The world map is the central area where players go to explore an Unreal world.  The world map is filled with terrain, which differs in many ways from levels that you create.  The world map also contains individual game levels, which the player can explore.

Levels

However, the Unreal Editor’s main function is to create game levels.  The entire editing region you see around you, consisting of everything inside it, is called a map.  If you add the right actor and game-play information, it will become a playable level.

Cameras

Each of the views (windows) you have open on the world shows you a different camera view.  There are a number of types of views available to you:

Wireframe	Shows you only the brushes which make up the world.

Polygon   	Adds simple gray polygon faces to the brushes.  This is the real geometry, but without the detail.

Textures  	Shows you the textures of the polygons in your world.  No lighting is applied, so all textures will be of a consistent brightness.

Lighting  	Adds estimated lighting to the textures, so you can get a feel of how they will look with your lights applied without slowing down your redraw speed too much.

Shadows  	Adds shadows to the lighting of the textures.  Now, you will see more graduated lighting, but it exacts a performance penalty to draw.

2-D View 	This will give you a grid view of either the X, Y, or Z planes of your map.  This view only shows the wireframes of the brushes you used.  For example, you can see a top-down view of your map, showing how the layout would look to an architect.

Brushes

A brush is the basic unit you’ll use to build levels.  Unlike most 3D modeling programs, the Unreal World Editor uses Constructive Solid Geometry -- an advanced method of modeling that enables you to build with large objects, rather than with individual polygons.

Textures

After you start giving the world shape and form, you will want to add color and surfaces to the world.  The front face of the block you just made might look like wood paneling, while another face might have carved stone figurines on it.  Every polygon face in the game can be given a different texture, along with a number of special graphical effects.  In addition, the textures can be moved, scaled, rotated, and so on to allow you to make the graphic appear exactly as you want it.  This allows you to create a hole for a doorway and position a graphic exactly around that hole to make it look like a real arched doorway.

Map Editing Mode

Normally, there is no way to change the map you have created.  Once you add or subtract a brush, it is there forever.  However, you can enter the special map editing mode, which allows you to manipulate the brushes (move, add, or delete) you have previously added to or subtracted from your world.

This mode is activated by clicking on the map icon in the toolbar.  In this mode, the solid geometry is inactive, so you cannot view the textures or polygon faces within the level.  All you will see is a wireframe view.

After you are done, you must rebuild the map in order to view the geometry again.  This can take some time, so it is best to plan ahead to avoid waiting for your computer.

Rebuilding

The Options/Rebuild... dialog is a key aspect of the Unreal editor.  Many elements in a level aren’t updated as you edit the level, and must be updated by using the Rebuild... dialog.  These elements are:

Map Geometry: Rebuilding the map’s geometry goes through all of the brushes in a level and adds or subtracts them in order.  This is needed after moving or deleting brushes in map editing mode.

BSP: The BSP is a complex data structure that holds all of the visible polygons in a level.  Rebuilding the BSP cleans up the level and usually reduces the number of polygons in the level.  The fewer polygons, the faster the editor’s and game’s performance will be.

Lighting: Rebuilding the lighting causes all lights in the world to be applied to polygons, and correct shadows generated for them.  Lights and shadows are not automatically updated as you move them around.

Actors

“Actor” is a generic term for anything in a level that can move, change, or be affected by gameplay.  Actors include players, monsters, pickups, weapons, teleporters, doors, lights, and platforms.

You can add actors to the world, delete them, and set their properties.

The type of an actor is referred to as its “Actor Class”.

For those familiar with object-oriented programming, actor classes are set up as a hierarchy where child actor classes inherit both properties and default actions from their parent class.

Lights

Lights are a special kind of actor.  Lights, of course, illuminate polygons and actors around them, and they can also cast shadows.  You can add them, delete them, and set their properties.

Also See: Unreal Metrics and Specifications, Design Tips, Dealing with Map Corruption, and Creating Optimized Levels


Hello Room

By: Skarz

Introduction:

Ever since I entered the Unreal scene (with my Unofficial UnrealED Manual), I have gotten many emails from people trying to start their first map and having trouble doing so. I have tried many of the tutorials out there and while many of them go step by step to get the goal accomplished, many of them don’t actually explain WHY they are doing what they are or WHY a tool works a certain way. Well I hope that my tutorials will help you to better understand WHY you are doing what you are. Let’s get started…

Theory of Unreal Level Design:

I assume that many of you are familiar with how to make a level in Quake or something similar. This will help, but is not a necessity. In the past, when you made a room in Quake or whatever, you would start with a big empty void- and add a room to it. This void could be like working in outer-space. There is nothing to start with, you just build in the void. This was done by making walls with a thickness on all sides as well as a floor and ceiling.

Well in the land of UnrealED, the world is already solid. This would be like working underground. In UnrealED, you subtract from the solid. This means that instead of building a room with walls and stuff, you can just take a cube (known in UnrealED as a brush) and subtract it. Your walls don’t need a thickness to them- unless you are making inner walls in your room of course. If you did take a cube and told UnrealEd to make it hollow, like you would in Quake, you end up living in the walls (the part that is cut out is in the wall space- not in the center of the room). With this in mind- lets make a room!

Hello Room Tutorial:

Follow each of these steps and we will have you building a room in no time!

1). Load UnrealED (if you haven’t already) - This will put you in a blank, solid world. Ready to make your own level (well at least this one room for now). Also make sure your Unreal CD is in the drive.

2). Load some textures. The first thing we should do is load up some of Unreal’s cool textures to use for our walls and stuff. When you first load UnrealED, none of the good textures load with it, so it’s up to us to load what we want. On the very top right-hand side of the UnrealED interface you will see combo-box (pull-down menu) next to the word BROWSE. The default should already be on textures- if it’s not then select “Textures” from the pull-down.

Now along the right you will see a bunch of textures already loaded. These textures are for special things (like the player skins) and not good fo making walls and stuff. Below this part of the interface (the very bottom right side) you will see some buttons. We want the “Load” button. Press the load button and you will get a file selector all ready set to the default texture area. Select the file called “Ancient.utx”. This has a lot of nice textures to work with. After you select that file, you will see them load in and pop up in the texture area for your viewing pleasure.

3). Find a good wall texture that looks good to you. You can either scrol through all the textures or select the bottom most combo-box at the top right and select “Wall”. Right now it should say “(All)”

 which shows you all the textures in the Ancient.utx pack. After you fond a good wall texture, proceed to step 4.

4). Make a cube. First we want to set up the cube dimension. Right-Click (use the right mouse button) on the Cube Brush button on the left hand side. It is three over and seven down. It looks like a 3D cube or box. When you do this a pop-up menu will appear. Select “Cube Properties..” from the list (it will be the top most selection).

When you do this the “Build a Cube” window will come up. Make sure it is selected to be a solid- NOT HOLLOW. It will be selected to be a solid by default. Now we are going to tell UnrealED how big we want our room. Lets make a big room. Set the Height to 512, the Width to 1024, and the Breadth to 1024. Forget the other stuff for now. Hit the “Build” button. This will make an outline of your cube in the world. Now select the “Close” button to close the window.

5) Now you are ready to subtract your cube from the solid world to make a room. Woohoo! The subtract button is three over and two down (left click it)- or you can select “Subtract” from the “Brush” menu. There the same thing. When you do this, the room appears and uses the wall texture you selected above for it’s texture. In the 3D (preview) window. Move over and into you room. This way you can look around and see all the walls. As you can now see- the room is nice and big.

6). Now let’s put a ceiling and floor texture in our room. To do this you just select (left-click) on the floor or ceiling in the 3D Preview window. Once it is selected it will highlight with blue. After you do this, you may then select a good floor and ceiling texture for your room. Just click on a texture and it will change what you selected before your eyes! Try going to the “Floor” or “Ceiling” texture areas (by using the pull-down menu like when you went to the “Wall” area)

7). Now we need a light to make things look cool and Unreal-like. Luckily UnrealED is already set up for adding lights into your world. All you need to do is Right-Click on the map were you want your light. You can do this in any of the views. Use the top view (top-left side) this time- it works well. Just select  “Add Light Here” from the pop-up menu. If you need to move the light, just select the light (it will highlight green) and then hold down the left mouse button and the Control button (Ctrl on the keyboard) at the same time, and move the light around. You use this keyboard/mouse combo to move anything in UnrealED.

8). Now we need to tell Unreal were to start the player (you) when you play the map. This is called the PlayerStart class. To add a class go to the very top right-hand side of the UnrealED interface and use the combo-box (pull-down menu) next to the word BROWSE. This is the same one mentioned earlier for selecting textures. This time select “Classes” from the pull-down. The texture area will go away and be replaced by a list of some classes. Under the “Actor” class you should see a list of sub-classes. Left-click on the minus sign next to the “NavigationPoint” class. This will “expand the NavigationPoint class to show you it’s sub-classes. Select the class called “PlayerStart” so it is highlighted.

Now to put a player start in the room just Right-Click in the room were you want the player to start (just like putting a light in) and select “Add PlayerStart Here” from the pop-up menu. Make sure you won’t be stuck in a wall or anything!

9). Now we will build the map and try it! Press the “F8” key on the keyboard. This will bring up the “Rebuilder” window. Just hit the “Rebuild Geometry” button at the bottom of the window. Your level is processed and now should be lit by your light instead of being all bright (looks better huh?). Now press the “Close” button to close the window.

10).  Now save your level. Select “Save level” from the “File” menu and give you level a good name- like “FirstRoom” or something.

11) Now to check out your room! Either press Ctrl+P or select “Play level” from the “File” menu. Make sure your Unreal CD is in the drive. Have fun!

Skarz (www.skarz.com)

skarz@skarz.com


History

----------------------------------------------

v0.5

Added a new tutorial of my own for the first time room builder (Hello Room).

Fixed a couple more format problems

Fixed some old info that a few users emailed me about (thanx again peoplez!)

Fixed some info in the "Links" area

Things to add for next version:

More of what Tim Sweeny gave me.

Graphics for the brush types

More tutorials (email me with some!)

Optimize the graphics for size

More Stuff...

----------------------------------------------

v0.4

Added the new stuff that was on the unreal tech site (some great new info).

Fixed a couple more format problems

Fixed some old info that a few users emailed me about (thanx peoplez!)

Added the Green Marine's OOB tutorial.

Things to add for next version:

More of what Tim Sweeny gave me.

Graphics for the brush types

More tutorials (email me with some!)

Optimize the graphics for size

Stuff...

----------------------------------------------

v0.3

Tim Sweeny hooked me up with a ton of info! Thanks Man! I know have some great new

topics that talk about things like, Level Optimization, Avoid/Fix corrupt

levels, Macros, About Brushes, Using Grids, etc...

Misc. Enhancments

Things to add for next version:

More of what Tim Sweeny gave me.

Graphics for the brush types

More tutorials (By GMarine, etc.)

Optimize the graphics for size

Stuff...

----------------------------------------------

v0.21

Fixed a couple of typos and display problems

----------------------------------------------

v0.2

Added a lot of tutorials from http://www.unrealism.com/design/

Added a graphic which made the help file MUCH larger (UI Screenshot)

Getting rave reviews on EFnet's #unrealed channel (Thanks Pplz!)

Changed the content system around a little to help organize things

Added a version number to help make sure you got the latest build

Misc little improvments...

----------------------------------------------

v0.1

Everything was new!


Hot Keys

•	Delete: Delete selected actors.

•	1, 2, 3: Slow, medium, and fast movement speed.

•	F1: Help.

•	F4: Actor properties.

•	F5: Surface properties.

•	F6: Level properties.

•	F7: Compile changed scripts.

•	F8: Rebuilder.

•	B: Toggle brush visibility in the current viewport.

•	H: Toggle actor visibility in the current viewport.

•	P: Toggle player controls or realtime update of the viewport.

•	Shift-A: Select all actors.

•	Shift-B: Select all surfaces belonging to the selected surfaces' brushes.

•	Shift-C: Select adjacent coplanar polygons.

•	Shift-D: Duplicate selected actors.

•	Shift-F: Select adjacent floors.

•	Shift-G: Select surfaces belonging to the selected surfaces' groups.

•	Shift-I: Select surfaces with items matching the selected surfaces' items.

•	Shift-J: Select all adjacent surfaces(flood-fill).

•	Shift-L: Look ahead in the current viewport (no pitch or roll).

•	Shift-M: Memorize selected surfaces.

•	Shift-N: Select none.

•	Shift-O: Select surfaces from intersection of selected surfaces and memory.

•	Shift-P: Select all surfaces.

•	Shift-Q: Reverse the set of selected surfaces.

•	Shift-R: Recall memorized surface selection.

•	Shift-T: Select all surfaces which use the current texture.

•	Shift-U: Select union of selected surfaces and memorized surfaces.

•	Shift-W: Select adjacent wall surfaces (flood-fill).

•	Shift-X: Select exclusive or of selected surfaces and memorized surfaces.

•	Shift-Y: Select adjacent slanted surfaces.

•	Shift-Z: Select none.

•	Ctrl-A: Add brush to world.

•	Ctrl-B: Load brush.

•	Ctrl-C: Copy.

•	Ctrl-D: Deintersect brush with world.

•	Ctrl-E: Save as.

•	Ctrl-L: Save level.

•	Ctrl-O: Load level.

•	Ctrl-P: Play level.

•	Ctrl-N: Intersect brush with world.

•	Ctrl-R: Redo.

•	Ctrl-S: Subtract brush from world.

•	Ctrl-V: Paste.

•	Ctrl-W: Duplicate.

•	Ctrl-X: Cut.

•	Ctrl-Z: Undo.


Importing Objects

Importing 3D Models into UnrealED - by Jon Renner

For Starters, you'll need a 3D Modeler. If you don't have one, you can get a free beta (expires after a certain amount of time) at www.rhino3d.com. Save your model as an AutoCad DXF file format (.DXF) and open UnrealED. Now go under the Brush menu at the top and click on import. Find your DXF file and import it. UnrealED is Very picky about the models it will import, and the lower the polygon count the better (nothing above 500). I've had some problems with certain models where I would add/subtract with the brush and my level would become "screwed up". Parts of it would start disappearing. This is a technique that was used by Epic for a lot of the more complicated geometry.

Note: Exporting LightWave objects as DXF doesn't work to well. If you are interested in helping with a .lwo to Unreal converter, email me (Skarz) at help@skarz.com. Serious inquiries only!


Installing This Manual

To install this manual, just put the unzipped files into your Unreal/System directory. This should be the directory that has the unrealed.exe file. That's it! Now when you press "F1" in UnrealED, this manual will pop up. Enjoy!


Levels with Speed

Building Unreal Levels with Speed in Mind - by Jon Renner

Yeah, we know it's hard to build cool looking stuff with UnrealEd, this certainly isn't BSP, WorldCraft, or QERadiant (Yet.). But you've got something else to worry about too. If your level is too complicated, it will run too slow for people. Adding Combat slows down the rendering process quite a bit, as it has to deal with the monster models and the special effects created by weapons. If you type "STAT FPS" at the console or by using the TAB command, you will see a number displaying the current polygon count being rendered. Here is a guide to keep in mind taken from the readme file in the unreal\help dir:

•	200: No combat going on, little to no actors or monsters out there.

•	130 or less: Combat with one monster.

•	100: Combat with 2-3 monsters.

•	20-50: Combat with 4 monsters or less.

Here are some other tips taken from the notes at unreal.epicgames.com:

Suggestions for making maps run faster

Here are some fairly straightforward tricks that can be implemented in existing maps. These are worthwhile enough that I recommend going back and applying them to existing maps, in the worst-performance areas where you need a speed boost. The areas that are noticeably slow are the large outdoor areas where you see buildings from the outside, and areas which use a lot of dynamic light.

•	When you have a huge outdoor area, have as few far-away meshes in view as possible. Type "STAT MESH" and look at the "MESHCOUNT=xxx" number to see how many meshes are in view. About 50% of the CPU time required to draw a mesh is irrespective of its size, so if you have a gun lying on the ground a mile away, but it's visible, even though it might only take up 1 pixel on the screen, it takes several milliseconds for the engine to perform lighting, transformation, and teeny polygon rendering on it. For example, in walking along the ridge in Bluff, the MESHCOUNT is 6, though I was only aware of one mesh (the Nali). It turns out that there's a transparent window, and two meshes visible through the transparent window, and three meshes somewhere else (not sure where).

•	In the huge levels that combine indoors and outdoors, like Bluff, where you want to have transparent windows that players can see out of, use this one-way transparency trick: Add a semisolid cube brush for the window; make the inside face transparent and one-sided; and make the outside face non-transparent and one-sided. This way, players inside can see out, but players outside can't see in. This noticeably speeds up maps when the player is on the outside, looking in.

•	If you have a lot of dynamic lights in an area, and you don't mind extremely fuzzy (low detail) shadows, use the "super low shadow detail trick": If you select both "low shadow detail" and "high shadow detail" on a surface together, the engine uses a special "super low shadow detail" mode which is 4X faster for dynamic lighting. Since this makes the shadows extremely fuzzy (which looks weird sometimes), this isn't a good trick to use all over the place -- it's just for the areas where you want to have a LOT of dynamic light, or dynamic light in huge outdoors areas.


Links

The following places are good to visit on a regular basis. They will keep you up to date on UnrealED and other related topics:

Technical Information:

http://unreal.epicgames.com/	-	The official place to go for Unreal Information and Patches.

http://www.skarz.com	-	My site. This is where you can get the latest help file as well as some general newz.

http://www.unrealed.com	-	Great site for Unreal technical info.

http://www.unrealism.com/design/	-	Got a lot of the tutorials from this site...

Unreal News:

http://www.bluesnews.com/	-	The one and only Blue will keep you up to speed with Info!

http://www.voodooextreme.com/	-	Great place for game info. Lots of 3Dfx related things.

http://www.skarz.com	-	My site covers only the big news of the day and covers anything technology based.

http://www.unrealnation.com/	-	Yet another top notch site.

IRC

:

#unrealed	-	Server:

EFnet unreal channels are dead due to lamers. To bad really...


Macros

UnrealEd’s macro-recording menu lets you record often-used operations, save them, and play them back later.

This feature is limited in that only certain kinds of operations can be recorded:

Only menu commands and operations that affect the world which are done through UnrealEd’s various properties windows can be recorded.  For example, scaling the brush via the “Resize/move brush” window can be recorded.  Importing and loading textures can be recorded.  Changing the grid settings can be imported.  Adding/subtracting brushes can be recorded.

Operations that you do with the mouse or keyboard within a camera window are generally not recorded.  Moving the brush with the mouse can’t be recorded, and neither can adding actors by clicking on surfaces.  This is because there’s no general-purpose way to record those things – they are particular to the task that you’re doing.

That said, the best way to determine whether a macro can be recorded for a particular operation is to try it and see if it works.


Map Editing Mode

Map Editing Mode

When you’re in map editing mode, you can reposition brushes that you had previously added and subtracted to the world.  In this mode, you can only see wireframe views of the world and not the regular polygon geometry.

When in map editing mode, you can’t perform regular operations such as moving actors or adjusting textures.

To get out of map editing mode, you must rebuild the level’s geometry, which regenerates the polygon and texture geometry, enabling you to see the world in its full beauty.

Mouse movements

Right-clicking on a brush selects or deselects it.  Use this to select several brushes.

Left-clicking on a brush selects it and deselects everything else.

Moving the mouse around scrolls the view.

Holding Ctrl and moving the mouse around moves the selected brushes.

Keyboard shortcuts

Shift-A selects all brushes.

Shift-N selects no brushes.

Shift-D duplicates selected brushes.

Del deletes selected brushes.

Map Toolbar

The Map Toolbar, which is always visible while you’re in map editing mode, gives you several advanced options to use.  Here are the non-obvious ones:

Copy to brush: Copies the selected brush on the map to the default (red) brush which you can easily manipulate and add/subtract.

Copy from brush: Copies the default (red) brush to all selected brushes in the world.  This is useful for replacing a bunch of brushes with a new brush.  All of the regular brush operations (the brush builders, add, and subtract) work in this mode.

Delete: Deletes the selected brushes from the map.

Duplicate: Duplicates the selected brushes.

To First: Moves the selected brushes to the front of the add/subtract order.  This causes them to be added/subtracted first when the map is rebuilt.  This is useful because the results of CSG operations depend on the order in which they’re performed.  Adding a wall then subtracting a window produces a wall with a window, whereas subtracting a window then adding a wall produces just a wall.

To Last: Moves the selected brushes to the end of the add/subtract order.  This causes them to be added/subtracted last, after everything else when the map is rebuilt.

Select First/Last: Selects the first- or last-added brush in the map.

Select Adds/Subtracts: Selects all brushes that were either added or subtracted.

Select Semi-Solids: Selects all semi-solid brushes in the map.

Select Non-Solids: Selects all non-solid brushes in the map.

Select Previous/Mext:  These are useful for seeing the order in which brushes were added/subtracted.

Wireframe Color: Lets you change the color of all selected brushes, as they appear in wireframe views.  This affects the visual display in UnrealEd only, and doesn’t affect the actual level you’re creating.

Solidity: Enables you to reclassify the selected brushes as solid, semi-solid, or non-solid.  This only affects brushes that were added, not brushes that were subtracted.

Set Group Name: Enables you to change the group name of all the selected brushes.  This is useful as a convenience in selecting polygons for texture mapping.


Moving Brushes

by Jon Renner

A little bit of info before you read that should clear things up: Keyframes are basically 'images' of the moving brush that define the stopping points for moving brushes, so if I put keyframe-0 of a door that slides upward in the door's "closed" position and keyframe-1 in the doors "open" position. The moving brush will swing/slide/alter/rotate/move, depending on what kind of movement is required, from one keyframe to the next. Keyframes are what you would see if you kept your eyes closed while the brush was moving, but opened them when it wasn't. Take a look at this map for an example of a moving brush.

(the following is modified version of the Unreal readme.txt)

Creating Moving Brushes
-----------------------

A Moving Brush, or Mover, is a piece of the world geometry that moves in predefined keyframes of animation. A typical mover is a door, a drawbridge, or a collapsing plank.

The best way to create your movers:
1. Make a huge building box somewhere off to the side of your level.
2. Build your lift, door, or whatever in that building box.
3. INTERSECT what you built.
4. Move your new red builder brush into your level and place it where you'd want your mover.
5. Hit the sixth button down on the right side of the toolbar, that looks like a cube with gray arcs coming off of it.
6. This added in your mover. You need to set its mover keyframes now, right click on it and say KEYFRAME-> 1. Move your mover to keyframe 1, and right click on it again and go KEYFRAME-> 0 to reset it. (NOTE: Your mover will be a purple brush, it will appear beneath your red builder brush. Be sure to move your red builder brush out of the way.)
7. Your mover is in place. In the movers' properties, under OBJECT, you can specify what makes this mover move. It defaults to BUMP OPEN TIMED, which means the mover will open when bumped into by the player. There are other types in here, mess around with them!

The multiple mover activate types are:

* Stand Open Timed: The mover will activate and go from keyframe zero to one when the player stands on it. Set lifts to this activate type.

* Bump Button: Um, I don't use this much, don't bother with it.

* Bump Open Timed: When the player bumps this moving brush (touches it) it will remain open for the time specified in MOVER (stay open time.) NOTE: The MOVE TIME is the time it takes the mover to move from keyframe to keyframe.

You can also activate a mover by a trigger. A trigger is an invisible actor that you can add into the world to activate most anything, in this instance, a moving brush. Triggers are in your class browser under TRIGGERS-TRIGGER. Add one in. A trigger, under EVENTS of its properties, has two areas you need to know about: EVENT and TAG. The EVENT is the name of what that this trigger will cause when it is touched/shot/activated. This corresponds to the TAG of the action you want to occur. For instance, a trigger that has the EVENT of Fred will trigger the moving brush that has the TAG of Fred. You can use this system to daisy chain events, you can have the Fred mover's event be George, and have another mover that's tag is George. That mover will trigger when the first one is done (provided it is set to Trigger Open Timed which leads us to the next mover activate types.)

* Trigger Pound: When you are touching the trigger who’s EVENT matches this mover’s TAG, the trigger will pound between its keyframes. Useful for squishing timing puzzles, or machinery.

* Trigger Control: When the player is touching the trigger for this mover, the mover will start to open and remain open as long as the player is within the vicinity of the trigger. Once he leaves the trigger, the door will proceed to close. Useful for doors.

* Trigger Toggle: When the trigger is touched, it will open the mover it is tagged to. When the trigger is touched again, the mover will close. It toggles the state of the mover from open to closed.

* Trigger Open Timed: When the trigger is touched, the mover will open, stay open for said time, and close.

You can also have one moving brush (lovingly often referred to as a Mover) trigger another. Build a button whose Object-State is BUMP OPEN TIMED and match its event to a door mover's tag. Set the door mover's Object-State to TRIGGER OPEN TIMED, and the door will open when the button is touched. (provided you specified keyframes, etc)

A helpful property in the movers' properties is BTRIGGERONCEONLY, when this is set to true the mover will open and never close again. Useful for one time doors/puzzles/traps.


Object Oriented Logic

GreenMarine's Object Oriented Logic Tutorial

(with specific references to OO's place in UnrealScript)

"For the layprogrammer." - GreenMarine

"You can use the pepper grinder to create pepper by turning the crank...BUT, a pepper grinder is _not_ pepper, so you MUST NOT TRY TO EAT IT!" - Tim Sweeney, Epic MegaGames, Inc.

You can always find the latest version of this document at
http://www.planetquake.com/osp/tuts/GM-OOtutorial.html.

Drafted by: Brandon "GreenMarine" Reinhart
Contact: greenmarine@ittc.ukans.edu - http://www.planetquake.com/osp/
Version: 1.0

ToDo

•	Constructors

•	Destructors

•	State

•	Advanced Techniques

Introduction

Talking on #UnrealED and #UnrealScript (both active EF-Net channels on IRC) it has come to my attention that a lot of interested UnrealScript hackers aren't very familiar with Object Oriented (OO) logic. In an attempt to do my bit o' public good, I'm writing this tutorial as a short guide to thinking in OO.

Hopefully, by the time you are done reading this, you'll have a strong enough grasp of Object Oriented Programming (OOP) to work uninhibited with UnrealScript. From my experience, I have learned that just by approaching a mod idea or problem with OO design in mind, an answer is more easily found.

I hope this tutorial is useful to you. I will continue to update it for as long as I see necessary. If you have any information or corrections than I urge you to email the address above. I will be more than happy to include such items with credit to the author.

This is just the first in a series of useful tutorials (called tuts by the in-crowd hehe) that I plan on authoring. Keep your eyes peeled.

Legal

This tutorial may only be transferred by electronic means. It may not be altered in any way, shape, or form without the express, written permission of the author. It may not be included on any CD-ROM archive without the express, written permission of the author. It may not be used for any commercial purpose without the express, written permission of the author.

The contents of this document are Copyright (c) 1998, Brandon Reinhart.

The Way Programmers Think

Programmers are a strange breed. They often forget to eat. They often forget to sleep. They even tend to neglect their girlfriend/boyfriend (if they are lucky enough to possess one *hint hint*) all the while attempting to make rather unintelligent machines more intelligent than any reasonable person would deem worthwhile.

Programmers, you see, are not reasonable people.

This lack of reason is in part due to the aforementioned lack of food, sleep, and sex, and also partly due to the way programmers think. Programmers like to solve problems. Specifically, programmers like to solve problems by changing the way they think about the problem. Object Oriented Programming, which is the focus of this tutorial, is one such way of solving problems. To understand the OO method of solving a problem, we first have to change the way we think about the problem.

Breaking It Up

Let's say you, as a programmer, have a problem. You want to write a program that will build a car. Sounds tough doesn't it? Well it is, building a car is certainly no trivial task, but half of the difficulty in thinking of a solution is in the way we think of the problem.

If you say "I want to write a program that will build a car," you are probably mentally overwhelmed by the immensity of the task! A car is made up of thousands of parts! How can you possibly write a program that will make all those parts? Thousands of parts? Ah ha! We've already started to break it up. What if, instead of saying "I want to write a program that will build a car," you said "I want to write a program that will build a series of car parts and then assemble those parts." Still a daunting task, but certainly more organized.

This is what we call "breaking it up" or "top-down programming."

By breaking the core problem up into successively smaller pieces, you are faced with many small, easy tasks instead of one large, difficult task.

If we were to leave the car analogy and move to an Unreal analogy, one might say "I want to write a bot that plays Unreal." A tough problem. However, if you break a bot down into successively smaller pieces, you end up with a path-finding project, a weapon-using project, and so on.

This is the first step in taking an OO approach to programming.

Getting Organized

Now that we've got a bunch of little tasks that make up our big task, we've got to get organized. If you were to write your car program in the classical C "functional" style, you'd have a lot of functions and a big mess. You could clean it up by assigning certain parts of the car to their own files, but that would still be pretty wild. How to we organize the small parts of the big task?

The solution is to change the way we think of the parts of the problem. Let's look at the car analogy. We want to build a car and we are going to do it by having one part of our program build car parts and another part of our program assemble those parts into a working car, right? Well what, exactly, is a car part?

Its maybe a mix of metal, plastic, smaller parts, and it has a specific function...different car parts of the same type might be slightly different. Basically, we could say that a car part is a generic type of object. It isn't any specific object in particular, just a blueprint by which we could manufacture the actual thing. Let's call this a "class."

The Class

In OO logic, a "class" is a description of what a thing might be if it were created. A class is a generic template. It defines abstract properties (the car part has color) but usually does not define the specific nature of those properties (the car part is red). A class also defines the behavior of an object. A series of special functions that the class owns define the exact way in which an object you create works in your program.

In programmer speak, the abstract properties are called "instance variables" and the behavior functions are called "methods." The process of taking a class and making an object from it is call "instantiation." It is _very_ important to realize that a class is not an object, merely a blueprint by which an object may be made. When you instantiate an object from a class, you are creating a model from that blueprint.

Class Mechanics

In UnrealScript, we define a class through the "class declaration:"

  class MyClass expands MyParentClass;

The class specifier tells UnrealScript that you are starting to define a new class. MyClass is the name of this class (it can be whatever you want, preferably something meaningful, like CarPart). We'll get to the rest in a bit.

After you've made your class declaration in UnrealScript you are ready to define the class's instance variables. This is done by listing a series of property variables:

  var int color;          // Part color index number

  var byte manufacturer;  // Manufacturer reference value

You can find out the specific data types that UnrealScript supports after you've read this tutorial by reading Tim Sweeney's UnrealScript Language Reference at http://unreal.epicgames.com/UnrealScript.htm. It might be smart to separate your instance variables from the rest of the code with a comment line like this:

  ///////////////////////////////////////////////////

  // Instance Variables for MyClass

This is just a matter of taste, but it won't hurt. Its usually a _good thing_ to make your code more readable, especially if you want to share it with others or come back to it later.

Defining methods for your new class are simular to defining instance variables, just make a list of functions:

  function doAThing()

  {

    // Do some stuff in UnrealScript

  }

  function doAnotherThing()

  {

    // Another function that does something

  }

Once again, you might separate the method area of your class from the rest of the code by using a comment line. It is also highly suggested that you name your methods after their functions. For example, a function that cleans your socks might be called cleanSocks().

In UnrealScript, we call object instantiation "spawning." As such, you use the Spawn() function to create a new object from a class template:

  var actor MyObject;            // variable to hold the object

  MyObject = Spawn(MyClass);     // spawning the object

A Brief Discussion of Methods

Objects are independent collections of "interactive" data that sit in memory. The keyword is _independent_. Each object does its own thing. If you have a class called MyBot and you spawn two objects from that class called BotA and BotB those two instantiations don't know about each other. This leads us to the next concept of Object Oriented Programming: objects edit themselves.

When an object is spawned it is usually stuffed into a hash table in memory, given a lookup key, and forgotten about. The system uses the lookup key to find the specific object in the hash table if you want to do something to it, but for all intents and purposes the object is just sort of unavailable. Unavailable in the since that, unlike a normal variable, you can't just change it. You cannot, for example, rip open an object and change the contents of the instance variables. (This is one of the ways in which objects are different from structs in C++.) Instead, you have to tell the object to change itself. This is done through the methods.

The methods of a class define the way an object will act when it is spawned. If you want to change an instance variable of an object, you have to have written a method in the class that allows this to behavior to take place. Our CarPart class might have a method that looks like this:

   function setColor(int newColor)

   {

     color = newColor;

   }

In this case, when the above method is called, the object takes the int supplied as an argument and sets the color instance variable to that value. The object alters itself. The syntax for calling an object's method in UnrealScript looks like this:

  MyObject.setColor(15);  // tell the object to call it's setColor() method

Methods, Variables, and Object Security

Remember when I told you that an object alters itself? Well that isn't entirely true. I wanted you to believe that so you would start thinking about objects as independent entities in your programming environment. It is possible, in fact, to change the instance variables of an object directly:

  MyObject.color = 15;

Notice the difference. In the method case, we tell the object to change itself and in the assignment case we change the nature of the object directly. This presents another one of those "How Programmers Think" issues. You're probably asking yourself if I can just alter an object directly, why would I ever use a method to do it? Well, think about it.

What if there were very special restrictions on the instance variable "color"? For example, you might want the color variable to only contain values from 1 to 10. Anything outside of that range would maybe cause your program to act unpredictably. In that case, it just wouldn't be a good idea to allow the object's user to edit the color variable directly. Right? Even though _you_ might know that 1 to 10 are the only correct values for color, someone else who uses your code might not. The solution is to make the instance variable private, so that only the class itself can change it:

  var private int color;  // declare a private variable

The private specifier indicates that this instance variable is _only_ accessable by an object of this class. The object can change the color variable from inside its own methods, but an external assignment, like:

  MyObject.color = 15;

Would become an error no matter what the right hand value. This allows you to control the input to your objects and more clearly define their behavior. Now you could have your object return an error code or take appropriate action if an invalid value was passed to it through a method.

Class Families

Whew. Getting tired yet? This might be a good time to grab a Dr. Pepper. We are just now getting the fundamental elements of objects!

As you can see from the above (if you are a creative individual and you must be if you are reading this), objects alone have a lot of potential. Objects make it easy to break down a problem into usuable parts. Nonetheless, it can still be difficult if you have to manage lots of objects. This brings us to the fundamentals of object oriented programming: The relationships between objects.

A good way to picture object relationships is through our car analogy. The CarPart class certainly doesn't go very far in describing what a CarPart is. Given what we know about objects so far, we'd probably not even use CarPart...we'd have to write classes like SteeringWheel that are more specific and useful.

Actually, this isn't quite the case. In our minds, CarPart has already created a relationship to SteeringWheel. A steering wheel is a kind of car part. Right? So what if the CarPart class defined very generic methods and instance variables that all car parts used and another class called SteeringWheel _expanded_ that functionality?

In programmer speak we call this "the parent-child relationship." CarPart is the "parent class" (or super class) of SteeringWheel. In UnrealScript, we define a child class like this:

  class SteeringWheel expands CarPart package(MyPackage);

See the expands specifier? It indicates that the class we are now declaring (SteeringWheel) is a child class of CarPart. As soon as Unreal sees this it forms a special relationship between the two classes.

Fundamental I: Inheritance

What, exactly, does this parent-child relationship do for us, as problem solvers? It simplifies the solution, that's what! By creating a parent-child relationship between two classes, the child class immediately "inherits" the properties and methods of the parent class. Without you even having to type a line of code, SteeringWheel contains all of the functionality of CarPart. If CarPart has a setColor() method defined (as discussed above) SteeringWheel has the same method. Inheritance applies to instance variables, methods, and states.

This allows us to create what programmers call an "Object Hierarchy" (or class family). Its a lot like a family tree:

                   Object

                      | expanded by

                    Actor

                      | expanded by

                   CarPart

                      | expanded by

                SteeringWheel

Object and Actor are special classes in Unreal described in Tim Sweeney's guide. The full class family tree for Unreal is a sprawling web of relationships as you can no doubt imagine. In our example, we have a basic "is-a" relationship:

        A SteeringWheel is a CarPart.

        A CarPart is an Actor.

        An Actor is an Object.

Each successive layer of the family tree inherits and expands upon the functionality and detail of the previous layer. This allows us to easily describe a complex object in terms of its component objects. It is important to realize that the relationship is not commutative. A SteeringWheel is always a CarPart, but a CarPart isn't always a SteeringWheel. Moving up the tree you get more general and moving down the tree you get more specialized. Get it? Good!

But wait a second...if we are building the car and a car is made up of parts, where is the Car class? This brings us to an important distinction in relationships: is-a vs. has-a. Clearly, a CarPart is not a kind of Car. Therefore, the relationship "CarPart expands Car" would be invalid. Rather, you would have a tree structure that might look like this:

                            Object

                              |

                            Actor

                           /     \

                         Car   CarPart

                                 |

                             SteeringWheel

Car is a class derived from Actor, but it doesn't have a direct relationship to CarPart (you might say they are siblings). Instead, the internal definition of the Car class might include instance variables that are CarParts. In this case, we have a has-a relationship. A Car has a SteeringWheel, but a SteeringWheel is not a Car. If you are ever designing a class hierarchy like this and you get confused about object relationship, it is sometimes very useful to phrase in the relationship in the "is-a" or "has-a" style.

As you can see, the relationship hierarchy allows us to do some very interesting things. If we wanted to, for example, make a more liberal definition of Car, we could add Vehicle:

                            Object

                              |

                             Actor

                            /     \

                         Part    Vehicle

                       /    |     |     \

                 CarPart AirPart  Car  Airplane

Pretty cool huh? Not only is it a great way to organize and visualize data, but the benefits of inheritance mean we save time that would normally be spent copying and rewriting code!

Fundamental II: Polymorphism

Poly what? Its more of that crazy programmer speak. (If you've understood everything up until now, you are more a programmer than you think.) Polymorphism is another one of the fundamentals of object oriented programming. In inheritance, the child class gains the instance variables, methods, and states of the parent class... but what if we want to change those inherited elements? In our car example, we might have a Pedal class that defines a method called pushPedal(). When pushPedal() is called, the method preforms a default behavior (maybe it activates the breaks.) If we expand the Pedal class with a new class called AcceleratorPedal, the pushPedal() method suddenly becomes incorrect. An accelerator certainly shouldn't turn on the breaks! (Or you're gonna have a lot of lawsuits when you release your program, believe you me).

In this situation, we have to replace the behavior we inherited from Pedal with something new. This is done through a process called "Polymorphism" or "Function Overloading." You'll run into this all the time when you write UnrealScript. To borrow an explanation from Tim Sweeney:

"[Function overloading] refers to writing a new version of a function in a subclass. For example, say you're writing a script for a new kind of monster called a Demon. The Demon class, which you just created, expands the Pawn class. Now, when a pawn sees a player for the first time, the pawn's [SeePlayer()] function is called, so that the pawn can start attacking the player. This is a nice concept, but say you wanted to handle [SeePlayer()] differently in your new Demon class."

To do this, just redefine the function in the child class. When the class is instantiated, the object will have the new behavior, and not the parent behavior. If you don't want anyone to redefine a function you have added to a class, add the "final" specifier to the function's declaration:

  function final SeePlayer()

This prevents the script from overloading the function in derived classes and can be very useful in maintaining a consistant behavior in code you write. Tim Sweeney notes that it also results in a speed increase inside Unreal.

Bringing It All Together

So now you know the fundamentals of Object Oriented design and have a good idea of how objects relate to one another. What do you do next?

The best advice is to get hacking. Dive into the code and don't come up for air even if the promise of food, sleep, or sex looms near. Seek the zone. Or...you can always read Tim Sweeney's guide to UnrealScript. It goes into much greater detail about the syntax surrounding OO in Unreal. In addition, I suggest you find other resources on the net discussing OO. As I develop this paper, I'll try to come up with some good link, which I will list below. There are a lot of subtle elements of OO that can only be learned. Some aren't really supported by Unreal, some are. Some are merely ways of thinking.

And that brings me to my closing point. OO is as much a way of thinking as it is a way of programming. As you walk to school or drive to work, try imagining the relationship between things you see (a tree has leaves, a rose is a flower). This will greatly enhance your understanding of OO. Create complex relationships in your mind and then find ways of representing them in code.

To those who really understand it and really enjoy it, programming is a mental, physical, and spiritual task. It might sound wierd, but programming touches the fundamental ways in which we think and solve problems. If you can think in OO, then your mind is unrestricted when it comes to solving problems in OO. The more you use it, the more you will come to realize it is true.

OO can't solve everything, however. Just like any other way of thinking, the Object Oriented paradigm ignores certain elements of problem solving in order to strengthen its analogy to natural systems. Most likely, however, you will not be faced with these issues when you write UnrealScript, unless you are authoring one helluva transcending mod.

- Brandon "GreenMarine" Reinhart, May, 1998

Notes

•	•	SkinDoggy notes that a class MUST extend some parent class in UnrealScript.

Useful Resources

•	•	UnrealScript Language Reference

•	•	The OO FAQ

About the Author

Brandon Reinhart, known as GreenMarine in the Quake/Quake2/Unreal scene is a dedicated mod hacker obsessed with game and graphics programming. Brandon has authored the King of the Hill modification for Quake2 and currently has multiple Unreal projects planned, in addition to a technology demonstration. Brandon is currently looking for employment in the games industry.

Special Thanks

•	Epic MegaGames

•	Tim Sweeney

•	Dr. Pepper

•	Mr. Pibb

•	Cabaret Voltaire

•	Front Line Assembly

•	Nick Cave

•	SkinDoggy from #UnrealED for Corrections

History

May 27, 1998 - Made corrective changes.
May 27, 1998 - Version 1.0 in PlainText and HTML
May 27, 1998 - First Revision
May 27, 1998 - First Draft

Copyright (c) 1998, Brandon Reinhart


Overview of Using Cameras

Overview of modes

UnrealEd has several different editing modes, which affect the types of operations you can perform.  All of the modes are available from Unreal’s toolchest, the window that’s usually on the left hand side of the screen.  The modes can be grouped as follows:

Brush movement modes: Holding down Ctrl while moving the mouse causes the brush (the big red wireframe object) to be moved, rotated, streteched, or manipulated in some way.  While in these modes, you can manipulate the brush and select polygons/textures.

Texture adjusting modes: Holding down Ctrl while moving the mouse adjusts textures on selected polygons to be affected.  In these modes, you can select/deselect polygons and adjust their textures.

Actor modes: In these modes, you can select, deselect, add, delete, and otherwise adjust the actors on a particular level.

Terraforming mode: You’ll use this mode to edit the terrain in a level.


Packages

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

Audience: Level Designers, UnrealScript Programmers, C++ Programmers.

About this document

This document has been written with our licensees in mind (Microprose, Ion Storm, Legend, and others). However, much of the info is useful to the Unreal community, so I am releasing it here unedited. The sections that refer to C++ code are not relevent to the community because we aren't releasing the C++ source. But, there is still a lot of useful information here.

Overview

An Unreal "package" is a collection of related objects such as textures, sound effects, and scripts which are grouped together for convenient distribution and use.

For example, in Unreal, textures are stored in texture package files, which use the ".utx" extension. A .utx file contains many (tens or hundreds) of textures which are part of a similar theme, such as the "SkyCity.utx" texture package.

Unreal's file format is based on packages because packages enable the game engine and content to be developed modularly. Artists maintain their textures in .utx files; the programmers working on the engine and game maintain separate packages of UnrealScript classes; people in the Unreal community can create and distribute their own packages online; and so on.

One package may refer to objects which are contained in another package. For example, an .unr level package may refer to textures which reside in various external .utx files; sounds in other .uax files; and music in a .umx file. We say that the level file is "dependent" on the other packages. To load that .unr level file successfully, you need to have all of the other .utx, .uax, and .umx files which that level refers to. If one of those packages is missing, you will not be able to load the .unr file.

Package files

All Unreal package files are stored in the same binary file format, but they use different extensions to identify their type:

•	.utx files are packages of textures.

•	.uax files are packages of audio (sound effects).

•	.umx files are packages of music.

•	.unr files contain one game level.

•	.u files are packages containing UnrealScript classes and objects (like textures, sounds, and meshes) they contain.

When the Unreal engine needs to load a package, it looks in the subdirectories listed in the [Core.System] section, in the Path#= list. The relevent lines of the clean (unmodified) Unreal.ini file look like this:

[Core.System]

CachePath=..\Cache

CacheExt=.uxx

Paths[0]=..\System\*.u

Paths[1]=..\Maps\*.unr

Paths[2]=..\Textures\*.utx

Paths[3]=..\Sounds\*.uax

Paths[4]=..\Music\*.umx

When you try to load a package by its raw name (such as "SkyCity"), the engine first searches in the CachePath for a matching package downloaded from the Internet; then it searches in each of the numbered directories in order (0, 1, 2...) for matching files. For example, it looks for \Unreal\Cache\[some funky name].uxx, then \Unreal\System\SkyCity.u, then \Unreal\Maps\SkyCity.unr, then \Unreal\Textures\SkyCity.utx -- and the file \Unreal\Textures\SkyCity.utx does exist, so it uses that file.

Because of this storage and search scheme, you must not create two packages with the same base name, which only differ by extension. For example, you must not create a texture file named SkyCity.utx and a music file named SkyCity.umx. If you do that, the engine will always fail to load one of the packages and give an error.

Internet package file downloading and caching

Whenever you save a package file to disk, the file is internally stamped with a GUID ("Globally Unique Identifier"), which is a 128-bit number which is guaranteed to be unique. In single-player play, this GUID is never used and is irrelevent. However, when you connect to an Internet-based server, the server sends a list of packages that are required for gameplay there (for example, the level it uses, any texture packages it uses, any sound packages, etc). These packages are identified by name and GUID. If you don't have one of the packages required by the server, the package file is automatically downloaded to your \Unreal\Cache directory, and given a filename based on its GUID.

A typical \Unreal\Cache directory looks something like this:

Directory of F:\Unreal\Cache

06/02/98 03:37a <DIR> .

06/02/98 03:37a <DIR> ..

06/02/98 03:37a 8,932 2306087A11D1E2FD4F00DBA5CAA00349.uxx

06/02/98 03:38a 8,932 2401042A11D1E2FD4F00DBA5CAA00381.uxx

3 File(s) 8,932 bytes

698,601,472 bytes free

Packages stored in the \Unreal\Cache directory are identified by their GUID rather than the package name given to them by their creator, to avoid conflicting names. For example, there are bound to be a ton of levels on the net called Test.unr, a ton of textures named Walls.utx, etc. The GUID scheme avoids conflicts.

In UnrealEd, each time a package file is saved, it is assigned a new GUID. This way, each version of a package is guaranteed to be tracked and cached separate from other versions. This is good, because it prevents people from trying to play on a server using different versions of a level. This is bad, because if you simply load a texture file, resave it, and copy it to your UnrealServer, all of the players who come to your server will have to re-download the package. Therefore, we recommend modifying your package files only when necessary, and releasing them only after enough testing and use that you know they're not going to change and force redownloading a day later -- especially with large package files.

Why Unreal is based on packages

•	Packages enable an open plug-in architecture for easy community and licensee extensibility.

•	Packages make the Unreal engine expandable in content, UnrealScript code, and C++ code.

•	Packages help to improve the modularity of the code and reduce interdependencies.

•	Packages make it much easier for licensees to separarate the Unreal engine from the Unreal game.

•	Packages simplify Web-style downloading of content in Internet play.

Standard class packages that ship with Unreal

Core	The high-level framework Unreal is built on, similar to the MFC core or the Java Virtual Machine. The Core package contains the definitions of object, class, subsystem, script, property, name, and the object manager. The core is indepenent of any notion of a game or 3d engine.

Engine	The Unreal 3d engine, including support for vector math, actors, physics, collision, interaction, cameras, and networking.

Editor	The UnrealEd 3d editing environment with geometry editing, realtime lighting, and actor editing support.

Render	The Unreal rendering engine implementation.

Window	The platform-specific code supporting Unreal.

Galaxy	The implementation of Unreal's sound system (UAudioSubsystem) running on top of the Galaxy sound system for Windows. It is possible (for example, when porting Unreal to another platform) to completely replace the Galaxy package with an implementation of another sound system.

GlideDrv	Unreal 3d hardware support code for 3dfx's Glide library.

UnrealI	The Unreal I game implementation.

WinDrv	Windows viewport and client driver.

SoftDrv	Software rendering driver.

Fire	Fractal fire and water effects.

IpDrv	TCP/IP networking driver.

Licensees: Unreal package usage

Licensees may use all our .u packages except UnrealI verbatim or you may modify them to fit your needs. Bear in mind that it is attractive to use them in an unmodified form, as that makes merging with future code updates much easier and makes it easy to isolate problems in each others' code.

Licensees may use the UnrealI package as a reference and for internal development use, but the content in UnrealI is specific to our particular game, and it mustn't be used in your final product.

Licensees should create one more more new packages, for example "WheelOfTime" for their game-specific content. Keep in mind that your package and UnrealI can exist side-by-side during your development cycle until you've fully migrated away from the UnrealI specific content.

Licensee programmers: Sample directory layout for the "Engine" package

Here is an example of the directory structure for all the files that are related to the "Engine" package. The other packages follow a similar structure.

Distributable files:

\Unreal\System\Engine.dll	The package's C++ DLL file.

\Unreal\System\Engine.u	The package's UnrealScript class file.

Developer files:

\Unreal\Engine\Inc\Engine.h	Main public header file for the engine package.

\Unreal\Engine\Inc\*.*	Various public header files for the engine package, included by Engine.h.

\Unreal\Engine\Src\EnginePrivate.h	Private implementation header file.

\Unreal\Engine\Src\EngineClasses.h	Scripted classes exported to C++.

\Unreal\Engine\Src\Engine.cpp	Generates the package's precompiled header file.

\Unreal\Engine\Src\*.*	Various C++ files comprising the engine's code.

\Unreal\Engine\Lib\Engine.lib	The export library for linking with the engine.

\Unreal\Engine\Classes\*.uc	The UnrealScript classes used in building Engine.u.

\Unreal\Engine\Textures\*.*	Graphics files used in building Engine.u.

\Unreal\Engine\Models\*.*	Model files used in building Engine.u.

\Unreal\Engine\Sounds\*.*	Sound files used in building Engine.u.

Licensee programmers: Associating packages and DLL's

When you declare an UnrealScript class as "intrinsic", the engine looks in the .DLL file corresponding to the class's package for the class's corresponding C++ code. For example, here is the declaration of the "PlayerPawn" class in the "Engine" package:

//=============================================

// PlayerPawn.

//=============================================

class PlayerPawn expands Pawn

intrinsic;

(You can find the above code in the file \Unreal\Engine\Classes\PlayerPawn.uc.)

When you declare a class as "intrinsic" in UnrealScript, you are telling the engine that you have created some corresponding C++ code for the class. In this way, you can mix and match UnrealScript and C++ code when you write your game code.

When you declare "intrinsic" classes, Unreal looks for the .DLL file in the \Unreal\System directory whose name matches your package's name. For example, to find the C++ implementation of the PlayerPawn class, Unreal looks in the "\Unreal\System\Engine.dll" file.

In C++, you must use the IMPLEMENT_INTRINSIC macro (defined in UnObjBas.h) to tell the engine that you have implemented a new class in C++. Internally, this macro generates some __declspec(DLL_EXPORT) declarations that Unreal looks for in your DLL. For example, the PlayerPawn class is exposed in the source file "\Unreal\Engine\UnPawn.cpp" as follows:

IMPLEMENT_CLASS(APlayerPawn);

In addition, once per package you need to use Unreal's package declaration macro to expose the package:

IMPLEMENT_Package(Engine);

So, to summarize:

•	Each Unreal package corresponds to a .u file, for example, "\Unreal\System\MyPackage.u".

•	If one or more classes in the package are "intrinsic" classes, then Unreal expects to find a C++ .DLL file corresponding to the package, for example, "\Unreal\System\MyPackage.dll".

•	Unreal dynamically loads and unloads packages and their optional, corresponding .DLL files, on the fly -- they are loaded and unloaded based on whether they are needed in the current game level.

Licensee programmers: Running the game and editor without the UnrealI.u package

You can start working with the "baseline" version of the Unreal engine (that is, the engine with all game-specific content removed), with:

unreal.exe level.unr?class=engine.playerpawn?class=engine.gameinfo

While you're playing with the baseline configuration, you won't be able to see the player model and you won't be able to use any weapons because, of course, all of those things are game-specific and stored in the UnrealI package. But, the point is, you can edit and play levels with only the baseline engine, without any of our game-specific content.

See below for a description of what the Unreal.ini [EditPackages], [DefaultGame], and [DefaultPlayer] settings mean.

Licensee programmers: Replacing UnrealI.u with your own game-specific package

The first question is, "How do I create my own game package like your UnrealI.u?"

The easiest way to create a new package is by creating your first new class within UnrealEd. When creating a new game using the Unreal technology, you will need to create a custom "GameInfo" class to define high-level gameplay rules. Here's how:

Run UnrealEd

Bring up the "Classes" browser on the right-hand side of the screen.

Expand the "Info" class.

Right-click the "GameInfo" class.

Pick the "Create new class below GameInfo..." menu option.

Give the new class a name, for example "KlingonsGameInfo" and a package, for example "Klingons".

Press F7 (or use the Script/Compile menu option) to recompile the new script.

Save your package's .u binary file by hitting the "Save" button in the class browser and selecting your package.

At the bottom of the class browser, hit the "Export" button to export all classes which you have modified. This generates *.uc files in a directory corresponding to your package. For example, if you just created a class named "KlingonsGameInfo" in a package called "Klingons", UnrealEd will generate the file "\Unreal\Klingons\KlingonGameInfo.uc". The .uc files are pure text versions of your scripts, which can later be cleanly rebuilt.

The next question is, "How do I have my new package used in the editor and during gameplay?" The Unreal.ini file defines many of these project-specific settings you will want to modify for your title:

•	The [EditPackages] section lists the class packages (.u files) to load for editing when UnrealEd is run. You will generally want to remove UnrealI from the list, and add your package(s) to the list, so that your level designers can see all of your content from within UnrealEd.

•	The [DefaultGame] section says which GameInfo-derived class is responsible for moderating gameplay. The GameInfo class (see \Unreal\Engine\GameInfo.uc) makes many high-level gameplay decisions in single-player and network play, i.e. it implements the game rules. For the baseline game, use Engine.GameInfo. To customize the game rules, you must create a subclass of GameInfo.

•	The [DefaultPlayer] section says which PlayerPawn-derived class should be spawned to represent the player in the game. For the baseline game, use Engine.PlayerPawn. To customize the player controls, mesh, etc., create a subclass of PlayerPawn.

Licensee programmers: Working with classes and packages in UnrealEd

The most important thing you need to realize while working with classes is that each class may be stored redundently in two separate places:

•	A binary copy of the class is stored in its package's .u file in the \Unreal\System directory. This binary copy of the class includes all objects referenced by the class. For example, the Skaarj class in the UnrealI package is stored in the file \Unreal\System\UnrealI.u. This binary version includes the Skaarj's mesh and all of the monster's sound effects. The binary copy of the class must be saved by using the "Save" button in the class browser. However, the binary file will break whenever the .u file format changes, which will happen several times prior to the release of Unreal.

•	For licensee programmers who have the entire Unreal C++ and UnrealScript codebase in standalone form, a text copy of the class is stored in one .uc file. For example, the text version of the Skaarj class is stored in \Unreal\UnrealI\Classes\Skaarj.uc. You can save these text files with the "Export" button in the class browser. The .uc file is a text file, so it doesn't contain any binary data. Rather, it contains UnrealScript "#exec" commands to import all ancillary objects like meshes, sound effects, and textures, when you perform a clean rebuild.

There are two ways you can create and edit UnrealScript classes:

•	You create new classes in UnrealEd by right-clicking on an existing class and subclassing it (by choosing the "Create new class below..." menu option), and then use the built-in script editor and compiler. To edit an existing class, just double-click on it. Use Script/Compile (or F7) to recompile your script.

•	You can create new classes from outside UnrealEd by creating a new .uc file in the package's directory. For example, to add a new class named "Timster" to the "UnrealI" package, create a new file called "\Unreal\UnrealI\Classes\Timster.uc". This way, you can use your favorite stand-alone editing tool, such as the text editor built into Visual C++, to edit your script. However, when you manually work with .uc files, you must cleanly rebuild your package in order to regenerate the binary .u file which UnrealEd requires.

To summarize:

•	You can create new classes in UnrealEd using the built-in editor, or you can work directly with the .uc files using your favorite stand-alone editor.

•	There is one text .uc for each class. Think of this as your source code.

•	There is one binary .u file for each package. Think of this as your object code.

Programmers: Cleanly rebuilding your packages from the command line

You can rebuild individual .u files, or all of the .u files, from the command line as follows:

Delete the .u file(s) which you want to rebuild. For example, type "del \Unreal\System\*.u".

Type "Unreal -make" to run Unreal and rebuild the .u files.

Now, Unreal will go through all of the packages listed in the Unreal.ini [EditPackages] section, and rebuild any packages whose .u files are missing.

When Unreal rebuilds a package, it switches into the \Unreal\packagename\Classes directory (for example, if you're rebuilding the Engine package, it switches into \Unreal\Engine\Classes), and it imports all of the *.uc files it finds there.

The .uc files are text files containing UnrealScript code. There is one .uc file for each class. The .uc filename must correspond to the class name. For example, the PlayerPawn class must reside in the file "PlayerPawn.uc".

The .uc files may contain special UnrealEd commands which begin with the keyword "#exec". These "#exec" commands import various objects as the script is compiled. For example, #exec commands exist to import textures, sounds, meshes, and music. The "#exec" commands are not currently documented; you will need to see the example .uc files in the UnrealI package for examples of usage.

Rebuilding certain packages, such as the Engine package and the UnrealI package, requires that you have the source artwork, sounds, and meshes, which are available on the UnEdit ftp site as a separate download. The source data is not included in the regular source distribution because of its huge size. The source artwork can be extracted with WinZip into the various subdirectories of the Unreal\Engine\ and \Unreal\UnrealI\ directories (for example, the engine sounds go into \Unreal\Engine\Sounds).

When cleanly rebuilding, any UnrealScript compiler errors cause the rebuild to halt, and an appropriate error message is displayed on the screen.

To summarize:

•	Using "Unreal -make" cleanly rebuilds any missing .u files.

•	All .uc files (UnrealScript class definitions) are imported and recompiled.

•	The .uc files may contain "#exec" commands to import ancillary content.

•	The end result is that a new .u file is generated for each missing package.

Package file attributes: .upkg Files

When Unreal rebuilds your package using "Unreal -make", it tries to load a text PackageName.upkg definition file from the same \Unreal\PackageName\Classes directory. If not found, the default package options are used. A sample package definition file looks like this:

[Flags]

AllowDownload=False

ClientOptional=False

ServerSideOnly=True

The options that appear in a package definition file are:

•	AllowDownload: Whether you want players to be able to download this file when they enter a server. This should be enabled for user-created modifications, and disabled for game publisher distribution (so that people aren't able to download retail files freely).

•	ClientOptional: Whether the package is optional on the client side. Not currently supported; may be supported in the future for things like player skins.

•	ServerSideOnly: Says the package should only be loaded on the server side, and is not necessary for clients. For example, the IpDrv.u package is tagged as ServerSideOnly, because it contains classes like the server-uplink which only need to run on the server, and will be frequently updated.

Licensee programmers: Generating C++ header files which mirror your UnrealScript classes

If you create any intrinsic UnrealScript classes, or if you need to access any UnrealScript classes from C++ code, then you can have Unreal generate a C++ header file which mirrors the classes you've defined in UnrealScript.

For example, the Actor class any many of its child classes are defined by scripts in the Engine package (such as \Unreal\Engine\Classes\Actor.uc). The C++ code in the engine often needs to access objects in the Actor class. Early in development, we manually created C++ definitions which mirrored all of the UnrealScript classes. This process became tedious and error-prone as the number of classes increased. So, we added an option to Unreal to automatically generate a C++ header file, based on your UnrealScript definitions.

For an example of an automatically-generated C++ header file, check out "\Unreal\Engine\Inc\EngineClasses.h". This file was not written by a human. Unreal generated it.

To automatically generate a C++ header for a package, do the following:

Delete the package's .u file. For example, type "del \Unreal\System\Engine.u".

Run Unreal with the following parameters: "Unreal -make -h".

Unreal will create a new file for you, called "\Unreal\Engine\Inc\EngineClasses.h".

Now recompile the C++ source code.

Because there are many ways which UnrealScript and C++ can share information back and forth, the automatically-generated header file (for example EngineClasses.h) contains a variety of definitions:

•	The enumerations defined in the package.

•	C++ class definitions for all the intrinsic classes defined in the package. Note that non-intrinsic classes are not exported to the header file, because you can only access intrinsic classes from C++. (Note: this does not in any way limit what you can do in UnrealScript vs. C++).

•	For each class, C++ class member functions for all intrinsic functions defined in the class.

•	For each class, a C++ "#include" statement if a class-specific header file exists (for example, the Unreal generated C++ definition of the Actor class contains the #include "AActor.h" statement because the file \Unreal\Engine\Inc\AActor.h exists.

For a more concrete example, carefully examine the UnrealScript file "\Unreal\Engine\Classes\TcpLink.uc" and the following definitions in the file \Unreal\Engine\Inc\EngineClasses.h": enum ETcpLinkState, enum ETcpMode, and class ATcpLink. This provides an example of a fairly isolated UnrealScript class which defines several enumerations and intrinsic functions.

Finally, to avoid a chicken-and-egg scenario, you should create new classes in the following order: first create a class in UnrealScript, then generate the C++ header, then recompile the engine code (adding in the IMPLEMENT_CLASS macro for any new intrinsic classes you've added).

To summarize the important points here:

•	You created a new class in UnrealScript.

•	You needed to access that new class from C++.

•	You used the "Unreal -make -h" command to automatically generate a C++ header file defining the package's classes.

Programmers: Package related problems to avoid

•	Don't remove objects from packages which other people are relying on. For example, say level designers are using a texture package like SkyCity.utx which contains a texture named "SkyWall2" which they're using in many of their levels. If you go through and remove that texture from the .utx file, then the level designers won't be able to load their levels successfully. Rather they will get an error message along the lines of "Texture SkyWall2 was not found in package SkyCity.utx".

•	Avoid package filename collisions. Packages are identified by their base (extension-less) names, so you should node create a texture package named "Fred.utx" and a level named "Fred.unr". The base filename of each package must be unique.

•	Avoid circular package dependencies in .u files. For example, if you create two packages, "MyPackage" and "YourPackage" which both contain UnrealScript classes that refer to the other package, it will be impossible to cleanly rebuild both packages. During the clean rebuild process, packages are imported in the order they are specified in the Unreal.ini [EditPackages] section, and each package may only be dependent on the packages listed before it.

•	If you delete an UnrealScript, you must manually remove the .uc file corresponding to it. When you do a clean rebuild, Unreal imports all of the *.uc files in each package's directory.

Licensee programmers: Putting .uc script files under source control with SourceSafe

For programmers who like to keep their work archived under Microsoft Visual SourceSafe, here are some tips. We use SourceSafe internally for our development, though it is purely optional -- nothing in the Unreal source code assumes that you have SourceSafe:

•	Put all of your .uc files under source control (.uc files are text files containing the text of the UnrealScript code).

•	If someone removes a .uc file from source control, be sure to delete the corresponding .uc file on disk.

•	In the UnrealEd class browser, the "Export" button exports all scripts which you've modified. If you try to export a script which you haven't checked out of SourceSafe, you will get a (safe, non-fatal) warning message that the .uc file is write-protected. If that happens, just check the .uc file out of SourceSafe and hit the "Export" button again.

Programmers: Adding/Removing variables in UnrealScript classes can be dangerous

When you add or remove variables in an UnrealScript class, that changes the binary layout of objects belonging to that class. For example, if you have a script that contains some variable declarations like this:

class TestClass expands Actor;

var int i, j;

var texture t;

And you remove one of the variables like this:

class TestClass expands Actor;

var int i;

var texture t;

Then any objects in memory belonging to TestClass will become corrupted as soon as you recompile the script. The solution is to only add or remove variables from a script in an empty level. However, empty levels contain an actor belonging to the LevelInfo class, as well as one or more Camera actors, so it's never safe to add or remove variables from any of the following classes in UnrealEd: Actor, Info, LevelInfo, Camera, PlayerPawn, Pawn. To work with these files, edit their .uc files on-disk, and do a clean rebuild.

Also, bear in mind that Unreal makes heavy use of the Actor, Pawn, PlayerPawn, LevelInfo, and other intrinsic classes in C++ code. So, adding and removing variables to any intrinsic classes will cause the C++ code and UnrealScript code to disagree about the binary layout of classes. Whenever you change an intrinsic class, the safe thing to do is a clean rebuild with the "Unreal -make -h" option to generate new C++ header files for your classes, then recompile the Unreal C++ source.

Programmers: The package file format

Abandon all hope ye who try to parse this file format.

The Unreal package file format is only useful to people who want to write external utilities that read and write Unreal files. Level designers and UnrealScript programmers don't need to know this info. But, the Unreal package file format is quite complex compared to what Quake, Quake 2, and Jedi Knight utility writers are accustomed to. It's so complex, in fact, that I doubt many utility writers are going to want to deal with it directly. It is complex for several reasons:

•	Unreal files can contain a wide range of objects (there are hundreds of unique classes defined in Unreal), versus perhaps 20-30 for Quake.

•	Unreal objects can contain complex interdependencies: for example, a level package can refer to a texture package, which can refer to a class package, which can contain a class that refers to a sound in a sound package. So, each package file needs to keep track of not only the objects it contains, but also the external objects that it refers to.

•	Unreal objects are expandable by users, so we needed to create a generalized system for serializing (a.k.a. saving and loading) these complex user-defined objects.

•	Unreal objects are scoped within hierarchical packages (much like DOS and Windows files are scoped within a system of hierarchical directories). Therefore, the entire tree structure of the object scope hierarchy must be described within the file.

The coming release of the enhanced version of UnrealEd in 3+ months will include a very modular plug-in interface for creating built-in UnrealEd tools, file importing tools, and file exporting tools, which will operate directly on the engine's C++ data. That release will greatly simplify the task of programmers who want to write Unreal utilities, because it eliminates the need to read and write package files directly. Rather, with the UnrealEd plug-in interface, you will be able to use C++ to create all of your tools and compile them into DLL's. You'll make calls to the Unreal engine to allocate objects, save package files, load package files, etc. with the hairy file-format issues taken care of by the engine.

Data types stored in package files.

•	The "int" type is signed, 4 bytes long, and is stored in Intel byte order.

•	The "float" type is signed, IEEE standard, 4 bytes long, and stored in Intel byte order.

•	The "string" type is stored as a bunch of characters (one nonzero byte each) terminated by a zero byte.

•	The "FCompactIndex type" corresponds to a 32-bit signed value but are stored in a compacted format. See below for a description.

•	The "FGuid" type corresponds to a set of four consecutive int's defining a globally unique identifier.

Object and Name flags.

Each object and name stored in a package file can contain any combination of the following bitflags:

•	RF_LoadForClient (0x00010000): Must be loaded for game client.

•	RF_LoadForServer (0x00020000): Must be loaded for game server.

•	RF_LoadForEdit (0x00040000): Must be loaded for editor.

•	RF_Public (0x00000004): Object may be imported by other package files.

•	RF_Standalone (0x00080000): Keep object around (don't garbage collect) for editor even if unreferenced.

•	RF_Intrinsic (0x04000000): Class or name is defined in C++ code and must be bound at load-time.

•	RF_SourceModified (0x00000020): The external data source corresponding to this object has been modified.

•	RF_Transactional (0x00000001): Object must be tracked in the editor by the Undo/Redo tracking system.

•	RF_HasStack (0x02000000): This object has an execution stack allocated and is ready to execute UnrealScript code.

Any other bitflags stored in package files are irrelevent, should be set to zero when saving a package file, and should be ignored when loading a package file.

Compact Indices.

Compact indices exist so that small numbers can be stored efficiently. An index named "Index" is stored as a series of 1-5 consecutive bytes with the following C++ code. Basically, the "Ar << B0" type code serializes the byte stored in the variable B0. Serialize can mean read or write, depending on the internal implementation of the archive object Ar.

//

// FCompactIndex serializer.

//

FArchive& operator<<( FArchive& Ar, FCompactIndex& I )

{

       	INT Original = I.Value;

DWORD V = Abs(I.Value);

       	BYTE B0 = ((I.Value>=0) ? 0 : 0x80) + ((V < 0x40) ? V : ((V & 0x3f)+0x40));

        I.Value = 0;

        Ar << B0;

        if( B0 & 0x40 )

        {

            V >>= 6;

            BYTE B1 = (V < 0x80) ? V : ((V & 0x7f)+0x80);

            Ar << B1;

            if( B1 & 0x80 )

            {

                V >>= 7;

                BYTE B2 = (V < 0x80) ? V : ((V & 0x7f)+0x80);

                Ar << B2;

                if( B2 & 0x80 )

                {

                    V >>= 7;

                    BYTE B3 = (V < 0x80) ? V : ((V & 0x7f)+0x80);

                    Ar << B3;

                    if( B3 & 0x80 )

                    {

                        V >>= 7;

                        BYTE B4 = V;

                        Ar << B4;

                        I.Value = B4;

                    }

                    I.Value = (I.Value << 7) + (B3 & 0x7f);

                }

                I.Value = (I.Value << 7) + (B2 & 0x7f);

            }

            I.Value = (I.Value << 7) + (B1 & 0x7f);

        }

        I.Value = (I.Value << 6) + (B0 & 0x3f);

        if( B0 & 0x80 )

            I.Value = -I.Value;

        if( Ar.IsSaving() && I.Value!=Original )

            appErrorf("Mismatch: %08X %08X",I.Value,Original);

    }

    return Ar;

}

Names

Names are stored a compact indices with values >= 0 which index into the file's name table.

Objects References.

Objects are stored as compact indices with values defined as follows:

•	If Index==0: The object is NULL (known as NULL in C++, None in UnrealScript).

•	If Index<0: Refers to the (-Index-1)th object in this file's import table.

•	If Index>0: Refers to the (Index-1)th object in this file's export table.

The Package file header.

•	int Tag: Always 0x9E2A83C1 (see PACKAGE_FILE_TAG in UnObjVer.h).

•	int FileVersion: Version of the engine which saved the file. Currently 61. Utilities should only operate on files with this exact version number, because only the file header is guaranteed not to change in future versions...anything else could change (See PACKAGE_FILE_VERSION in UnObjVer.h).

•	int PackageFlags: Bitflags describing the package:

•	PKG_AllowDownload (0x0001): The package is allowed to be downloaded to clients freely.

•	PKG_ClientOptional (0x0002): All objects in the package are optional (i.e. skins, textures) and it's up to the client whether he wants to download them or not. Not yet implemented; currently ignored.

•	PKG_ServerSideOnly (0x0004): This package is only needed on the server side, and the client shouldn't be informed of its presence. This is used with packages like IpDrv so that it can be updated frequently on the server side without requiring downloading stuff to the client.

•	int NameCount: Number of names stored in the name table. Always >= 0.

•	int NameOffset: Offset into the file of the name table, in bytes. 0 designates the first byte of the file, of course.

•	int ExportCount: Number of exported objects in the export table. Always >= 0.

•	int ExportOffset: Offset into the file of the export table.

•	int ImportCount: Number of imported objects in the import table. Always >= 0.

•	int ImportOffset: Offset into the file of the import table.

•	int HeritageCount: Number of GUID's stored in the package's heritage table. Always >= 1.

•	int HeritageOffset: Offset into the file of the heritage GUID table.

The following tables reside in the file at the offset specified by the header. If a table contains zero entries (as specified in the header), the offset value is meaningless and should be ignored.

Name table.

Contains a list of human-readable Unreal names (which correspond to the UnrealScript "name" datatype and the C++ "FName" data type). Each name is stored consecutively in the following format:

•	string NameString: String representation of the name, up to NAME_SIZE characters (currently 64, may increase with future versions).

•	int NameFlags: Internal flags describing the name. See "Object and Name Flags" above.

Export table.

Contains a list of objects contained in (a.k.a. "exported by") this file. Similar to a Windows DLL's export table.

•	object reference ClassIndex: Points to the class object describing the class of this object.

•	object reference PackageIndex: Points to the package object describing the package this object resides in.

•	object reference SuperIndex: If this is a field (a struct, class, property, or another field subclass): Points to the superfield object of the field.

•	FName ObjectName: This object's name.

•	int ObjectFlags: Flags.

•	int SerialSize: Size (in bytes) of the object's serialized data stored in this file.

•	if SerialSize>=0, int SerialOffset: Offset into this file of the start of the object's serialized data.

Import table.

Contains a list of objects in other packages which this packages refers to. Similar to a Windows DLL's import table.

•	name ClassPackage: The name of the package which this object's class object resides in.

•	name ClassName: The name of this object's class.

•	FCompactIndex PackageIndex: The index of the package this object resides in.

•	FName ObjectName: The name of this object.

Heritage GUID table.

Contains a list of GUID's which this package is compatible with. In the current version of Unreal, this table always contains exactly one GUID, because the backwards-compatible package management code has not yet been written. In the future, it may contain more than one GUID. Each entry contains:

•	A GUID (4 consecutive int's).

Serialize object format.

Extremely complex. Different for each class. Hard to read. Not yet documented.


Quick Reference

UnrealEd Quick Reference

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

Audience: Level Designers
UnrealEd undergoes rapid changes so this document may not be up-to-date.

Known Problems with the Beta

•	There is no complete documentation...we're working on it.

•	There are some blank icons on the UnrealEd toolbar (it will be rearranged later).

•	Some people are reporting "Runtime Error 50003" when running UnrealEd.exe...looking into it.

•	Some people are reporting "Wrong version of the Runtime DLL" when running UnrealEd.exe...looking into it.

Suggestions for making maps run faster

Here are some fairly straightforward tricks that can be implemented in existing maps. These are worthwhile enough that I recommend going back and applying them to existing maps, in the worst-performance areas where you need a speed boost. The areas that are noticeably slow are the large outdoor areas where you see buildings from the outside, and areas which use a lot of dynamic light.

•	When you have a huge outdoor area, have as few far-away meshes in view as possible. Type "STAT MESH" and look at the "MESHCOUNT=xxx" number to see how many meshes are in view. About 50% of the CPU time required to draw a mesh is irrespective of its size, so if you have a gun lying on the ground a mile away, but it's visible, even though it might only take up 1 pixel on the screen, it takes several milliseconds for the engine to perform lighting, transformation, and teeny polygon rendering on it. For example, in walking along the ridge in Bluff, the MESHCOUNT is 6, though I was only aware of one mesh (the Nali). It turns out that there's a transparent window, and two meshes visible through the transparent window, and three meshes somewhere else (not sure where).

•	In the huge levels that combine indoors and outdoors, like Bluff, where you want to have transparent windows that players can see out of, use this one-way transparency trick: Add a semisolid cube brush for the window; make the inside face transparent and one-sided; and make the outside face non-transparent and one-sided. This way, players inside can see out, but players outside can't see in. This noticeably speeds up maps when the player is on the outside, looking in.

•	If you have a lot of dynamic lights in an area, and you don't mind extremely fuzzy (low detail) shadows, use the "super low shadow detail trick": If you select both "low shadow detail" and "high shadow detail" on a surface together, the engine uses a special "super low shadow detail" mode which is 4X faster for dynamic lighting. Since this makes the shadows extremely fuzzy (which looks weird sometimes), this isn't a good trick to use all over the place -- it's just for the areas where you want to have a LOT of dynamic light, or dynamic light in huge outdoors areas.

Stupid UnrealEd Tricks

These are things people needed but I didn't have time to create proper user interfaces for:

To align textures as floors (like for the ground in Pancho's hubs) AND scale them up, do this:

1. Select the polygons.
2. Do the normal "align as floor" thing.
3. In the log window, type: POLY TEXSCALE RELATIVE UU=2.0 VV=2.0

The above command scales them up by a factor of 2.0. You can scale them up or down by different amounts by plugging in different numbers, for example: POLY TEXSCALE RELATIVE U=0.5 V=0.5

If you have a super-huge outdoor area and you want even lower shadow detail than normal, you can check both the "Low Shadow Detail" and the "High Shadow Detail" options. UnrealEd recognizes this as a special combination that means "Superduperultralow shadow detail".

Special mouse clicking combinations

•	A + right mouse click: Add actor there.

•	L + right mouse click: Add light there.

Shortcut keys

•	Delete: Delete selected actors.

•	1, 2, 3: Slow, medium, and fast movement speed.

•	F1: Help.

•	F4: Actor properties.

•	F5: Surface properties.

•	F6: Level properties.

•	F7: Compile changed scripts.

•	F8: Rebuilder.

•	B: Toggle brush visibility in the current viewport.

•	H: Toggle actor visibility in the current viewport.

•	P: Toggle player controls or realtime update of the viewport.

•	Shift-A: Select all actors.

•	Shift-B: Select all surfaces belonging to the selected surfaces' brushes.

•	Shift-C: Select adjacent coplanar polygons.

•	Shift-D: Duplicate selected actors.

•	Shift-F: Select adjacent floors.

•	Shift-G: Select surfaces belonging to the selected surfaces' groups.

•	Shift-I: Select surfaces with items matching the selected surfaces' items.

•	Shift-J: Select all adjacent surfaces(flood-fill).

•	Shift-L: Look ahead in the current viewport (no pitch or roll).

•	Shift-M: Memorize selected surfaces.

•	Shift-N: Select none.

•	Shift-O: Select surfaces from intersection of selected surfaces and memory.

•	Shift-P: Select all surfaces.

•	Shift-Q: Reverse the set of selected surfaces.

•	Shift-R: Recall memorized surface selection.

•	Shift-T: Select all surfaces which use the current texture.

•	Shift-U: Select union of selected surfaces and memorized surfaces.

•	Shift-W: Select adjacent wall surfaces (flood-fill).

•	Shift-X: Select exclusive or of selected surfaces and memorized surfaces.

•	Shift-Y: Select adjacent slanted surfaces.

•	Shift-Z: Select none.

•	Ctrl-A: Add brush to world.

•	Ctrl-B: Load brush.

•	Ctrl-C: Copy.

•	Ctrl-D: Deintersect brush with world.

•	Ctrl-E: Save as.

•	Ctrl-L: Save level.

•	Ctrl-O: Load level.

•	Ctrl-P: Play level.

•	Ctrl-N: Intersect brush with world.

•	Ctrl-R: Redo.

•	Ctrl-S: Subtract brush from world.

•	Ctrl-V: Paste.

•	Ctrl-W: Duplicate.

•	Ctrl-X: Cut.

•	Ctrl-Z: Undo.


Rebuilder Overview

Overview

An UnrealEd map contains three separate kinds of information: Geometry, the BSP, and lighting.  The BSP depends on the geometry, and lighting depends on the BSP.

As you build a level the geometry, BSP, and lighting aren’t always maintained in real-time.  For example, when you go into map-edit mode and make changes, the BSP is not kept up to date.  When you move lights around, the lighting isn’t kept up to date.  The Rebuilder dialog enables you to refresh these aspects of a level.

Rebuilding the Geometry

When you rebuild a level’s geometry, UnrealEd goes through and adds/subtracts all of the brushes in the level again.  This causes the polygon view of the level to be updated.

You only need to rebuild a level’s geometry after you leave Map Edit mode.  You won’t gain or lose anything by rebuilding the geometry in other circumstances.

Rebuilding the BSP

This rebuilding option goes through all of the polygons in the world and cleans them up.  The visible result is usually fewer polygons and a more efficient level.  If you find UnrealEd running slowly after you’ve performed a lot of add/subtract operations, rebuilding the BSP will often help.

In addition, this feature will usually patch up the thin cracks you may have in your walls from imprecise real-number rounding.

To see what rebuilding the BSP actually does, you should look at a world before and after using the “Polygon” camera mode, which shows all of the polygons that UnrealEd is dealing with.  The fewer, the better.

Rebuilding the Lighting

This option tells UnrealEd to rebuild all of the shadow patterns and lighting effects caused by lights you’ve placed in a level.  This is especially useful after you have move many lights around.  Note than you can pick the option “Apply selected lights only” to get quick feedback on the results of moving a particular light source.


References

Class Reference

Console Commands

Hot Keys

Quick Reference

UnrealScript Language Reference

Unit Conversions

User Interface Guide


SkyBox

SkyBox tutorial - by Jon Renner

The concept of a skybox can sometimes be difficult to understand, but I've found it's best to use this analogy to describe it: Consider the skybox a small room with a camera in it. Any face with the surface property "fake backdrop" applied acts like a TV connected to this camera. So if you apply the appropriate SkyBox textures (Load->SkyBox) it becomes very easy to create skies in your outdoor areas.

So create a box separated from the rest of your world, and apply the appropriate textures to it. (i.e., a cloud texture on the top, mountains on the sides, and ground/rock on the bottom.) Then under the Classes menu expand the Info->ZoneInfo->SkyZoneInfo thread and add a SkyZoneInfo actor to your SkyBox.

To spruce up your skies, you can add the "UPan" or "Vpan" surface properties to make them move. Another neat trick is to add a translucent sheet of a cloud-like texture slightly below the sky in the skybox. To change the speed at which the UPan and VPan properties move the sky you'll want to edit the Zone properties. To do this, double-click on the SkyZoneInfo in the 2D or 3D view, and look under the "ZoneLight" heading for UPanspeed and Vpan speed. Raise or lower these numbers to suite your tastes.


Textures

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

This document is a trade secret of Epic MegaGames, Inc.
Last Updated: 06/11/98

Texture dimensions

Unreal texture dimensions may be any powers of two from 1 to 1024. Textures need not be square. For example, many of the textures in Unreal 1 are 128x128, 256x128, and 256x256. Unreal's software rendering code supports textures of any size from 1x1 up to 1024x1024.

Unreal's 3D hardware rendering code gracefully handles textures of all sizes from 1x1 up to 1024x1024, though the actual rendered texture resolution is limited to texture sizes which the hardware supports. All current hardware is limited to 256x256 textures. For example, when you see a 1024x1024 texture on 3dfx hardware, Unreal substitutes a lower resolution (256x256) version of the texture. The texture is scaled up properly, so that the only noticeable artefact is blurring of the texture.

Because most current 3D hardware only supports textures up to 256x256, we generally don't use higher resolution textures in our game.

Creating and importing textures

Unreal textures are palettized, 256-color textures. Each texture in Unreal may have its own palette. The result is that you can achieve a lot of color variety by using textures with different palettes, while benefitting from the space savings of 8-bit textures.

The Unreal team creates textures in Fractal Painter and Photoshop, always working with the source art in 24-bit color. When a texture is complete, it is converted into a 256-color, palettized .pcx or .bmp file and imported into UnrealEd. To import a texture into UnrealEd, go into the texture browser (on the right side of the screen), and click on the "Import" button. When importing a texture, you can specify its name, the texture group it should appear in, and the package (.utx file) it should be saved in.

Unreal a texture mapping feature called "masking", where color zero is treated as if it were transparent. We use this for textures like vines, grating, and sprites. To create a masked texture, you will need to use a 256-color paint program to edit your image and apply color zero to the transparent portions of the texture. Then, import the texture and click on the "Masked" checkbox in the texture importing dialog. If you don't click on the "Masked" checkbox, the texture's mipmaps will not be properly masked.

When you import a texture, UnrealEd will automatically create mipmaps for the texture (mipmaps are lower resolution versions of the texture, used for antialiasing far-away polygons).

When you import two textures which use the same palette, UnrealEd makes note of this fact and takes advantage of it for optimization. In hardware rendering, the frame rate is partly dependent on the number of palettes visible in a scene, so there is a performance advantage to forcing textures to have the same palette. Programs like Image Alchemy can convert groups of 24-bit color images to 8-bit and force a common palette.

Graphics tools we use and recommend

•	Fractal Painter: For realistic painting of textures.

•	Photoshop: For realistic painting of textures and retouching of digitized textures.

•	Deluxe Paint: For creating masked textures, and for creating custom palettes.

•	Image Alchemy: For batch converting 24-bit color images to 256-color images.

Editing texture properties

To edit a texture's properties in UnrealEd, right-click on the texture in the texture browser (on the right side of the screen), and click on the "Properties" menu item. Here you can customize many properties of a texture. The properties which are not documented here are reserved for future use, and not yet supported.

Animating textures

The easiest way to create a sequence of animating textures is to import a bunch of textures with names that end in _A## (where ## is the number of the animation frame, starting at zero). For example, to create a four-texture animation sequence, import four files named:

•	MyAnim_A00.bmp

•	MyAnim_A01.bmp

•	MyAnim_A02.bmp

•	MyAnim_A03.bmp

When you import a texture into UnrealEd, it looks for _A## in the name and then sets up the texture for animation.

When you import animating textures into UnrealEd, the editor shows all of the individual frames of animation. However, you should always use the first one (the one with the name ending in A00) when setting the texture's properties and adjusting its frame rate. The following useful texture properties are related to animation:

•	AnimNext: The next texture in the animation sequence, or None to indicate that the sequence should proceed back to the first texture.

•	PrimeCount: For procedural animating textures, the texture internally animates itself PrimeCount times before it's first rendered. Use this to avoid algorithmic fire billowing up the first time it comes into view.

•	MinFrameRate: The minimum frame rate for the animation. The texture will always animate this fast, or faster (0 indicates that the texture should animate at the rendering frame rate).

•	MaxFrameRate: The maximum frame rate for the animation. The texture will always animate this fast, or slower. If you set this equal to MinFrameRate, the texture animation rate will never vary.

For texture animation, we support two animation rates (MinFrameRate and MaxFrameRate) to prevent "animation aliasing": the annoying artefacts you see when a texture animates through frames at a variable rate, such as "1 2 2 3 4 4 5". When the rendering frame rate is between MinFrameRate and MaxFrameRate, the texture will always animate smoothly, i.e. "1 2 3 4 5".

Detail textures and Macrotextures

A texture may optionally have a Detail texture and a Macrotexture associated with it. A detail texture is a very small, fine pattern which is faded in as you approach a surface, for example wood grain, or imperfections in stone. A Macrotexture is a large, scaled-up texture which is overlaid onto surface. For example, Macrotextures can be used to add large-scale detail to textures in outdoor spaces to avoid an overly "tiled" look.

Detail textures and Macrotextures only are visible on 3d hardware. For performance reasons, they are ignored in the software rendering code.

When you bring up the "texture properties" editor, you can associate a detail texture and a macrotexture with a given texture.

When you import a detail texture, you need to set its Scale value to a small number (typically 0.25) to specify its scaling relative to whatever texture it applies to. Macrotextures need to have their Scale value set to a large number (typically 8) to specify its scaling relative to the surface it's applied on.

It is valid to use procedural textures as macrotextures, microtextures, or both.

Detail textures and macrotextures modulate (multiply) the surface they're applied to. By modulating, they have the ability to scale the surface's brightness up or down. Colors with RGB brightness values from 0-127 darken the surface; 128 has no effect; and 129-255 brighten the surface. Therefore, when drawing microtextures and macrotextures, it is important that you design them with their brightnesses in the proper range so they affect surfaces naturally. If a detail texture's average brightness deviates too far from 128, then surfaces will appear to brighten or darken as you approach them.

Procedural textures

To create a new procedural texture, click on the "New" button in the texture browser and select a type of texture to create, for example "FireTexture" or "WaveTexture". Procedural textures are animated algorithmically so they have infinite, non-repeating animation. They also have the advantage of taking up very little disk space (on the order of 4K) and they only occupy as much memory as a single, non-animating texture of the same size. The procedural texture types and their options are documented elsewhere.

Texture .utx files

Unreal saves texture packages into .utx files. A .utx file contains all of the textures (one or more) in a particular package. The .utx file format contains the raw texture bitmaps as well as mipmaps, texture properties, and palettes. A game created with the Unreal engine will typically ship with many .utx files (one for each texture package).


Tutorials

Well got some tutorials for you all. If you wish to include information or a tutorial, please email me at: help@skarz.com. Check out my website for more info: www.skarz.com

Hello Room (Your very first tutorial)

Creating a Basic Room

Ambient Sounds

Fog

Importing Objects

Levels with Speed

Moving Brushes

SkyBox

Vertex Editing

Zones


Unit Conversions

ALSO SEE: Unreal Metrics and Specifications for in-depth info!

by Jon Renner

Unit Length Conversions:

•	16 Units is equal to a foot (a foot is a little less than 1/3 a meter)

•	1 Unit is a little under an inch (an inch is 2.54 cm)

Other Info: Thanks to Louis A. Kaplin (aka driftwood  -  lak193@email.psu.edu) for most of everything below.

•	The Player is 6 feet (86 units) tall.

•	MeleeRange=50

•	GroundSpeed=400

•	AirSpeed=400

•	AccelRate=2048

•	RotationRate=(Pitch=3072,Yaw=65000,Roll=2048)

•	UnderWaterTime=20 (secs, presumably)

•	BaseEyeHeight=23

•	CollisionRadius=17

•	CollisionHeight=39

And for the type of light the player gives off:

•	LightBrightness=70

•	LightHue=40

•	LightSaturation=128

•	LightRadius=6


Unreal Metrics and Specifications

Default Player Geometry

These apply to the woman and man.

·	Player height is 6 feet tall (60 world units)

·	Player's eye is 5 feet above the ground (50 world units)

·	The closest a player can get to a wall is 2 feet (20 world units)

·	The player's head bobs vertically up to plus-or-minus one half foot when walking

Monster geometry

Monsters move with physics similarly to the player's, except the following parameters can be changed:

·	How close it can get to walls (player: 2 feet)

·	How tall it is (player: 6 feet)

·	How high a step it can climb (player: 2.1 feet)

·	Its view height when the player is controlling it (player: 5 feet)

·	The maximum slope it can climb without sliding

·	The maximum slope it can climb with sliding

Metrics and Constraints

Steps

·	Any step that is 32 (2 feet) or fewer units tall or smaller is climbable.

·	Any step that is 48 (3 feet) or more units tall is unclimbable.  Useful for railings and ledges.

·	Try to avoid steps or railings between 32 and 48 units (2-3 feet) tall, because one can’t reliably predict whether a player will be able to climb it or not.

Doors and grates

·	Do not create grates on the floor where the player can walk. The player will get stuck in them.  A grate is an opening that the player can stand on but is too small for the player to fall through.

·	An opening 48 (3 feet) units wide or more is a door and the player can go through it.

·	A player can not go through an opening 32 (2 feet) units wide or less.

·	You can make tricky doorways designed to only let small players through, i.e. doorways less than 32 (2 feet) units wide.  If you do this, only do it with a small doorway, not a long passage.  If the player barely fits, she can go through a doorway easily but may get stuck on a long passage.

Ceiling

·	For best results, the ceiling should always be at least two feet above the player's head, and it looks best when significantly higher.  In regular architecture, ceilings under 10 feet high are uncommon.

·	Don't create ceilings (low doorways or slanted ceilings) where the player can hit his head on the ceiling.  Though these situations aren't disastrous, the engine doesn't handle them well and movement becomes choppy.

V-Passages

·	Avoid passages that get progressively narrower if there's a chance the player will get stuck at the end of one.  The collision system makes thin passageways difficult to deal with.

Wedge sides

·	Avoid creating buildings with sides that look like wedges (30 degrees or less).  The player gets snagged on these.  This only refers to exterior wedges (outsides of objects), not wedge corners in rooms.  Wedge corners in rooms are fine.

Grades

·	A slope less than 20 degrees behaves exactly like a floor (and is actually considered a floor).  Players can move on these without obstruction.

·	A slope between 20 and 35 degrees is a grade.  The player can move up these but she slides and must continually struggle to climb to avoid sliding all the way down.

·	A slope over 35 degrees is unclimbable.

Illumination problems

As you experiment with lighting, you'll notice some situations that look great and some that look weird.  In general, try to avoid the weird looking stuff.  More tips to come.

Texturing constraints

·	In some weird viewing positions, you'll notice textures warping. This is especially noticeable when a polygon is at a very skewed angle.  Try to "design around" this.  In general, floors and walls look best when horizontal or vertical.  Slopes look perfect when far away (i.e. on ceilings), but they warp when the player can get close and view them at skewed angles.

·	Textures tend to look bad (jittery and wavy) when far away. This is especially bad with high-contrast textures.  For best results, use low-contrast textures for large things that are often viewed from a distance, such as sides of buildings.

·	Since floors are always viewed at a very skewed angle, low-contrast textures look much better than high-contrast ones.  This doesn't apply as much to walls and ceilings.

·	In general, use door frames, railings, and other devices when possible to avoid situations where the player sees textures that are highly sloped.

Recommended object sizes

Soon, we'll put together a list of common object sizes (along with brushes for creating things like doors), including:

·	Doors (minimum size, typical sizes)

·	Ceilings (minimum height, typical sizes)

·	Stairways (stair minimum and maximum heights)


UnrealScript Language Reference

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

This document is a trade secret of Epic MegaGames, Inc.

Introduction

Purpose of this document

This is a technical document describing the UnrealScript language. It’s not a tutorial, nor does it provide detailed examples of useful UnrealScript code. For examples of UnrealScript prior to release of Unreal, the reader is referred to the source code to the Unreal scripts, which provides tens of thousands of lines of working UnrealScript code which solves many problems such as AI, movement, inventory, and triggers. A good way to get started is by printing out the "Actor", "Object", "Pawn", "Inventory", and "Weapon" scripts.

This document assumes that the reader has a working knowledge of C/C++, is familiar with object-oriented programming, has played Unreal and has used the UnrealEd editing environment.

Design goals of UnrealScript

UnrealScript was created to provide the development team and the third-party Unreal developers with a powerful, built-in programming language that maps naturally onto the needs and nuances of game programming.

The major design goals of UnrealScript are:

•	To support the major concepts of time, state, properties, and networking which traditional programming languages don’t address. This greatly simplifies UnrealScript code. The major complication in C/C++ based AI and game logic programming lies in dealing with events that take a certain amount of game time to complete, and with events which are dependent on aspects of the object’s state. In C/C++, this results in spaghetti-code that is hard to write, comprehend, maintain, and debug. UnrealScript includes native support for time, state, and network replication which greatly simplify game programming.

•	To provide Java-style programming simplicity, object-orientation, and compile-time error checking. Much as Java brings a clean programming platform to Web programmers, UnrealScript provides an equally clean, simple, and robust programming language to 3D gaming. The major programming concepts which UnrealScript derives from Java are: a pointerless environment with automatic garbage collection; a simple single-inheretance class graph; strong compile-time type checking; a safe client-side execution "sandbox"; and the familiar look and feel of C/C++/Java code.

•	To enable rich, high level programming in terms of game objects and interactions rather than bits and pixels. Where design tradeoffs had to be made in UnrealScript, I sacrificed execution speed for development simplicity and power. After all, the low-level, performance-critical code in Unreal is written in C/C++ where the performance gain outweighs the added complexity. UnrealScript operates at a level above that, at the object and interaction level, rather than the bits and pixels level.

During the early development of UnrealScript, several major different programming paradigms were explored and discarded before arriving at the current incarnation. First, I researched using the Sun and Microsoft Java VM’s for Windows as the basis of Unreal’s scripting language. It turned out that Java offered no programming benefits over C/C++ in the Unreal context, added frustraging restrictions due to the lack of needed language features (such as operator overloading), and turned out to be unfathomably slow due to both the overhead of the VM task switch and the inefficiencies of the Java garbage collector in the case of a large object graph. Second, I based an early implementation of UnrealScript on a Visual Basic variant, which worked fine, but was less friendly to programmers accustomed to C/C++. The final decision to base UnrealScript on a C++/Java variant was based on the desire to map game-specific concepts onto the language definition itself, and the need for speed and familiarity. This turned out to be a good decision, as it has greatly simplified many aspects of the Unreal codebase.

Example program structure

This example illustrates a typical, simple UnrealScript class, and it highlights the syntax and features of UnrealScript. Note that this code may differ from that which appears in the current Unreal source, as this documentation is not synced with the code.

//=============================================================================

// TriggerLight.

// A lightsource which can be triggered on or off.

//=============================================================================

class TriggerLight expands Light

package(UnEngine);

//-----------------------------------------------------------------------------

// Variables.

var() float ChangeTime; // Time light takes to change from on to off.

var() bool bInitiallyOn; // Whether it's initially on.

var() bool bDelayFullOn; // Delay then go full-on.

var ELightType InitialType; // Initial type of light.

var float InitialBrightness; // Initial brightness.

var float Alpha, Direction;

var actor Trigger;

//-----------------------------------------------------------------------------

// Engine functions.

// Called at start of gameplay.

function BeginPlay()

{

// Remember initial light type and set new one.

Disable( 'Tick' );

InitialType = LightType;

InitialBrightness = LightBrightness;

if( bInitiallyOn )

{

Alpha = 1.0;

Direction = 1.0;

}

else

{

LightType = LT_None;

Alpha = 0.0;

Direction = -1.0;

}

}

// Called whenever time passes.

function Tick( float DeltaTime )

{

LightType = InitialType;

Alpha += Direction * DeltaTime / ChangeTime;

if( Alpha > 1.0 )

{

Alpha = 1.0;

Disable( 'Tick' );

if( Trigger != None )

Trigger.ResetTrigger();

}

else if( Alpha < 0.0 )

{

Alpha = 0.0;

Disable( 'Tick' );

LightType = LT_None;

if( Trigger != None )

Trigger.ResetTrigger();

}

if( !bDelayFullOn )

LightBrightness = Alpha * InitialBrightness;

else if( (Direction>0 && Alpha!=1) || Alpha==0 )

LightBrightness = 0;

else

LightBrightness = InitialBrightness;

}

//-----------------------------------------------------------------------------

// Public states.

// Trigger turns the light on.

state() TriggerTurnsOn

{

function Trigger( actor Other, pawn EventInstigator )

{

Trigger = None;

Direction = 1.0;

Enable( 'Tick' );

}

}

// Trigger turns the light off.

state() TriggerTurnsOff

{

function Trigger( actor Other, pawn EventInstigator )

{

Trigger = None;

Direction = -1.0;

Enable( 'Tick' );

}

}

// Trigger toggles the light.

state() TriggerToggle

{

function Trigger( actor Other, pawn EventInstigator )

{

log("Toggle");

Trigger = Other;

Direction *= -1;

Enable( 'Tick' );

}

}

// Trigger controls the light.

state() TriggerControl

{

function Trigger( actor Other, pawn EventInstigator )

{

Trigger = Other;

if( bInitiallyOn ) Direction = -1.0;

else Direction = 1.0;

Enable( 'Tick' );

}

function UnTrigger( actor Other, pawn EventInstigator )

{

Trigger = Other;

if( bInitiallyOn ) Direction = 1.0;

else Direction = -1.0;

Enable( 'Tick' );

}

}

The key elements to look at in this script are:

•	The class declaration. Each class "expands" (derives from) one parent class, and each class belongs to a "package", a collection of objects that are distributed together. All functions and variables belong to a class, and are only accessible through an actor that belongs to that class. There are no system-wide global functions or variables.

•	The variable declarations. UnrealScript supports a very diverse set of variable types including most base C/Java types, object references, structs, and arrays. In addition, variables can be made into editable properties which designers can access in UnrealEd without any programming.

•	The functions. Functions can take a list of parameters, and they optionally return a value. Functions can have local variables. Some functions are called by the Unreal engine itself (such as BeginPlay), and some functions are called from other script code elsewhere (such as Trigger).

•	The code. All of the standard C and Java keywords are supported, like "for", "while", "break", "switch", "if", and so on. Braces and semicolons are used in UnrealScript as in C, C++, and Java.

•	Actor and object references. Here you see several cases where a function is called within another object, using an object reference.

•	The "state" keyword. This script defines several "states", which are groupings of functions, variables, and code which are executed only when the actor is in that state.

•	Note that all keywords, variable names, functions, and object names in UnrealScript are case-insensitive. To UnrealScript, "Demon", "demON", and "demon" are the same thing.

The Unreal Virtual Machine

The Unreal Virtual Machine consists of several components: The server, the client, the rendering engine, and the engine support code.

The Unreal server controls all gameplay and interaction between players and actors. In a single-player game, both the Unreal client and the Unreal server are run on the same machine; in an Internet game, there is a dedicated server running on one machine; all players connect to this machine and are clients.

All gameplay takes place inside a "level", a self-contained environment containing geometry and actors. Though UnrealServer may be capable of running more than one level simultaneously, each level operates independently, and are shielded from each other: actors cannot travel between levels, and actors on one level cannot communicate with actors on another level.

Each actor in a map can either be under player control (there can be many players in a network game) or under script control. When an actor is under script control, its script completely defines how the actor moves and interacts with other actors.

With all of those actors running around, scripts executing, and events occuring in the world, you're probably asking how one can understand the flow of execution in an UnrealScript. The answer is as follows:

To manage time, Unreal divides each second of gameplay into "Ticks". A tick is the smallest unit of time in which all actors in a level are updated. A tick typically takes between 1/100th to 1/10th of a second. The tick time is limited only by CPU power; the faster machine, the lower the tick duration is.

Some commands in UnrealScript take zero ticks to execute (i.e. they execute without any game-time passing), and others take many ticks. Functions which require game-time to pass are called "latent functions". Some examples of latent functions include "Sleep", "FinishAnim", and "MoveTo". Latent functions in UnrealScript may only be called from code within a state, not from code within a function.

While an actor is executing a latent function, that actor's state execution doesn't continue until the latent function completes. However, other actors, or the VM, may call functions within the actor. The net result is that all UnrealScript functions can be called at any time, even while latent functions are pending.

In traditional programming terms, UnrealScript acts as if each actor in a level has its own "thread" of execution. Internally, Unreal does not use Windows threads, because that would be very inefficient (Windows 95 and Windows NT do not handle thousands of simultaneous threads efficiently). Instead, UnrealScript simulates threads. This fact is transparent to UnrealScript code, but becomes very apparent when you write C++ code which interacts with UnrealScript.

All UnrealScripts execute in parallel. If there are 100 monsters walking around in a level, all 100 of those monsters' scripts are executing simultaneously and independently.

Class overview

Before beginning work with UnrealScript, it’s important to understand the high-level relationships of objects within Unreal. The architecture of Unreal is a major departure from that of most other games: Unreal is purely object-oriented (much like COM/ActiveX), in that it has a well-defined object model with support for high-level object oriented concepts such as the object graph, serialization, object lifetime, and polymorphism. Historically, most games have been designed monolithically, with their major functionality hardcoded and unexpandable at the object level, though many games, such as Doom and Quake, have proven to be very expandable at the content level. There is a major benefit to Unreal’s form of object-orientation: major new functionality and object types can be added to Unreal at runtime, and this expansion can take the form of subclassing, rather than (for example) by modifying a bunch of existing code. This form of extensibility is extremely powerful, as it encourages the Unreal community to create Unreal enhancements that all interoperate.

Object is the parent class of all objects in Unreal. All of the functions in the Object class are accessible everywhere, because everything derives from Object. Object is an abstract base class, in that it doesn’t do anything useful. All functionality is provided by subclasses, such as Texture (a texture map), TextBuffer (a chunk of text), and Class (which describes the class of other objects).

Actor (expands Object) is the parent class of all standalone game objects in Unreal. The Actor class contains all of the functionality needed for an actor to move around, interact with other actors, affect the environment, and do other useful game-related things.

Pawn (expands Actor) is the parent class of all creatures and players in Unreal which are capable of high-level AI and player controls.

Class (expands Object) is a special kind of object which describes a class of object. This may seem confusing at first: a class is an object, and a class describes certain objects. But, the concept is sound, and there are many cases where you will deal with Class objects. For example, when you spawn a new actor in UnrealScript, you can specify the new actor’s class with a Class object.

With UnrealScript, you can write code for any Object class, but 99% of the time, you will be writing code for a class derived from Actor. Most of the useful UnrealScript functionality is game-related and deals with actors.

Major elements of UnrealScript

The class declaration

Each script corresponds to exactly one class, and the script begins by declaring the class, the class’s parent, and any additional information that is relevent to the class. The simplest form is:

class MyClass expands MyParentClass

package(MyPackage);

Here I am declaring a new class named "MyClass", which inherets the functionality of "MyParentClass". Additionally, the class resides in the package named "MyPackage".

Each class inherets all of the variables, functions, and states from its parent class. It can then add new variable declarations, add new functions (or override the existing functions), add new states (or add functionality to the existing states).

The typical approach to class design in UnrealScript is to make a new class (for example a Minotaur monster) which expands an existing class that has most of the functionality you need (for example the Pawn class, the base class of all monsters). With this approach, you never need to reinvent the wheel – you can simply add the new functionality you want to customize, while keeping all of the existing functionality you don’t need to customize. This approach is especially powerful for implementing AI in Unreal, where the built-in AI system provides a tremendous amount of base functionality which you can use as building blocks for your custom creatures.

The class declaration can take several optional specifiers that affect the class:

Intrinsic: Says "this class uses behind-the-scenes C++ support". Unreal expects Intrinsic classes to contain a C++ implementation in the DLL corresponding to the class’s package. For example, if your package is named "Robots", Unreal looks in the "Robots.dll" for the C++ implementation of the intrinsic class, which is generated by the C++ IMPLEMENT_CLASS macro.

HideParent: Says "when a user is editing an object of this class in UnrealEd, don’t show any of the parent class’s properties in the editor".

Abstract: Declares the class as an "abstract base class". This prevents the user from adding actors of this class to the world in UnrealEd, because the class isn’t meaningful on its own. For example, the "Pawn
base class is abstract, while the "Brute" subclass is not abstract – you can place a Brute in the world, but you can’t place a Pawn in the world.

Guid: Associates a globally unique identifier (a 128-bit number) with the class. This Guid is currently unused, but will be relevent when native COM support is later added to Unreal.

Transient: Says "objects belonging to this class should never be saved on disk". Only useful in conjunction with certain kinds of intrinsic classes which are non-persistent by nature, such as players or windows.

ScriptConst: Says "objects of this class must be declared Const in UnrealScript", to prevent them from being changed during gameplay.

Variables

Here are some examples of instance variable declarations in UnrealScript:

var int a; // Declare an integer variable named "A".

var byte Table[64]; // Declare an array of 64 bytes named "Table".

var string[32] PlayerName; // Declare a max 32-character string.

var actor Other; // Declare a variable referencing an actor.

Variables can appear in two kinds of places in UnrealScript: instance variables, which apply to an entire object, appear immediately after the class declarations. Local variables appear within a function, and are only active while that function executes. Instance variables are declared with the "var" keyword. Local variables are declard with the "local" keyword.

Here are the basic variable types supported in UnrealScript:

•	byte: A single-byte value ranging from 0 to 255.

•	int: A 32-bit integer value.

•	bool: A boolean value: either "true" or "false".

•	float: A 32-bit floating point number.

•	string: A string of characters.

•	name: The name of an item in Unreal (such as the name of a function, state, class, etc). Names are stored as a 16-bit index into the global name table. Names correspond to simple strings of 1-31 characters. Names are not like strings: strings can be modified dynamically, but names can only take on predefined name values.

•	Enumeration: A variable that can take on one of several predefined name values. For example, the ELightType enumeration defined in the Actor script describes a dynamic light and takes on a value like LT_None, LT_Pulse, LT_Strobe, and so on.

•	Object and actor references: A variable that refers to another object or actor in the world. For example, the Pawn class has an "Enemy" actor reference that specifies which actor the pawn should be trying to attack. Object and actor references are very powerful tools, because they enable you to access the variables and functions of another actor. For example, in the Pawn script, you can write "Enemy.Damage(123)" to call your enemy’s Damage function – resulting in the enemy taking damage. Object references may also contain a special value called "None", which is the equivalent of the C "NULL" pointer: it says "this variable doesn’t refer to any object".

•	Structs: Similar to C structures, UnrealScript structs let you create new variable types that contain sub-variables. For example, two commonly-used structs are "vector", which consists of an X, Y, and Z component; and "rotator", which consists of a pitch, yaw, and roll component.

Variables may also contain additional specifiers such as "const" that further describe the variable. Actually, there are quite a lot of specifiers which you wouldn’t expect to see in a general-purpose programming language, mainly as a result of wanting UnrealScript to natively support many game- and environment- specific concepts:

•	const: Advanced. Treats the contents of the variable as a constant. In UnrealScript, you can read the value of const variables, but you can’t write to them. "Const" is only used for variables which the engine is responsible for updating, and which can’t be safely updated from UnrealScript, such as an actor’s Location (which can only be set by calling the MoveActor function).

•	input: Advanced. Makes the variable accessible to Unreal’s input system, so that input (such as button presses and joystick movements) can be directly mapped onto it. Only relevent with variables of type "byte" and "float".

•	transient: Advanced. Declares that the variable is for temporary use, and isn’t part of the object’s persistent state. Transient variables are not saved to disk. Transient variables are initialized to zero when an actor is loaded.

•	intrinsic: Advanced. Declares that the variable is loaded and saved by C++ code, rather than by UnrealScript.

•	private: The variable is private, and may only be accessed by the class's script; no other classes (including subclasses) may access it.

Arrays are declared using the following syntax:

var int MyArray[20]; // Declares an array of 20 ints.

UnrealScript supports only single-dimensional arrays, though you can simulate multidimensional arrays by carrying out the row/column math yourself.

In UnrealScript, you can make an instance variable "editable", so that users can edit the variable’s value in UnrealEd. This mechanism is responsible for the entire contents of the "Actor Properties" dialog in UnrealEd: everything you see there is simply an UnrealScript variable, which has been declared editable.

The syntax for declaring an editable variable is as follows:

var() int MyInteger; // Declare an editable integer in the default category.

var(MyCategory) bool MyBool; // Declare an editable integer in "MyCategory".

Object and actor reference variables

You can declare a variable that refers to an actor or object like this:

var actor A; // An actor reference.

var pawn P; // A reference to an actor in the Pawn class.

var texture T; // A reference to a texture object.

The variable "P" above is a reference to an actor in the Pawn class. Such a variable can refer to any actor that belongs to a subclass of Pawn. For example, P might refer to a Brute, or a Skaarj, or a Manta. It can be any kind of Pawn. However, P can never refer to a Trigger actor (because Trigger is not a subclass of Pawn).

One example of where it’s handy to have a variable refering to an actor is the Enemy variable in the Pawn class, which refers to the actor which the Pawn is trying to attack.

When you have a variable that refers to an actor, you can access that actor’s variables, and call its functions. For example:

// Declare two variables that refer to a pawns.

var pawn P, Q;

// Here is a function that makes use of P.

// It displays some information about P.

function MyFunction()

{

// Set P’s enemy to Q.

P.Enemy = Q;

// Tell P to play his running animation.

P.PlayRunning();

}

Variables that refer to actors always either refer to a valid actor (any actor that actually exists in the level), or they contain the value "None". None is equivalent to the C/C++ "NULL" pointer. However, in UnrealScript, it is safe to access variables and call functions with a "None" reference; the result is always zero.

Note that an object or actor reference "points to" another actor or object, it doesn’t "contain" an actor or object. The C equivalent of an actor reference is a pointer to an object in the AActor class (in C, you’d say an AActor*). For example, you could have two monsters in the world, Bob and Fred, who are fighting each other. Bob’s "Enemy" variable would "point to" Fred, and Fred’s "Enemy" variable would "point to" Bob.

Unlike C pointers, UnrealScript object references are always safe and infallible. It is impossible for an object reference to refer to an object that doesn’t exist or is invalid (other than the special-case "None" value). In UnrealScript, when an actor or object is destroyed, all references to it are automatically set to "None".

Class reference variables

In Unreal, classes are objects just like actors, textures, and sounds are objects. Class objects belong to the class named "class". Now, there will often be cases where you'll want to store a reference to a class object, so that you can spawn an actor belonging to that class (without knowing what the class is at compile-time). For example:

var() class C;

var actor A;

A = Spawn( C ); // Spawn an actor belonging to some arbitrary class C.

Now, be sure not to confuse the roles of a class C, and an object O belonging to class C. To give a really shaky analogy, a class is like a pepper grinder, and an object is like pepper. You can use the pepper grinder (the class) to create pepper (objects of that class) by turning the crank (calling the Spawn function)...BUT, a pepper grinder (a class) is not pepper (an object belonging to the class), so you MUST NOT TRY TO EAT IT!

When declaring variables that reference class objects, you can optionally use the special class<classlimitor> syntax to limit the variable to only containing references to classes which expand a given superclass. For example, in the declaration:

var class<actor> ActorClass;

The variable ActorClass may only reference a class that expands the "actor" class. This is useful for improving compile-time type checking. For example, the Spawn function takes a class as a parameter, but only makes sense when the given class is a subclass of Actor, and the class<classlimitor> syntax causes the compiler to enforce that requirement.

As with dynamic object casting, you can dynamically cast classes like this:

class<actor>( SomeFunctionCall() )

Enumerations

Enumerations exist in UnrealScript as a convenient way to declare variables that can contain "one of" a bunch of keywords. For example, the actor class contains the enumeration EPhysics which describes the physics which Unreal should apply to the actor. This can be set to one of the predefined values like PHYS_None, PHYS_Walking, PHYS_Falling, and so on.

Internally, enumerations are stored as byte variables. In designing UnrealScript, enumerations were not seen as a necessity, but it makes code so much easier to read to see that an actor’s physics mode is being set to "PHYS_Swimming" than (for example) "3".

Here is sample code that declares enumerations.

// Declare the EColor enumeration, with three values.

enum EColor

{

CO_Red,

CO_Green,

CO_Blue

};

// Now, declare two variables of type EColor.

var EColor ShirtColor, HatColor;

// Alternatively, you can declare variables and

// enumerations together like this:

var enum EFruit

{

FRUIT_Apple,

FRUIT_Orange,

FRUIT_Bannana

} FirstFruit, SecondFruit;

In the Unreal source, we always declare enumeration values like LT_Steady, PHYS_Falling, and so on, rather than as simply "Steady" or "Falling". This is just a matter of programming style, and is not a requirement of the language.

UnrealScript only recognizes unqualified enum tags (like FRUIT_Apple) in classes where the enumeration was defined, and in its subclasses. If you need to refer to an enumeration tag defined somewhere else in the class hierarchy, you must "qualify it":

FRUIT_Apple // If Unreal can't find this enum tag...

EFruit.FRUIT_Apple // Then qualify it like this.

Structs

An UnrealScript struct is a way of cramming a bunch of variables together into a new kind of super-variable called a struct. UnrealScript structs are just like C structs, in that they can contain any simple variables or arrays.

You can declare a struct as follows:

// A point or direction vector in 3D space.

struct Vector

{

var float X;

var float Y;

var float Z

};

Once you declare a struct, you are ready to start declaring specific variables of that struct type:

// Declare a bunch of variables of type Vector.

var Vector Position;

var Vector Destination;

To access a component of a struct, use code like the following.

function MyFunction()

{

Local Vector A, B, C;

// Add some vectors.

C = A + B;

// Add just the x components of the vectors.

C.X = A.X + B.X;

// Pass vector C to a function.

SomeFunction( C );

// Pass certain vector components to a function.

OtherFunction( A.X, C.Z );

}

You can do anything with Struct variables that you can do with other variables: you can assign variables to them, you can pass them to functions, and you can access their components.

There are several Structs defined in the Object class which are used throughout Unreal. You should become familiar with their operation, as they are fundamental building blocks of scripts:

•	Vector: A unique 3D point or vector in space, with an X, Y, and Z component.

•	Plane: Defines a unique plane in 3D space. A plane is defined by its X, Y, and Z components (which are assumed to be normalized) plus its W component, which represents the distance of the plane from the origin, along the plane’s normal (which is the shortest line from the plane to the origin).

•	Rotation: A rotation defining a unique orthogonal coordinate system. A rotation contains Pitch, Yaw, and Roll components.

•	Coords: An arbitrary coordinate system in 3D space.

•	Color: An RGB color value.

•	Region: Defines a unique convex region within a level.

Functions

In UnrealScript, you can declare new functions and write new versions of existing functions. Functions can take one or more parameters (of any variable type UnrealScript supports), and can optionally return a value. Though most functions are written directly in UnrealScript, you can also declare functions that can be called from UnrealScript, but which are implemented in C++ and reside in a DLL. The Unreal technology supports all possible combinations of function calling: The C++ engine can call script functions; script can call C++ functions; and script can call script.

Here is a simple function declaration. This function takes a vector as a parameter, and returns a floating point number:

// Function to compute the size of a vector.

function float VectorSize( vector V )

{

return sqrt( V.X * V.X + V.Y * V.Y + V.Z * V.Z );

}

The word "function" always precedes a function declaration. It is followed by the optional return type of the function (in this case, "float"), then the function name, and then the list of function parameters enclosed in parenthesis.

When a function is called, the code within the brackets is executed. Inside the function, you can declare local variables (using the "local" keyword"), and execute any UnrealScript code. The optional "return" keyword causes the function to immediately return a value.

You can pass any UnrealScript types to a function (including arrays), and a function can return any type.

By default, any local variables you declare in a function are initialized to zero.

Function calls can be recursive. For example, the following function computes the factorial of a number:

// Function to compute the factorial of a number.

function int Factorial( int Number )

{

if( Number <= 0 )

return 1;

else

return Number * Factorial( Number – 1 );

}

Some UnrealScript functions are called by the engine whenever certain events occur. For example, when an actor is touched by another actor, the engine calls its "Touch" function to tell it who is touching it. By writing a custom "Touch" function, you can take special actions as a result of the touch occuring:

// Called when something touches this actor.

function Touch( actor Other )

{

Log( "I was touched!")

Other.Message( "You touched me!" );

}

The above function illustrates several things. First of all, the function writes a message to the log file using the "Log" command (which is the equivalent of Basic’s "print" command and C’s "printf"). Second, it calls the "Message" function residing in the actor Other. Calling functions in other actors is a common action in UnrealScript, and in object-oriented languages like Java in general, because it provides a simple means for actors to communicate with each other.

Function parameter specifiers

When you normally call a function, UnrealScript makes a local copy of the parameters you pass the function. If the function modifies some of the parameters, those don’t have any effect on the variables you passed in. For example, the following program:

function int DoSomething( int x )

{

x = x * 2;

return x;

}

function int DoSomethingElse()

{

local int a, b;

a = 2;

log( "The value of a is " $ a );

b = DoSomething( a );

log( "The value of a is " $ a );

log( "The value of b is " $ b );

}

Produces the following output when DoSomethingElse is called:

The value of a is 2

The value of a is 2

The value of b is 4

In other words, the function DoSomething was futzing with a local copy of the variable "a" which was passed to it, and it was not affecting the real variable "a".

The "out" specified lets you tell a function that it should actually modify the variable that is passed to it, rather than making a local copy. This is useful, for example, if you have a function that needs to return several values to the caller. You can juse have the caller pass several variables to the function which are "out" values. For example:

// Compute the minimum and maximum components of a vector.

function VectorRange( vector V, out float Min, out float Max )

{

// Compute the minimum value.

if ( V.X<V.Y && V.X<V.Z ) Min = V.X;

else if( V.Y<V.Z ) Min = V.Y;

else Min = V.Z;

// Compute the maximum value.

if ( V.X>V.Y && V.X>V.Z ) Max = V.X;

else if( V.Y>V.Z ) Max = V.Y;

else Max = V.Z;

}

Without the "out" keyword, it would be painful to try to write functions that had to return more than one value.

With the "optional" keyword, you can make certain function parameters optional, as a convenience to the caller. For UnrealScript functions, optional parameters which the caller doesn’t specify are set to zero. For intrinsic functions, the default values of optional parameters depends on the function. For example, the Spawn function takes an optional location and rotation, which default to the spawning actor’s location and rotation.

The "coerce" keyword forces the caller’s parameters to be converted to the specified type (even if UnrealScript normally would not perform the conversion automatically). This is useful for functions that deal with strings, so that the parameters are automatically converted to strings for you.

Function overriding

"Function overriding" refers to writing a new version of a function in a subclass. For example, say you’re writing a script for a new kind of monster called a Demon. The Demon class, which you just created, expands the Pawn class. Now, when a pawn sees a player for the first time, the pawn’s "SeePlayer" function is called, so that the pawn can start attacking the player. This is a nice concept, but say you wanted to handle "SeePlayer" differently in your new Demon class. How do you do this? Function overriding is the answer.

To override a function, just cut and paste the function definition from the parent class into your new class. For example, for SeePlayer, you could add this to your Demon class.

// New Demon class version of the Touch function.

function SeePlayer( actor SeenPlayer )

{

log( "The demon saw a player" );

// Add new custom functionality here…

}

Function overriding is the key to creating new UnrealScript classes efficiently. You can create a new class that expands on an existing class. Then, all you need to do is override the functions which you want to be handled differently. This enables you to create new kinds of objects without writing gigantic amounts of code.

Several functions in UnrealScript are declared as "final". The "final" keyword (which appears immediately before the word "function") says "this function cannot be overridden by child classes". This should be used in functions which you know nobody would want to override, because it results in faster script code. For example, say you have a "VectorSize" function that computes the size of a vector. There’s absolutely no reason anyone would ever override that, so declare it as "final". On the other hand, a function like "Touch" is very context-dependent and should not be final.

Advanced function specifiers

Static: A static function acts like a C global function, in that it can be called without having a reference to an object of the class. Static functions can call other static functions, and can access the default values of variables. Static functions cannot call non-static functions and they cannot access instance variables (since they are not executed with respect to an instance of an object). Unlike languages like C++, static functions are virtual and can be overridden in child classes. This is useful in cases where you wish to call a static function in a variable class (a class not known at compile time, but referred to by a variable or an expression).

Singular: The "singular" keyword, which appears immediately before a function declaration, prevents a function from calling itself recursively. The rule is this: If a certain actor is already in the middle of a singular function, any subsequent calls to singular functions will be skipped over. This is useful in avoiding infinite-recursive bugs in some cases. For example, if you try to move an actor inside of your "Bump" function, there is a good chance that the actor will bump into another actor during its move, resulting in another call to the "Bump" function, and so on. You should be very careful in avoiding such behaviour, but if you can’t write code with complete confidence that you’re avoiding such potential recursive situations, use the "singular" keyword.

Intrinsic: You can declare UnrealScript functions as "intrinsic", which means that the function is callable from UnrealScript, but is actually written (elsewhere) in C++. For example, the Actor class contains a lot of intrinsic function definitions, such as:

intrinsic(266) final function bool Move( vector Delta );

The number inside the parenthesis after the "intrinsic" keyword corresponds to the number of the function as it was declared in C++ (using the AUTOREGISTER_INTRINSIC macro). The intrinsic function is expected to reside in the DLL named identically to the package of the class containing the UnrealScript definition.

Latent: Declares that an intrinsic function is latent, meaning that it can only be called from state code, and it may return after some game-time has passed.

Iterator: Declares that an intrinsic function is an iterator, which can be used to loop through a list of actors using the "foreach" command.

Simulated: Declares that a function may execute on the client-side when an actor is either a simulated proxy or an autonomous proxy. All functions that are both intrinsic and final are automatically simulated as well.

Operator, PreOperator, PostOperator: These keywords are for declaring a special kind of function called an operator (equivalent to C++ operators). This is how UnrealScript knows about all of the built-in operators like "+", "-", "==", and "||". I'm not going into detail on how operators work in this document, but the concept of operators is similar to C++, and you can declare new operator functions and keywords as UnrealScript functions or intrinsic functions.

Event: The "event" keyword has the same meaning to UnrealScript as "function". However, when you export a C++ header file from Unreal using "unreal -make -h", UnrealEd automatically generates a C++ -> UnrealScript calling stub for each "event". This is a much cleaner replacement for the old "PMessageParms" struct, because it automatically keeps C++ code synched up with UnrealScript functions and eliminates the possibility of passing invalid parameters to an UnrealScript function. For example, this bit of UnrealScript code:

event Touch( Actor Other )

{ ... }

Generates this piece of code in EngineClasses.h:

void Touch(class AActor* Other)

{

    FName N("Touch",FNAME_Intrinsic);

    struct {class AActor* Other; } Parms;

    Parms.Other=Other;

    ProcessEvent(N,&Parms);

}

Thus enabling you to call the UnrealScript function from C++ like this:

AActor *SomeActor, *OtherActor;

Actor->Touch(OtherActor);

Flow control

UnrealScript supports all the standard flow-control statements of C/C++/Java:

•	"For" loops let you cycle through a loop as long as some condition is met. For example:

// Example of "for" loop.

function ForExample()

{

local int i;

log( "Demonstrating the for loop" );

for( i=0; i<4; i++ )

{

log( "The value of i is " $ i );

}

log( "Completed with i=" $ i);

}

The output of this loop is:

Demonstrating the for loop

The value of i is 0

The value of i is 1

The value of i is 2

The value of i is 3

Completed with i=4

In a for loop, you must specify three expressions separated by semicolons. The first expression is for initializing a variable to its starting value. The second expression gives a condition which is checked before each iteration of the loop executes; if this expression is true, the loop executes. If it’s false, the loop terminates. The third condition gives an expression which increments the loop counter.

Though most "for" loop expressions just update a counter, you can also use "for" loops for more advanced things like traversing linked lists, by using the appropriate initialization, termination, and increment expressions.

In all of the flow control statements, you can either execute a single statement, without brackets, as follows:

for( i=0; i<4; i++ )

log( "The value of i is " $ i );

Or you can execute multiple statements, surrounded by brackets, like this:

for( i=0; i<4; i++ )

{

log( "The value of i is" );

log( i );

}

•	"Do"-"Until" loops let you cycle through a loop while some ending expression is true. Note that Unreal's do-until syntax differs from C/Java (which use do-while).

// Example of "do" loop.

function DoExample()

{

local int i;

log( "Demonstrating the do loop" );

do

{

log( "The value of i is " $ i );

i = i + 1;

} until( i == 4 );

log( "Completed with i=" $ i);

}

The output of this loop is:

Demonstrating the do loop

The value of i is 0

The value of i is 1

The value of i is 2

The value of i is 3

Completed with i=4

•	"While" loops let you cycle through a loop while some starting expression is true.

// Example of "while" loop.

function WhileExample()

{

local int i;

log( "Demonstrating the while loop" );

while( i < 4 )

{

log( "The value of i is " $ i );

i = i + 1;

}

log( "Completed with i=" $ i);

}

The output of this loop is:

Demonstrating the do loop

The value of i is 0

The value of i is 1

The value of i is 2

The value of i is 3

Completed with i=4

•	The "break" command exits out of the nearest loop ("For", "Do", or "While").

// Example of "while" loop.

function WhileExample()

{

local int i;

log( "Demonstrating break" );

for( i=0; i<10; i++ )

{

if( i == 3 )

break;

log( "The value of i is " $ i );

}

log( "Completed with i=" $ i );

}

The output of this loop is:

Demonstrating break

The value of i is 0

The value of i is 1

The value of i is 2

Completed with i=3

•	The "Goto" command goes to a label somewhere in the current function or state.

// Example of "goto".

function GotoExample()

{

log( "Starting GotoExample" );

goto Hither;

Yon:

log( "At Yon" );

goto Elsewhere;

Hither:

log( "At Hither" );

goto Yon;

Elsewhere:

log( "At Elsewhere" );

}

The output is:

Starting GotoExample

At Hither

At Yon

At Elsewhere

•	"If", "Else If", and "Else" let you execute code if certain conditions are met.

// Example of simple "if".

if( LightBrightness < 20 )

log( "My light is dim" );

// Example of "if-else".

if( LightBrightness < 20 )

log( "My light is dim" );

else

log( "My light is bright" );

// Example if "if-else if-else".

if( LightBrightness < 20 )

log( ‘My light is dim" );

else if( LightBrightness < 40 )

log( "My light is medium" );

else if( LightBrightness < 60 )

log( "My light is kinda bright" );

else

log( "My light is very bright" );

// Example if "if" with brackets.

if( LightType == LT_Steady )

{

log( "Light is steady" );

}

else

{

log( "Light is not steady" );

}

•	"Switch", "Case", "Default", and "Break" let you handle lists of conditions easily.

// Example of switch-case.

function TestSwitch()

{

// Executed one of the case statements below, based on

// the value in LightType.

select( LightType )

{

case LT_None:

log( "There is no lighting" );

break;

case LT_Steady:

log( "There is steady lighting" );

break;

case LT_Backdrop:

log( "There is backdrop lighting" );

break;

default:

log( "There is dynamic" );

break;

}

}

A "switch" statement consists of one or more "case" statements, and an optional "default" statement. After a switch statement, execution goes to the matching "case" statement if there is one; otherwise execution goes to the "default" statement; otherwise execution continues past the end of the "select" statement.

After you write code following a "case" label, you must use a "break" statement to cause execution to go past the end of the "switch" statement. If you don’t use a "break", execution "falls through" to the next "case" handler.

States

Historically, game programmers have been using the concept of states ever since games evolved past the "pong" phase. States (and what is known as "state machine programming") are a natural way of making complex object behaviour manageable. However, before UnrealScript, states have not been supported at the language level, requiring developers to create C/C++ "switch" statements based on the object’s state. Such code was difficult to write and update.

UnrealScript supports states at the language level.

In UnrealScript, each actor in the world is always in one and only one state. Its state reflects the action it wants to perform. For example, moving brushes have several states like "StandOpenTimed" and "BumpOpenTimed". Pawns have several states such as "Dying", "Attacking", and "Wandering".

In UnrealScript, you can write functions and code which exist in a particular state. These functions are only called when the actor is in that state. For example, say you’re writing a monster script, and you’re contemplating how to handle the "SeePlayer" function. When you’re wandering around, you want to attack the player you see. When you’re already attacking the player, you want to continue on uninterrupted.

The easiest way to do this is by defining several states (Wandering and Attacking), and writing a different version of "Touch" in each state. UnrealScript supports this.

Before delving deeper into states, you need to understand that there are two major benefits to states, and one complication:

•	Benefit: States provide a simple way to write state-specific functions, so that you can handle the same function in different ways, depending on what the actor is doing.

•	Benefit: With a state, you can write special "state code", using all of the regular UnrealScript commands plus several special functions known as "latent functions". A latent function is a function which executes "slowly", and may return after a certain amount of "game time" has passed. This enables you to perform time-based programming – a major benefit which neither C, C++, nor Java offer. Namely, you can write code in the same way you conceptualize it; for example, you can write a script that says the equivalent of "open this door; pause 2 seconds; play this sound effect; open that door; release that monster and have it attack the player". You can do this with simple, linear code, and the Unreal engine takes care of the details of managing the time-based execution of the code.

•	Complication: Now that you can have functions (like "Touch") overridden in multiple states as well as in child classes, you have the burden of figuring out exactly which "Touch" function is going to be called in a specific situation. UnrealScript provides rules which clearly delineate this process, but it is something you must be aware of if you create complex hierarchies of classes and states.

Here is an example of states from the TriggerLight script:

// Trigger turns the light on.

state() TriggerTurnsOn

{

function Trigger( actor Other, pawn EventInstigator )

{

Trigger = None;

Direction = 1.0;

Enable( 'Tick' );

}

}

// Trigger turns the light off.

state() TriggerTurnsOff

{

function Trigger( actor Other, pawn EventInstigator )

{

Trigger = None;

Direction = -1.0;

Enable( 'Tick' );

}

}

Here you are declaring two different states (TriggerTurnsOn and TriggerTurnsOff), and you’re writing a different version of the Trigger function in each state. Though you could pull off this implementation without states, using states makes the code far more modular and expandable: in UnrealScript, you can easily subclass an existing class, add new states, and add new functions. If you had tried to do this without states, the resulting code would be more difficult to expand later.

A state can be declared as editable, meaning that the user can set an actor’s state in UnrealEd, or not. To declare an editable state, do the following:

state() MyState

{

//...

}

To declare a non-editable state, do this:

state MyState

{

//...

}

You can also specify the automatic, or initial state that an actor should be in by using the "auto" keyword. This causes all new actors to be placed in that state when they first are activated:

auto state MyState

{

//...

}

State code

In addition to functions, a state can contain one or more labels followed by UnrealScript code. For example:

auto state MyState

{

Begin:

Log( "MyState has just begun!" );

Sleep( 2.0 );

Log( "MyState has finished sleeping" );

goto Begin;

}

The above state code prints the message "MyState has just begun!", then it pauses for two seconds, then it prints the message "MyState has finished sleeping". The interesting thing in this example is the call to the latent function "Sleep": this function call doesn’t return immediately, but returns after a certain amount of game time has passed. Latent functions can only be called from within state code, and not from within functions. Latent functions let you manage complex chains of events which include the passage of time.

All state code begins with a label definition; in the above example the label is named "Begin". The label provides a convenient entry point into the state code. You can use any label name in state code, but the "Begin" label is special: it is the default starting point for code in that state.

There are three main latent functions available to all actors:

•	Sleep( float Seconds ) pauses the state execution for a certain amount of time, and then continues.

•	FinishAnim() waits until the current animation sequence you’re playing completes, and then continues. This function makes it easy to write animation-driven scripts, scripts whose execution is governed by mesh animations. For example, most of the AI scripts are animation-driven (as opposed to time-driven), because smooth animation is a key goal of the AI system.

•	FinishInterpolation() waits for the current InterpolationPoint movement to complete, and then continues.

The Pawn class defines several important latent functions for actions such as navigating through the world and short-term movement. See the separate AI docs for descriptions of their usage.

Three intrinsic UnrealScript functions are particularly useful when writing state code:

•	The "Goto" function (similar to the C/C++/Basic goto) within a state causes the state code to continue executing at a different label.

•	The special Goto('') command within a state causes the state code execution to stop. State code execution doesn’t continue until you go to a new state, or go to a new label within the current state.

•	The "GotoState" function causes the actor to go to a new state, and optionally continue at a specified label (if you don’t specify a label, the default is the "Begin" label). You can call GotoState from within state code, and it goes to the destination immediately. You can also call GotoState from within any function in the actor, but that does not take effect immediately: it doesn’t take effect until execution returns back to the state code.

Here is an example of the state concepts discussed so far:

// This is the automatic state to execute.

auto state Idle

{

// When touched by another actor…

function Touch( actor Other )

{

log( "I was touched, so I’m going to Attacking" );

GotoState( ‘Attacking’ );

Log( "I have gone to the Attacking state" );

}

Begin:

log( "I am idle…" );

sleep( 10 );

goto ‘Begin’;

}

// Attacking state.

state Attacking

{

Begin:

Log( "I am executing the attacking state code" );

//...

}

When you run this program and then go touch the actor, you will see:

I am idle…

I am idle…

I am idle…

I was touched, so I’m going to Attacking

I have gone to the Attacking state

I am executing the attacking state code

Make sure you understand this important aspect of GotoState: When you call GotoState from within a function, it does not go to the destination immediately, rather it goes there once execution returns back to the state code.

State inheretance and scoping rules

In UnrealScript, when you subclass an existing class, your new class inherets all of the variables, functions and states from its parent class. This is well-understood.

However, the addition of the state abstraction to the UnrealScript programming model adds additional twists to the inheretance and scoping rules. The complete inheretance rules are:

•	A new class inherets all of the variables from its parent class.

•	A new class inherents all of its parent class’s non-state functions. You can override any of those inhereted non-state functions. You can add entirely new non-state functions.

•	A new class inherets all of its parent class’s states, including the functions and labels within those states. You can override any of the inhereted state functions, and you can override any of the inhereted state labels, you can add new state functions, and you can add new state labels.

Here is an example of all the overriding rules:

// Here is an example parent class.

class MyParentClass expands Actor

package(MyPackage);

// A non-state function.

function MyInstanceFunction()

{

log( "Executing MyInstanceFunction" );

}

// A state.

state MyState

{

// A state function.

function MyStateFunction()

{

Log( "Executing MyStateFunction" );

}

// The "Begin" label.

Begin:

Log("Beginning MyState");

}

// Here is an example child class.

class MyChildClass expands MyParentClass

package(MyPackage);

// Here I’m overriding a non-state function.

function MyInstanceFunction()

{

Log( "Executing MyInstanceFunction in child class" );

}

// Here I’m redeclaring MyState so that I can override MyStateFunction.

state MyState

{

// Here I’m overriding MyStateFunction.

function MyStateFunction()

{

Log( "Executing MyStateFunction" );

}

// Here I’m overriding the "Begin" label.

Begin:

Log( "Beginning MyState in MyChildClass" );

}

When you have a function that is implemented globally, in one or more states, and in one or more parent classes, you need to understand which version of the function will be called in a given context. The scoping rules, which resolves these complex situations, are:

•	If the actor is in a state, and an implementation of the function exists somewhere in that state (either in the actor’s class or in some parent class), the most-derived state version of the function is called.

•	Otherwise, the most-derived non-state version of the function is called.

In complex programming situations, you will often need to call a specific version of a function, rather than the one that’s in the current scope. To deal with these cases, UnrealScript provides the following keywords:

•	Global: Calls the most-derived global (non-state) version of the function.

•	Super: Calls the corresponding version of the function in the parent class. The function called may either be a state or non-state function depending on context.

•	Super(classname): Calls the corresponding version of the function residing in (or above) the specified class. The function called may either be a state or non-state function depending on context.

It is not valid to combine multiple calling specifiers (i.e. Super(Actor).Global.Touch).

Here are some examples of calling specifiers:

class MyClass expands Pawn

package(MyPackage);

function MyExample( actor Other )

{

Super(Pawn).Touch( Other );

Global.Touch( Other );

Super.Touch( Other );

}

As an additional example, the BeginPlay() function is called when an actor is about to enter into gameplay. The BeginPlay() function is implemented in the Actor class and it contains some important functionality that needs to be executed. Now, say you want to override BeginPlay() in your new class MyClass, to add some new functionality. To do that safely, you need to call the version of BeginPlay() in the parent class:

class MyClass expands Pawn

package(MyPackage);

function BeginPlay()

{

// Call the version of BeginPlay in the parent class (important).

Super.BeginPlay();

// Now do custom BeginPlay stuff.

//...

}

Advanced state programming

If a state doesn’t override a state of the same name in the parent class, then you can optionally use the "expands" keyword to make the state expand on an existing state in the current class. This is useful, for example, in a situatio where you have a group of similar states (such as MeleeAttacking and RangeAttacking) which have a lot of functionality in common. In this case you could declare a base Attacking state as follows:

// Base Attacking state.

state Attacking

{

// Stick base functions here...

}

// Attacking up-close.

state MeleeAttacking expands Attacking

{

// Stick specialized functions here...

}

// Attacking from a distance.

state RangeAttacking expands Attacking

{

// Stick specialized functions here...

}

A state can optionally use the "ignores" specifier to ignore functions while in a state. The syntax for this is:

// Declare a state.

state Retreating

{

// Ignore the following messages...

ignores Touch, UnTouch, MyFunction;

// Stick functions here...

}

You can tell what specific state an actor is in from its "state" variable, a variable of type "name".

It is possible for an actor to be in "no state" by using GotoState(‘’). When an actor is in "no state", only its global (non-state) functions are called.

Whever you use the GotoState command to set an actor’s state, the engine can call two special notification functions, if you have defined them: EndState() and BeginState(). EndState is called in the current state immediately before the new state is begun, and BeginState is called immediately after the new state begins. These functions provide a convenient place to do any state-specific initialization and cleanup which your state may require.

Constants

In UnrealScript, you can specify constant values of nearly all data types:

•	Integer and byte constants are specified with simple numbers, for example: 123

•	If you must specify an integer or byte constant in hexidecimal format, use i.e.: 0x123

•	Floating point constants are specified with decimal numbers like: 456.789

•	String constants must be enclosed in double quotes, for example: "MyString"

•	Name constants must be enclosed in single quotes, for example ‘MyName’

•	Vector constants contain X, Y, and Z values like this: Vect(1.0,2.0,4.0)

•	Rotation constants contant Pitch, Yaw, and Roll values like this: Rot(0x8000,0x4000,0)

•	The "None" constant refers to "no object" (or equivalantly, "no actor").

•	The "Self" constant refers to "this object" (or equivalantly, "this actor"), i.e. the object whose script is executing.

•	General object constants are specified by the object type followed by the object name in single quotes, for example: texture ‘Default’

•	EnumCount gives you the number of elements in an enumeration, for example: EnumCount(ELightType)

•	ArrayCount gives you the number of elements in an array, for example: ArrayCount(Touching)

You can use the "const" keyword to declare constants which you can later refer to by name. For example:

const LargeNumber=123456;

const PI=3.14159;

const MyName="Tim";

const Northeast=Vect(1.0,1.0,0.0);

Constants can be defined within classes or within structs.

To access a constant which was declared in another class, use the "classname.constname" syntax, for example:

Pawn.LargeNumber

Expressions

To assign a value to a variable, use "=" like this:

function Test()

{

local int i;

local string[80] s;

local vector v, q;

i = 10; // Assign a value to integer variable i.

s = "Hello!"; // Assign a value to string variable s.

v = q; // Copy value of vector q to v.

}

In UnrealScript, whenever a function or other expression requires a certain type of data (for example, an "float"), and you specify a different type of data (for example, an "int), the compiler will try to convert the value you give to the proper type. Conversions among all the numerical data types (byte, int, and float) happen automatically, without any work on your part.

UnrealScript is also able to many other built-in data types to other types, if you explicitly convert them in code. The syntax for this is:

function Test()

{

local int i;

local string[80] s;

local vector v, q;

local rotation r;

s = string(i); // Convert integer i to a string, and assign it to s.

s = string(v); // Convert vector v to a string, and assign it to s.

v = q + vector(r); // Convert rotation r to a vector, and add q.

}

Here is the complete set of non-automatic conversions you can use in UnrealScript:

•	String to Byte, Int, Float: Tries to convert a string like "123" to a value like 123. If the string doesn’t represent a value, the result is 0.

•	Byte, Int, Float, Vector, Rotation to String: Converts the number to its textual representation.

•	String to Vector, Rotation: Tries to parse the vector or rotation’s textual representation.

•	String to Bool: Converts the case-insensitive words "True" or "False" to True and False; converts any non-zero value to True; everything else is False.

•	Bool to String: Result is either "True" or "False".

•	Byte, Int, Float, Vector, Rotation to Bool: Converts nonzero values to True; zero values to False.

•	Bool to Byte, Int, Float: Converts True to 1; False to 0.

•	Name to String: Converts the name to the text equivalant.

•	Rotation to Vector: Returns a vector facing "forward" according to the rotation.

•	Vector to Rotation: Returns a rotation pitching and yawing in the direction of the vector; roll is zero.

•	Object (or Actor) to Int: Returns an integer that is guaranteed unique for that object.

•	Object (or Actor) to Bool: Returns False if the object is None; False otherwise.

•	Object (or Actor) to String: Returns a textual representation of the object.

Converting among Actor and Object classes

Just like the conversion functions above, which convert among simple datatypes, in UnrealScript you can convert actor and object references among various types. For example, all actors have a variable named "Target", which is a reference to another actor. Say you are writing a script where you need to check and see if your Target belongs to the "Pawn" actor class, and you need to do something special with your target that only makes sense when it’s a pawn -- for example, you need to call one of the Pawn functions. The actor cast operators let you do this. Here’s an example:

var actor Target;

//...

function TestActorConversions()

{

local Pawn P;

// See if my target is a Pawn.

P = Pawn(Target);

if( P != None )

{

// Target is a pawn, so set its Enemy to Self.

P.Enemy = Self;

}

else

{

// Target is not a pawn.

}

}

To perform an actor conversion, type the class name followed by the actor expression you wish to convert, in parenthesis. Such a conversion will either succeed or fail based on whether the conversion is sensible. In the above example, if your Target is referencing a Trigger object rather than a pawn, the expression Pawn(Target) will return "None", since a Trigger can’t be converted to a Pawn. However, if your Target is referencing a Brute object, the conversion will successfully return the Brute, because Brute is a subclass of Pawn.

Thus, actor conversions have two purposes: First, you can use them to see if a certain actor reference belongs to a certain class. Second, you can use them to convert an actor reference from one class to a more specific class. Note that these conversions don’t affect the actor you’re converting at all -- they just enable UnrealScript to treat the actor reference as if it were a more specific type.

Another example of conversions lies in the Inventory script. Each Inventory actor is owned by a Pawn, even though its Owner variable can refer to any Actor. So a common theme in the Inventory code is to cast Owner to a Pawn, for example:

// Called by engine when destroyed.

function Destroyed()

{

// Remove from owner's inventory.

if( Pawn(Owner)!=None )

Pawn(Owner).DeleteInventory( Self );

}

Built-in operators and their precedence

UnrealScript provides a wide variety of C/C++/Java-style operators for such operations as adding numbers together, comaring values, and incrementing variables. The complete set of operators is defined in Object.u, but here is a recap. Here are the standard operators, in order of precedence. Note that all of the C style operators have the same precedence as they do in C.

Operator	Types it applies to	Meaning
$	string	String concatenation
*=	byte, int, float, vector, rotation	Multiply and assign
/=	byte, int, float, vector, rotation	Divide and assign
+=	byte, int, float, vector	Add and assign
-=	byte, int, float, vector	Subtract and assign
||	bool	Logical or
&&	bool	Logical and
&	int	Bitwise and
|	int	Bitwise or
^	int	Bitwise exlusive or
!=	All	Compare for inequality
==	All	Compare for equality
<	byte, int, float, string	Less than
>	byte, int, float, string	Greater than
<=	byte, int, float, string	Less than or equal to
>=	byte, int, float, string	Greater than or equal to
~=	float, string	Approximate equality (within 0.0001), case-insensitive equality.
<<	int, vector	Left shift (int), Forward vector transformation (vector)
>>	int, vector	Right shift (int), Reverse vector transformation (vector)
+	byte, int, float, vector	Add
-	byte, int, float, vector	Subtract
%	float	Modulo (remainder after division)
*	byte, int, float, vector, rotation	Multiply
/	byte, int, float, vector, rotation	Divide
Dot	vector	Vector dot product
Cross	vector	Vector cross product
**	float	Exponentiation
The above table lists the operators in order of precedence (with operators of the same precedence grouped together). When you type in a complex expression like "1*2+3*4", UnrealScript automatically groups the operators by precedence. Since multiplication has a higher precedence than addition, the expression is evaluated as "(1*2)+(3*4)".

The "&&" (logical and) and "||" (logical or) operators are short-circuited: if the result of the expression can be determined solely from the first expression (for example, if the first argument of && is false), the second expression is not evaluated.

In addition, UnrealScript supports the following unary operators:

•	! (bool) Logical not.

•	- (int, float) negation.

•	~ (int) bitwise negation.

•	++, -- Decrement (either before or after a variable).

General purpose functions

Integer functions:

•	int Rand( int Max ); Returns a random number from 0 to Max-1.

•	int Min( int A, int B ); Returns the minimum of the two numbers.

•	int Max( int A, int B ); Returns the maximum of the two numbers.

•	int Clamp( int V, int A, int B ); Returns the first number clamped to the interval from A to B.

Floating point functions:

•	float Abs( float A ); Returns the absolute value of the number.

•	float Sin( float A ); Returns the sine of the number expressed in radius.

•	float Cos( float A ); Returns the cosine of the number expressed in radians.

•	float Tan( float A ); Returns the tangent of the number expressed in radians.

•	float Atan( float A ); Returns the inverse tangent of the number expressed in radians.

•	float Exp( float A ); Returns the constant "e" raised to the power of A.

•	float Loge( float A ); Returns the log (to the base "e") of A.

•	float Sqrt( float A ); Returns the square root of A.

•	float Square( float A ); Returns the square of A = A*A.

•	float FRand(); Returns a random number from 0.0 to 1.0.

•	float FMin( float A, float B ); Returns the minimum of two numbers.

•	float FMax( float A, float B ); Returns the maximum of two numbers.

•	float FClamp( float V, float A, float B ); Returns the first number clamped to the interval from A to B.

•	float Lerp( float Alpha, float A, float B ); Returns the linear interpolation between A and B.

•	float Smerp( float Alpha, float A, float B ); Returns an Alpha-smooth nonlinear interpolation between A and B.

Unreal’s string functions have a distinct Basic look and feel:

•	int Len( coerce string[255] S ); Returns the length of a string.

•	int InStr( coerce string[255] S, coerce string[255] t); Returns the offset into the first string of the second string if it exists, or -1 if not.

•	string[255] Mid ( coerce string[255] S, int i, optional int j ); Returns the middle part of the string S, starting and character i and including j characters (or all of them if j is not specified).

•	string[255] Left ( coerce string[255] S, int i ); Returns the i leftmost characters of s.

•	string[255] Right ( coerce string[255] S, int i ); Returns the i rightmost characters of s.

•	string[255] Caps ( coerce string[255] S ); Returns S converted to uppercase.

Vector functions:

•	float Size( vector A ); Returns the euclidean size of the vector (the square root of the sum of the components squared).

•	vector Normal( vector A ); Returns a vector of size 1.0, facing in the direction of the specified vector.

•	Invert ( out vector X, out vector Y, out vector Z ); Inverts a coordinate system specified by three axis vectors.

•	vector VRand ( ); Returns a uniformly distributed random vector.

•	float Dist ( vector A, vector B ); Returns the euclidean distance between two points.

•	vector MirrorVectorByNormal( vector Vect, vector Normal ); Mirrors a vector about a specified normal vector.

ForEach and iterator functions

UnrealScript’s "foreach" command makes it easy to deal with large groups of actors, for example all of the actors in a level, or all of the actors within a certain distance of another actor. "foreach" works in conjunction with a special kind of function called an "iterator" function whose purpose is to iterate through a list of actors.

Here is a simple example of foreach:

// Display a list of all lights in the level.

function Something()

{

local actor A;

// Go through all actors in the level.

log( "Lights:" );

foreach AllActors( class ‘Actor’, A )

{

if( A.LightType != LT_None )

log( A );

}

}

The first parameter in all "foreach" commands is a constant class, which specifies what kinds of actors to search. You can use this to limit the search to, for example, all Pawns only.

The second parameter in all "foreach" commands is a variable which is assigned an actor on each iteration through the "foreach" loop.

Here are all of the iterator functions which work with "foreach".

AllActors ( class BaseClass, out actor Actor, optional name MatchTag ); Iterates through all actors in the level. If you specify an optional MatchTag, only includes actors which have a "Tag" variable matching the tag you specified.

ChildActors( class BaseClass, out actor Actor ); Iterates through all actors owned by this actor.

BasedActors( class BaseClass, out actor Actor ); Iterates throgh all actors which are standing on this actor.

TouchingActors( class BaseClass, out actor Actor ); Iterates through all actors which are touching (interpenetrating) this actor.

TraceActors( class BaseClass, out actor Actor, out vector HitLoc, out vector HitNorm, vector End, optional vector Start, optional vector Extent ); Iterates through all actors which touch a line traced from the Start point to the End point, using a box of collision extent Extent. On each iteration, HitLoc is set to the hit location, and HitNorm is set to an outward-pointing hit normal.

RadiusActors( class BaseClass, out actor Actor, float Radius, optional vector Loc ); Iterates through all actors within a specified radius of the specified location (or if none is specified, this actor’s location).

VisibleActors( class BaseClass, out actor Actor, optional float Radius, optional vector Loc ); Iterates through a list of all actors who are visible to the specified location (or if no location is specified, this actor’s location).

Advanced language features

•	Accessing default values of variables: UnrealEd enables level designers to edit the "default" variables of an object's class. When a new actor is spawned of the class, all of its variables are initialized to those defaults. Sometimes, it’s useful to manually reset a variable to its default value. For example, when the player drops an inventory item, the inventory code needs to reset some of the actor’s values to its defaults. In UnrealScript, you can access the default variables of a class with the "Default." keyword. For example:

var() float Health, Stamina;

//...

// Reset some variables to their defaults.

function ResetToDefaults()

{

// Reset health, and stamina.

Health = Default.Health;

Stamina = Default.Stamina;

}

•	Accessing default values of variables in a variable class: If you have a class reference (a variable of "class" or "class<classlimitor>" type), you can access the default properties of the class it references, without having an object of that class. This syntax works with any expression that evaluates to class type.

var class C;

var class<Pawn> PC;

Health = class'Spotlight'.default.LightBrightness; // Access the default value of LightBrightness in the Spotlight class.

Health = PC.default.Health; // Access the default value of Health in a variable class identified by PC.

Health = class<Pawn>(C).default.Health; // Access the default value of Health in a casted class expression.

•	Accessing static functions in a variable class: Static functions in a variable class may be called using the following syntax.

var class C;

var class<Pawn> PC;

class'SkaarjTrooper'.static.SomeFunction(); // Call a static function in a specific class.

PC.static.SomeFunction(); // Call a static function in a variable class.

class<Pawn>(C).static.SomeFunction(); // Call a static function in a casted class expression.

UnrealScript binary compatibility issues

UnrealScript is designed so that classes in package files may evolve over time without breaking binary compatibility. Here, binary compatibility means "dependent binary files may be loaded and linked without error"; whether your modified code functions as designed is a separate issue. on the Specifically, the kinds of modifications when may be made safely are as follows:

•	The .uc script files in a package may be recompiled without breaking binary compatibility.

•	Adding new classes to a package.

•	Adding new functions to a class.

•	Adding new states to a class.

•	Adding new variables to a class.

•	Removing private variables from a class.

Other transformations are generally unsafe, including (but not limited to):

•	Adding new members to a struct.

•	Removing a class from a package.

•	Changing the type of any variable, function parameter, or return value.

•	Changing the number of parameters in a function.

Technical notes

Garbage collection: All objects and actors in Unreal are garbage-collected using a tree-following garbage collector similar to that of the Java VM. The Unreal garbage collector uses the UObject class’s serialization functionality to recursively figure out which other objects are referenced by each active object. As a result, object need not be explicitly deleted, because the garbage collector will eventually hunt them down when they become unreferenced. This approach has the side-effect of latent deletion of unreferenced objects; however it is far more efficient than reference counting in the case of infrequent deletion.

Unreal COM integration: Unreal’s base UObject class derives from IUnknown in anticipation of making Unreal interoperable with the Component Object Model without requiring binary changes to objects. However, Unreal is not COM-aware at the moment and the benefits of integrating Unreal with COM are not yet clear, so this project is on indefinite hold.

UnrealScript is bytecode based: UnrealScript code is compiled into a series of bytecodes similar to p-code or the Java bytecodes. This makes UnrealScript platform-neutral; this porting the client and server components of Unreal to other platforms, i.e. the Macintosh or Unix, is straightforward, and all versions can interoperate easily by executing the same scripts.

Unreal as a Virtual Machine: The Unreal engine can be regarded as a virtual machine for 3D gaming in the same way that the Java language and the built-in Java class hierarchy define a virtual machine for Web page scripting. The Unreal virtual machine is inherently portable (due to splitting out all platform-dependent code in separate modules) and expandable (due to the expandable class hierarchy). However, at this time, there are no plans to document the Unreal VM to the extent necessary for others to create independent but compatible implementations.

The UnrealScript compiler is two-pass: Unlike C++, UnrealScript is compiled in two distinct passes. In the first pass, variable, state and function definitions are parsed and remembered. In the second pass, the script code is compiled to byte codes. This enables complex script hierarchies with circular dependencies to be completely compiled and linked in two passes, without a separate link phase.

Persistent actor state: It is important to note that in Unreal, because the user can save the game at any time, the state of all actors, including their script execution state, can be saved at any time where all actors are at their lowest possible stack level. This persistence requirement is the reason behind the limitation that latent functions may only be called from state code: state code executes at the lowest possible stack level, and thus can be serialized easily. Function code may exist at any stack level, and could have (for example) C++ intrinsic functions below it on the stack, which is clearly not a situation which one could save on disk and later restore.

Unrealfiles: Unrealfiles are Unreal’s native binary file format. Unrealfiles contain an index, serialized dump of the objects in a particular Unreal package. Unrealfiles are similar to DLL’s, in that they can contain references to other objects stored in other Unrealfiles. This approach makes it possible to distribute Unreal content in predefined "packages" on the Internet, in order to reduce download time (by never downloading a particular package more than once).

Why UnrealScript does not support static variables: While C++ supports static (per class-process) variables for good reasons true to the language's low-level roots, and Java support static variables for reasons that appear to be not well thought out, such variables do not have a place in UnrealScript because of ambiguities over their scope with respect to serialization, derivation, and multiple levels: should static variables have "global" semantics, meaning that all static variables in all active Unreal levels have the same value? Should they be per package? Should they be per level? If so, how are they serialized -- with the class in its .u file, or with the level in its .unr file? Are they unique per base class, or do derived versions of classes have their own values of static variables? In UnrealScript, we sidestep the problem by not defining static variables as a language feature, and leaving it up to programmers to manage static-like and global-like variables by creating classes to contain them and exposing them in actual objects. If you want to have variables that are accessible per-level, you can create a new class to contain those variables and assure they are serialized with the level. This way, there is no ambiguity. For examples of classes that serve this kind of purpose, see LevelInfo and GameInfo.

UnrealScript programming strategy

Here I want to cover a few topics on how to write UnrealScript code effectively, and take advantage of UnrealScript’s strengths while avoiding the pitfalls.

•	UnrealScript is a slow language compared to C/C++. A typical C++ program runs at about 50 million base language instructions per second, while UnrealScript runs at about 2.5 million - a 20X performance hit. The programming philosophy behind all of our own script writing is this: Write scripts that are almost always idle. In other words, use UnrealScript only to handle the "interesting" events that you want to customize, not the rote tasks, like basic movement, which Unreal’s physics code can handle for you. For example, when writing a projectile script, you typically write a HitWall(), Bounce(), and Touch() function describing what to do when key events happen. Thus 95% of the time, your projectile script isn’t executing any code, and is just waiting for the physics code to notify it of an event. This is inherently very efficient. In our typical level, even though UnrealScript is comparably much slower than C++, UnrealScript execution time averages 5-10% of CPU time.

•	Exploit latent functions (like FinishAnim and Sleep) as much as possible. By basing the flow of your script execution on them, you are creating animation-driven or time-driven code, which is fairy efficient in UnrealScript.

•	Keep an eye on the Unreal log while you’re testing your scripts. The UnrealScript runtime often generates useful warnings in the log that notify you of nonfatal problems that are occuring.

•	Be wary of code that can cause infinite recursion. For example, the "Move" command moves the actor and calls your Bump() function if you hit something. Therefore, if you use a Move command within a Bump function, you run the risk of recursing forever. Be careful. Infinite recursion and infinite looping are the two error conditions which UnrealScript doesn’t handle gracefully.

•	Spawning and destroying actors are fairly expensive operations on the server side, and are even more expensive in network games, because spawns and destroys take up network bandwidth. Use them reasonably, and regard actors as "heavy weight" objects. For example, do not try to create a particle system by spawning 100 unique actors and sending them off on different trajectories using the physics code. That will be sloooow.

•	Exploit UnrealScript’s object-oriented capabilities as much as possible. Creating new functionality by overriding existing functions and states leads to clean code that is easy to modify and easy to integrate with other peoples’ work. Avoid using traditional C techniques, like doing a switch() statement based on the class of an actor or the state, because code like this tends to break as you add new classes and modify things.

Topics to be documented later, maybe

Unreal specific functions

Explain probes, Disable, Enable

Debugging

Logging

Assert

Object related

Animation

Actor related

Spawn

Destroy, describe latency issues

String

Explain concatenation operator

Physics

AI

Inventory

Preprocessor

#exec

#alwaysexec

Mesh commands

Texture commands

Sound commands

Licensee dev / distribution models

Whether or not to retain binary compatibility with Unreal/UnrealEd


User Interface Guide

by Jon Renner

Toolbar Commands:

1. Normal Camera View  2. Rotate Brush 3. Scale 4. Snap Scale Brush 5. Select All 6. Select None 7. Replace Selected Brushes 8. Undo 9. Pan Textures 10. Change Drawing Region to Selected Actors 11. Hide Selected Actors 12. Help (Not Functioning) 13. Toggle Grid 14. Toggle Rotation Grid 15. Change Speed 16. Vertex Snap 17. Change Drawing Region to Z 18. Turn Drawing Region Off 19. Rotate Textures 20. Redo	21. Replace Selected Non-Brush Actors 22. Invert Selection 23. Select Actors Inside Brush 24. Select All Polygons 25. Constricted Scale 26. Shear Brush 27. Zoom 28. Add Brush To World 29. Subtract Brush From World 30. Intersect 31. Desect 32. Add Special Brush 33. Add Moveable Brush 34. Build Cube 35. Build Sphere 36. Build Cylinder 37. Build Cone 38. Build Stairs 39. Build Spiral Stairs 40. Build Curved Stairs 41. Build Sheet


Using Grids

Grid Mode	(Toggle)

When grid mode is on, the brush is snapped to grid points as you move it.  This is extraordinarily useful because it is almost impossible to align objects exactly without the use of the grid.  Turn it off only when you need it off for a very specific purpose.

You can change the grid mode in two ways: Either by pulling down the “Grid” combo box on the toolbar, or by right-clicking on the toolchest’s grid icon.

Powers of two

The grid’s default settings are all powers of two.  This may seem confusing for non-mathematicians at first, but grid settings of 1, 2, 4, 8, 16, 32… are far more useful when editing than the traditional sizes of 1, 2, 5, 10, 20, 50, 100…

The reason for this is due to the fact that the brush’s pivot point is usually in the center of the brush.  Because of this, you’ll often need to cut the grid value in half in order to align some object with the side of a brush.  If traditional grid settings were used, you would be in trouble when you had to change the grid setting from 5 down to 2.5 because fractional values aren’t supported.

With powers of two, you can always set the grid value in half by choosing the next lower power of two, and you can always double a grid size easily.

Grid Size

The grid dialog enables you to set the grid size.  You can either set it to one of the predefined values, set it to a custom value, or set the grid sizes differently for the X, Y, and Z axes independently.  When setting a custom grid size, a value of zero prevents the brush from being grid-snapped in that dimension.

Vertex Snap Distance

This has nothing to do with the grid.  This item controls the maximum distance that the brush’s pivot point may be moved in order to snap it to an existing point in the world.  This has effect when the “Snap Vertices” toolbar button is on.

Notes

·	When you’re moving brushes around, you’ll often want to select a brush’s pivot point (by clicking on one of the rectangular knobs at the brush’s vertices).  When you left-click on a pivot, the pivot is simply selected.  When you right-click on a pivot, the pivot is both selected and snapped to the grid.

Copyright 1995 Epic MegaGames, Inc.


Using Rotational Grids

Rotational Grid Mode	(Toggle)

Use the Rotational Grid for precisely aligning brushes that must be rotated.  This option is on when you start UnrealEd, it’s recommended to keep it on unless you have a very precise reason to turn it off.

Right-click on the Rotational Grid icon to bring up a dialog of rotational grid properties.  This enables you to customize the grid’s granularity.

The rotational grid works with powers of two, so it can’t be used to precisely align triangles, hexagons, or other oddly-shaped brushes.  In general, these items can never be aligned exactly, so it’s best to use CSG operations which don’t require precise alignment.


Vertex Editing

Vertex Editing, Locking, and that Cross - by Jon Renner

Vertex Editing:

Click on the vertex of your building brush you wish to edit until the red cross appears over it and then use Alt+Left Click&Drag to move the vertex.

Locking for Constricted Scaling:

Select a vertex along the side you do not wish to move. and use the constricted scaling to move a the non-locked sides.

The Cross also acts as a pivot point for rotation and can put emphasis on a certain side during scaling.


Zones

Unreal Zones

Tim Sweeney
Epic MegaGames, Inc.
tim@epicgames.com
http://www.epicgames.com/

Audience: Level Designers.

The concept of zones

Unreal levels can be huge; many of our game levels are pushing 20,000 world polygons. At any time, the player only sees a tiny fraction of those 20,000 polygons, typically 100-200 polygons. The engine spends a significant amount of CPU time figuring out which 200 polygons, out of a potential 20,000, are visible in each scene. Unreal employs several techniques to speed up this "visible surface determination" process. Most of these techniques are automatic, requiring no designer intervention. However, one of the most powerful techniques, zoning, requires level designers to manually place invisible polygons called "zone portals" in their levels. Zones greatly accelerate the engine's visibility calculations, and they also enable designers to create many special effects that are specific to a region of space, such as ambient lighting or modified gravity.

A zone is an non-convex interior region of connected 3D space, for example a room, or a group of several complex, interconnected rooms.

By dividing your map up into zones, you gain several benefits:

•	Speed. A well-zoned level typically speeds up the engine's "visible surface determination" process by over 100% in a complex map, compared to an unzoned level.

•	Ambient lighting. Each zone can have its own ambient lighting value, which is added to the regular lighting on each surface. Ambient lights are very useful for outdoors areas, where pure black shadows are unnatural, as well as in diffuse environments where one would not expect dark shadows.

•	Reverberation. Each zone can have its own aural reverberation properties; see the audio document for more information.

•	Zone-based physics properties, such as friction and gravity.

•	Water.

Seeing zones

UnrealEd has a special mode that enables you to see your level's zones graphically, which each zone rendered in a distinct color. In UnrealEd, in the 3D viewport's menu, select "Zone/Portal view". You can also see this in the game by typing "RMODE 2" at the console.

In UnrealEd, zone portals are normally visible, and you normally can't see through them. To hide them, press the joystick button in the viewport, which turns on realtime updating of the viewport. You should only use this for previewing your architecture, as this realtime updating slows down the rest of UnrealEd's user interface.

Partitioning a level into zones

Level designers can partition their levels into zones by using special kinds of brushes, zone portals, to seal up regions of their maps and make them "water tight".

There are two tools in UnrealEd that you need to use to create zone portals:

•	The "sheet brush" tool. This is represented by the bottom brush builder icon on the toolbar, which lets you build a flat square polygon. You need to build zone portal polygons using this tool; you need to create polygons that are big enough to block the passages you are sealing up.

•	The "add special brush" tool. This is represented by the solid green square icon on the toolbar, below the "add" and "subtract" buttons, which enables you to add a polygon to the world with special properties to it. When you click on the "add special brush" tool, a little dialog box comes up with several pull-down options. Choose the "Zone Portal" pulldown option. Then position your sheet brush and click "add" when you're ready to add the portal.

To zone your map, first you add a bunch of portal polygons (using the "sheet brush" tool to build them, and the "add special brush" tool to add them). Next, bring up the "rebuilder" dialog and rebuild you map. The rebuilder will go through your map and detect regions of space which are sealed up "water-tight" and assign a unique zone to each region. You can go into the "Zone/Portal" view to verify, graphically, that your level is properly zoned.

If, in Zone/Portal view, you see that the engine hasn't recognized your zones, you have probably not made the portals "water tight". You need to add in enough portals that the separate zones are completely sealed-off from each other.

If, in the game, you see "hall of mirror" effects where you placed portals, make sure your portals completely seal up the regions of space they separate. If you have a portal that only partially fills up a passageway, you might see through it into nothingness.

Where to place zone portals

For special effects zones like water zones you will, of course, place the portals wherever you need the effect.

For zones whose purpose is only to speed up the engine, your goal is to divide your level up into zones while introducing portals whose overall area is as small as possible. The smaller the portals, the less work the engine must do to process the portals. Therefore, we place our portals in passageways which naturally separate large areas, such as doorways and hallways. This approach causes the level to be divided up well, without adding too much portal area.

There is no benefit (and often a performance penalty) to placing portals in the middle of large rooms. These huge portals usually eat up more CPU time being processed than they save. Stick portals in doorways, hallways, and other narrow passages.

Adding ZoneInfo actors to specify zone properties

If you want to assign individual properties to a zone, such as water, ambient lighting, or reverb, you need to add a "ZoneInfo" actor to the zone. You only need to do this if you want to assign custom properties to the zone; if all you want it the speed advantage of portalization, you don't need to add ZoneInfo's.

In the class browser, expand the "Info" class and you'll see "ZoneInfo" right there. You can add the ZoneInfo actor anywhere in your zone; as long as it's in empty space and there aren't more than one ZoneInfo's in your zone, the ZoneInfo will work. For the engine to recognize your ZoneInfo actor, you need to rebuild your map again.

See the ZoneInfo property sheet for a complete list of the ZoneInfo properties. There are many cool adjustable parameters, such as friction, gravity, ambient lighting, pain, water, etc.

Water and translucent zone portals

To create a water zone, just set the ZoneInfo's bWaterZone variable to True. The Unreal physics code (in Pawn.uc and PlayerPawn.uc) automatically recognizes these water zones and transitions between walking and swimming physics modes.

To make transparent water, just select the zone portal's surface in UnrealEd, bring up the "Surface Properties" and turn its "Translucent" option on.

Caveats

•	A level can only have 64 zones. If you create more than 64 zones, the engine will merge some zones together, causing a loss of performance. This limit might be extended in the future.