This tutorial is intended for people who have basic
knowledge of mapping for Unreal Tournament 2003, and
who are already familiar with the basics of bot
pathing. If your bots are all standing in the corners
and ignoring everyone, then this tutorial is not for
you. If your bots are moving around and fighting, but
just not giving it their all, then read on.
To be specific, I assume that you know your way around
UnrealEd 3.0, that you can find your way around the
class browser, place actors in your level, and that you
know how to lay out PathNodes. Nearly all the actors
discussed in this tutorial can be found under NavigationPoint.
Some game elements such as JumpPads, Lifts and Doors are
covered in this tutorial strictly from a pathing perspective.
I assume that you can set these up, or can find tutorials
specific to these topics. I may point out that a JumpPad
should be accompanied by some sort of emitter (for example),
but I will not provide details here as to how to set up the
emitter.
One of the most important things you can do to help
out your bots is to plan ahead. Bots prefer wide paths
and they play better when you give them lots of choices.
If you are working on a capture the flag (CTF) map, then
you'll need to give the bots (and human players) several
routes to attack the flag. Bots will tend to take the
shortest route when running to the flag, but don't worry.
Later in this tutorial, we'll learn to set up AssaultPaths
so that the bots can coordinate their attacks among
multiple routes.
Another aspect of planning your routes is to keep in mind
that while players will readily translocate to grab a
favorite weapon, bots may consider this too cumbersome.
Bots translocate much better in ut2003 than they did in UT,
but they still associate a small extra cost with the
action, and need to be sufficiently bribed to perform the
maneuver. Adequate bribes include: a nice powerup (supershield,
etc); a shorter path to a flag, bomb spawn, or bomb gate;
or a shortcut to a defense point if this is a base-oriented
game like BR or CTF.
A bot's main goal in life is to find interesting things
and then kill you with them. Make sure this isn't all
available in one spot. If you pile up your weapons, health
packs, etc. in one location, that's where the bots will stay.
They aren't very good at actually hunting down players. They
will wander around and attack you when they see you. Keep
this in mind when you are placing your items on your map.
Distribute your items in such a way as to keep the bots moving
and not focused on one particular area. If an area isn't
worth any pickups or game objectives, then it's probably not
worth having on your map.
Another trick for item placement is to put weapons and ammo
along the normal routes of travel, and put more powerful items
(redeemer, udamage, wildcard) in harder to reach places. By
putting lesser weapons and ammo in your "running lanes", you
encourage your bots to stay focused on the game objectives,
rather than on finding a weapon. This is especially important
in deathmatch.
Unreal Tournament 2003 has a nice feature that lets mappers
recommend the number of bots that will join in on their maps.
Determine what you will use for this number while you are
still designing your level. Decide how often you want the
bots to encounter players (and each other), and keep this number
in mind as you are balancing weapons, ammo, etc.
If you don't already know this, be sure to view your paths
while designing. Right click on the title bar in the 3D view of the editor,
and select View->Show Paths. Your paths will show up as colored
lines. The UDN (http://udn.epicgames.com/Two/NavigationAI)
explains them thusly:
- White - very wide path, which large NPCs can use (large is
defined by MAXCOMMONRADIUS in UnPath.h, with a default value of 120).
- Green - wide path, which moderately large NPCs can use
(defined by COMMONRADIUS, with a default value of 72).
- Blue - narrow path, useable by smaller NPCs.
- Purple - path using a lift or teleporter.
- Light Purple - path using a ladder.
- Yellow - forced path. A path between two NavigationPoints can be
forced, if no connection is automatically made, by putting the name
of the destination NavigationPoint in the ForcedPaths[] array of the
source NavigationPoint (in the NavigationPoint properties sheet).
- Red - proscribed path. A path between two NavigationPoints can
be proscribed (forbidden) by putting the name of the destination
NavigationPoint in the ProscribedPaths[] array of the source
NavigationPoint (in the NavigationPoint properties sheet).
The most important thing to know about the paths is that you want
to keep them white if you can. Bots prefer white paths so they have
room to dodge and strafe. In some circumstances, bots will never follow
blue or green paths if there are white paths available. This means
keep your hallways and walkways wide, and keep your paths generally
down the center. In UT, the bots tended to walk right on those lines,
but in ut2003 they seem to stray a little more. On open
terrain, lay out your paths like a web so that there are no areas that
the bots can get stuck.
If you read nothing else in this tutorial, read this! As you are
building your paths, periodically run the "Review Paths" option from the
Tools menu. When you run it, you'll see a progress bar with the heading
"Reviewing Paths". If it has no errors or warnings to report, then the
bar just disappears and that's it. Otherwise, a "Map Check" box will
appear with a list of actors and warning messages. You can double click
on any line to be taken to that actor in the 3D view. (You may have to
click in the 3D view to have it jump to the right actor).
These messages not only let you know about certain errors, but they also
give you suggestions as to where JumpSpots (see below) can be added to
improve flow. Other common warnings include unreachable inventory spots
and paths that are too long. Here's a rundown of some of the common
messages, what they mean, and what to do about them:
- No navigation point associated with this mover! If your mover
is not a lift or a door, then set it's AI->bNoAIRelevance property to
true. If your mover is a door or a lift see the appropriate section
below.
- Cannot reach XXX from this node! Generally XXX is some game
objective, like a flag, bombgate, etc. Make sure that there is a path
from the indicated actor to the objective. Usually, this is a pathnode
or some ammo that got hidden from the rest of the pathways, so just add
a node or two so everything's connected.
- Should be JumpDest for PathNodeXXX! A very common message.
Generally, this shows up when you can get down from the indicated
actor to PathNodeXXX, but not back up. It is sometimes a pain, but
your bots will work harder if you fix all of these. Also, if your map is
played with the lowgrav mutator, the bots will be able to navigate to
these locations (if you fix them). Place a JumpSpot on top of the
indicated actor and note its object->name property. Next, go to
PathNodeXXX and put the JumpSpot's name in the ForcedPaths[]
array (under NavigationPoint in the properties). Then, delete the
indicated actor.
- Only X PlayerStarts in this level If your map will be played
with more than X players, add more starts!
- Path to PathNodeXXX is very long - add a pathnode in between.
The solution is in the message. A good reason to do this is that bots
will not make certain AI decisions while they are between nodes. A long
path can significantly slow a bot's reaction time if it needs to turn
around and chase the flag carrier (for example).
- JumpDest has no forced paths to it. A JumpSpot is a
destination for a jump. PathNodes must be placed where the jump will
start, and the JumpSpot's object->name property must appear in the
PathNodes' ForcedPaths[] array.
- No forced destination for this jumppad! The opposite of the
previous problem. JumpPads are the source of a jump, and need to
specify the name of the PathNode they will jump TO in the ForcedPaths[]
array of the JumpPad.
- Navigation point not on valid base, or too close to steep slope
Usually indicates a pathnode that got buried under the floor or terrain,
or is on a hill that is two steep to walk on. Move the pathnode onto
more level ground.
- No paths from XXX A lonely pathnode. Connect it up to the
others and it will be happy.
Epic places some tools at your disposal for debugging bots. These are
used in-game to follow the bots around and gain some insight into what
they're "thinking". If you're having problems with your map, these tools
are invaluable for finding trouble spots and testing remedies. Here's
the first technique:
- Start up a single player game with a full compliment of bots
- At the console, suicide so the bots won't come after you or, if you
have the latest patch, join the game as a spectator.
- At the console, use the command: ShowDebug to display information about
the current player (initially it will show details about you)
- Also at the console, use the command Viewclass pawn to toggle among the
bots. You will follow them around, see the paths they are following and
a whole bunch out output to show what they're "thinking"
- If the bot you're following dies, your view will bump to another bot.
Another tool for debugging bots is the RememberSpot. This allows you to
see the shortest path between any two points in a level. With this
technique, you do not need bots in the level. To use this, go to a place
in your level that you have questions about, and type RememberSpot at the
console. You'll also need to have the debugging output on (ShowDebug).
Now, as you run around the level, you'll see the shortest path back to your
remembered spot continuously updated by tracing through the path network.
This should give you insight as to where you need to add pathnodes to get
the bots to travel more quickly.
In a recent tutorial,
Epic has revealed even more useful console commands:
- ReviewJumpSpots. This command spawns a bot that will attempt different
types of jumps to every jumpspot in your level, and log the results. If your bots
are failing to make accurate translocator throws, you can use the TranslocZOffset property
to adjust their aim. See the Advanced JumpSpots section for further details.
- ShowAI. Less output than ShowDebug
- ViewBot. Pretty much the same as Viewclass pawn, but easier to remember.
- ViewFlag. View the flag carrier.
- SoakBots. Bots will complain (and pause the game) when they encounter an error.
SoakBots is a useful tool that deserves a bit of additional explanation.
Turn this on at the start of your match, and play normally. If a bot gets
stuck, or encounters any sort of error, the game will freeze, and you will
be able to see the error, the AI state of the bot, etc. Once you have
reviewed the situation, you can unpause the game by hitting ESC, and then
pushing the "Continue" button. If the bot is in serious trouble, it may
holler again, in which case you can either kill the bot, or quit and go
fix your map. Other than forfeiting, I have not found a way to turn
soaking off once it's been activated in a match.
The next section deals with specific pathing situations. For each one,
I provide a basic explanation of how it works along with some tips on
advanced use and also how these actors can effect the flow of a map
(for better or worse).
Don't confuse these with JumpPads. JumpPads give a player a "boost" to
another location, and effect humans as well as bots. JumpSpots are just
for bots. They tell bots "here is a good place to jump." Most of the
time, you will not need to change the JumpSpot's properties. Bots will
figure out the best kind of jump to make, whether it is translocator,
shield jump, double jump or even dodge-jump. Here's how to set one up:
- Place the jumpspot where you want the bots to jump TO.
- If there aren't already some available, place pathnodes where you
want the bots to jump FROM. You can have more than one, but there is a
limit of 8 paths through the JumpSpot.
- For each pathnode you want the bots to potentially jump from, place
the JumpSpot's object->name property (NOT its tag) in the ForcedPaths[]
array of the PathNode.
- Build paths and you should see a yellow line from each PathNode to
the JumpSpot.
It is not necessary to force a path FROM a jumpspot, but not forbidden
either. If the spot is very high up, you will need a way for the bots to
get back down. Placing a JumpSpot on the ground and forcing a path from
your tower (or whatever) is a good technique to get bots to translocate
down. Remember, if you don't path a way down, the bots won't bother to
go up.
Another important consideration is using JumpSpots for speed. Bots in
ut2003/2004 do translocate ahead when running to flags or bombs, but they are
still not as savvy as experienced human players. You can improve this by
paying attention during play-testing. In objective-based games, try to
outrun the bots. If you used some long translocator throws, try putting
in some jumpspots so that the bots will make the same throws. Try
outrunning them again. After a while, you'll get a feel for where it
works and where it doesn't, but don't go overboard as too many
JumpSpots can slow down the AI. Judiciously applied, this technique can
make your bots quicker and more aggressive.
Finally, this may seem obvious to some, but it is often overlooked. Make
sure bots can reach all the areas of your map. Put JumpSpots on all the
high places that players can reach, and make sure the routes are pathed.
Areas that aren't pathed are virtually invisible to bots, and can be
exploited by knowledgeable players. If you can translocate onto a
building or cliff, make sure the bots can get up there and kill you. If
you don't want bots up there, then use a blocking volume and keep human
players off too.
As mentioned above, you can review your jumpspots by loading up your map
(without bots) and typing ReviewJumpSpots at the console. You can watch as
a bot tests every one of your jumpspots using translocator, shield jump,
combo jumps and low-gravity jumps. The results are written to the log
(found in <ut2003 dir>\System\UT2003.log).
ReviewJumpSpots also takes an optional parameter, for limiting the
types of jumps tested. This parameter can be any of the following:
Transloc | Combo | Jump | LowGrav.
The test bot will sometimes succeed and sometimes fail on the same jump, so
you may need to test more than once. Also, if you have paths forced to the
flag in CTF maps, the test bot will grab the flag, and may falsely report a
failure on subsequent jumps to the flag (since the flag will no longer be
there). Usually, this situation is evident from watching the bot. You should
also consider watching the bots in-game for especially tricky jumps or
translocations. During game play, bots will not always stand exactly on
the PathNode they are jumping from. If the bots are not making every throw,
make sure they are at least recovering smoothly. A well-configured JumpSpot
should allow the bots to succeed at least 90% of the time.
Sometimes bots have trouble translocating to your JumpSpots. There are
a couple of properties you can adjust to give the bots a little help in
aiming. The first and simplest is to set the JumpSpot's TranslocZOffset
property. This tells the bot how high above (or below) the JumpSpot to
aim. A good rule of thumb is to always set this to 64 and only adjust it
if needed. You may need to set it higher if the bots will be aiming along
a particularly steep path. A side-effect of this method is that bots will
tend to translocate to a spot in the air, and drop down. This makes it
less likely that they will inadvertently telefrag one another.
Some mappers like to have hidden or difficult to reach areas to hide
more powerful pickups. For example, a narrow window through which a
translocator can be tossed. With a little practice, human players have
no trouble navigating such openings, but bots can have no end of trouble.
For this type of precision aiming, you'll want to use the TranslocTargetTag
property of the jumpspot.
This technique involves placing a jumpspot beneath the window and then
forcing a path from the other side of the window to this jumpspot. In
order to force the translocator to be thrown through the window, a target
is placed within the opening and associated with the jumpspot. In the pictured
example, I used a window opening of 48 (height) x 16 (breadth) x 72 (width). The
bottom of the window is 64 units above the floor. The target is a generic
actor provided for such uses, called a LookTarget (found under Keypoint).
To set up your jump, follow these steps:
- Create your window as noted above.
- Center a LookTarget in the window, and align the bottom with the bottom of
the window.
- Give the LookTarget a name in the Event->Tag property (like Window1).
- Place a jumpspot beneath the window near the wall.
- On the other side, place a PathNode some distance back from the wall,
and force a path to the JumpSpot.
- Set the TranslocTargetTag of the JumpSpot to the tag of the LookTarget
(eg: Window1).
- Set the following JumpSpot properties to True: bNeverImpactJump, bNoLowGrav,
bOnlyTranslocator. Leave TranslocZOffset at 0.
- Set up a PathNode and JumpSpot in the other direction if you need the bots
to be able to escape. If you used the example window size, you should be able
to reuse the same LookTarget.
You can use ReviewJumpSpots to test your window.
UT2004 adds a pair of new properties to jumpspots:
- bForceAllowDoubleJumping: When bots are preparing to double-jump, there is an AI check
to see whether the bot will succeed. This property forces the bots to attempt the jump, even if
the AI check indicates the bot will "barely fail".
- bDodgeUp: This property is used to tell bots they can use a "slope dodge" to jump up to a
higher spot. Players were able to do this in UT2003, now bots can do it too!
As mentioned above, JumpPads give players a "boost" from one spot to
another. The UTJumpPad actor is not visible to human players, so you
will probably want to accompany it with a base mesh, emitters, etc.
Pathing JumpPads is much easier than kickers were in UT. First, place the
UTJumpPad actor where you want your jump to originate. Then open up the
properties. Under JumpPad->Sound, select a nice activation sound for the
JumpPad, such as Sound'wm_sounds.wm_BootJmp' (feel free to select
something more original). The JumpZModifier can be adjusted if you find
you're not getting the right height on your jumps. Leave it at the
default unless you need to tweak it.
Any PathNode can be a destination for your JumpPad. Select or place a
PathNode where you want your players to land, and note its Object->Name
property. Then, place that name in the NavigationPoint->ForcedPaths[0]
property of the UTJumpPad actor.
Before explaining how to set up teleporters, it is worth mentioning that
these should be used sparingly. Teleporters are a bot's best friend, but
they can be a nightmare for human players because it is confusing to
suddenly appear somewhere else on a map. Very rarely do teleporters
actually improve the flow of a map, and they generally weaken it.
But, if you "gotta have one", then read on. First, like JumpPads,
teleporters are not visible to players, so they should be accompanied by
some sort of emitter effect. Place a teleporter at both the source and
destination of the teleportation. Your teleportation can be one-way,
two-ways or even more confusing by having a teleporter be a destination
for one, but a source for something else. I recommend against this last
choice.
Once you have your teleporters placed, choose a name for the
destination. If this is a two-way setup, then choose a name for the
source. Set the Events->Tag properties to the chosen name(s). Next, set
the Teleporter->URL property of the source to the name of the destination,
and vice versa for two-way teleportations.
Lift pathing is not always intuitive to new mappers. Here's a quick
step by step on what to do for simple lifts:
- Set the lift's object->InitialState property to StandOpenTimed.
- Give your lift a unique name by setting the Events->tag property of
the mover.
- Place your mover at keyframe 0, and place a LiftCenter on the mover.
- Set the LiftCenter->LiftTag property to the lift's name.
- Add a LiftExit at keyframe 0. Set its LiftExit->LiftTag to the lift's
name, and set its SuggestedKeyFrame to 0.
- Add a LiftExit at keyframe 1. Set its LiftExit->LiftTag to the lift's
name, and set its SuggestedKeyFrame to 1.
In UT2003 (and earlier), players could get a significant boost by jumping
while riding up a lift. In UT2004, bots can do this too. To tell bots where
they can lift-jump, you need to add an extra lift exit at the destination
of the jump. Set up the lift exit as you normally would at the top of the lift,
but also set its LiftJump->bLiftJumpExit property to true.
Normally, bots will attempt to double-jump in the air in order to reach your
lift jump exit. If this is causing them to miss, try setting the
LiftJump->bNoDoubleJump property to true.
The UDN Suggests setting the AI->bAutoDoor property, but I have not had
good luck with this. For simple doors that are closed normally and open
when you approach them, follow these steps:
- Set the door's object->InitialState property to TriggerOpenTimed.
- Give your door a unique name by setting the Events->tag property of
the mover.
- Add a Door (NavigationPoint->Door) actor and place it a little above
the floor (same height as other pathnodes) inside the center of the door
mover.
- Set the door's properties as follows:
- bBlockedWhenClosed=True
- bInitiallyClosed=True
- DoorTag={the name you gave to the door}
- DoorTrigger={a unique trigger name. If this is "MyDoor1",
make it "MyDoor1Trigger"};
- Create a trigger, place it in front of the door and make sure it's
centered.
- Set the trigger's Events->Event property to the name of the door, and
set its Events->Tag property to the trigger name you chose
- Set the trigger's Collision->CollisionRadius property to 1 half the
width of the door.
- Make another trigger for the other side of the door with the same
properties. Optionally, you can place a single trigger right on top of
the door nav point...it's up to you to decide what works best for your
door.
Note: if you want your door to stay open while a player is near it, and
close as soon as they leave the area, then follow the above steps, but set
the door's object->InitialState to TriggerControl.
Be careful not to intersect your door mover or navigation point with a
ZonePortal. This can lead to problems building the path network, and
make your doors unusable by bots. See the Common Problems/Solutions
section at the end of this tutorial for more details.
This isn't necessarily a pathing issue, but it's a handy trick, and worth
mentioning here. Sometimes a trigger or pair of triggers is just not
enough to cover your door. Rather than pepper your map with triggers, or
increase your trigger radius/height to cover all you need and more, you
can define the area precisely using a volume. Here are the steps:
- Place your trigger above the door (or anywhere out of the way), and leave it's collision alone.
- Use the steps in the previous section to connect your door and trigger
- Make sure to give your trigger a unique tag.
- Create a volume to define the "trigger area" for the door.
- Set the Volume's Volume->AssociatedActorTag to the tag of your trigger.
- Now the Volume's collision will be used to activate your trigger (and your door)!
Ladders are relatively simple to path, but they are not very intuitive. The
visible portion of the ladder is simply a mesh, a texture on the wall, or
anything that gives players a visual cue that they can climb. If you use a mesh,
I recommend turning off its Collision->bBlockNonZeroExtentTraces property and
(if necessary) surrounding it with a blocking volume.
To make the ladder climbable, you need to create a ladder volume. I recommend
a minimum width and breadth of 64 units. The volume should start even with the
floor and continue about 40 units above the top of the ladder itself. This is
so that the automatic path actor (AutoLadder) is created at the height of the
other navigation points on that level. Also, make sure the ladder is touching
the wall being climbed. If necessary, use a blocking volume to provide
the "wall."
Once the volume is in place, you need to rotate it. In the top view, you'll see
an arrow in the center of the volume. Use the Volume's LadderVolume->WallDir->Yaw
property to change the direction of the ladder. As you might guess, the WallDir must
point to the wall itself. In the top view, these are the appropriate values for
the four major directions of the wall:
Yaw: 0 (right)
Yaw: 16384 (down)
Yaw: 32768 (left)
Yaw: 49152 (up)
If your wall is at an angle, you will need to use a value somewhere in between.
If you leave the bAutoPath flag set to true, the AutoLadder actors will appear in
your volume the next time you build your paths. These need to be rotated in the
opposite direction of the WallDir, which you can do the same way you rotate any
other actor in the top view. If you have problems with the AutoLadders, you can
set bAutoPath to false and place NavigationPoint->SmallNavigationPoint->Ladder
actors in the volume manually. The center of the Ladder actor must be within the
LadderVolume or it won't function properly.
Vehicles travel along special PathNodes. There are different types for ground
vehicles and flying vehciles. Vehicle PathNodes can be much farther apart than regular
PathNodes, so keep them fairly spread out when pathing open terrain. Make sure your
vehicles have a wide road to travel; they need room to maneuver. If your routes are
too narrow, bots may abandon your vehicles and travel enormous distances on foot!
Roads are defined using NavigationPoint->PathNode->RoadPathNode. As mentioned above,
keep the road paths spread out. Bots will also travel these routes, and you will notice
that other NavigationPoints will connect to them if they are in range. Don't lay out roads
in a web like you might with ordinary pathnodes across an open space. Make a nice linear
route that connects each vehicle and each objective. Roads must be comprised of white paths
(see below).
Flying vehicles use: NavigationPoint->PathNode->FlyingPathNode. These need to be placed in
the air. They will connect automatically to any NavigationPoints on the ground. So, start
above your flying vehicle and path routes to all the important areas of your map. To give
your bots a better chance at dogfighting, lay FlyingPathNodes out in more of a web so they
can range around rather than fly direct routes every time. If you have high mountains,
buildings, etc., you may have to step your FlyingPathNodes up gradually to climb over the top.
Pay close attention to whether or not they are linking to each other when you build your paths.
Generally, bots view vehicles as a means to reach a major game objective. If you want
your bots to stop and pick up other items (such as a redeemer), then you need to use:
NavigationPoint->PathNode->SpecialVehicleObjective. Give your pickup a name in the
Event->Tag property, and set the SpecialVehicleObjective->AssociatedActorTag to that name.
Next, you'll need to specify which vehicles are capable of reaching this objective. Add
each vehicle class to the AccessibleVehicleClasses array. Finally, you can optionally specify
how near vehicles should be before attempting to stop at this objective. If you leave MaxDist
at 0, bots will consider travelling to this objective from anywhere on the map. If you set this
to any number greater than 0, they will only stop if they happen to be in the right vehicle and
within that distance.
Once your layout is finalized, it is vital to fly around in the editor and make sure
there is a white path route between all of your vehicles and GameObjectives (flags,
PowerNodes, etc). Raptors need only to connect to a flying PathNode route, but other vehicles
should connect directly to your road. It's ok if there are some extra connections of green or
blue, as long as the primary path is uninterrupted white.
In other words, think of this as a single, white road that connects to each vehicle and each
objective. Bots will only understand how to reach objectives if there is a white route from
the vehicle they just hopped into to the objective they're seeking. If this route doesn't exist,
then the bot will abandon the vehicle and proceed on foot.
Reminder: To see whether your paths are white, right-click on the title bar of the 3D
(or any) viewport and select View->Show Paths
In ut2003, AssaultPaths replace the old AlternatePath with some more
robust AI options. They are primarily used in Bombing Run and Capture
the flag in order to recommend varied attack routes to the bases. You can
weight the paths so that the bots will favor a particular route, but this
is a decision that should be based on your map design. If you can't
decide how to weight (prioritize) your paths, leave them all at equal
weights and the bots should use them all equally.
On a couple of occassions, I have seen mappers lay out their AssaultPaths
like regular PathNodes, so that the bots would run along a long,
continuous route made entirely of AssaultPaths. This is incorrect. Think
of AssaultPaths as a place where bots should pass on their way to the
flag (or other objective), or as a place to gather for an attack. In most
maps, only a few AssaultPaths are needed for each objective.
The simplest way to use AssaultPaths is to place one at each entrance to
your base. Let's assume you are pathing a CTF map, and each base has a
left, right and center entrance. Here's the steps you would take:
- Add an AssaultPath near the left entrance of the red base and change
the following properties:
- ObjectiveTag=RedFlag [or whatever you set the
Events->tag property of the xRedFlagBase to]
- PathTag[0]=RedLeft [or something at least as
descriptive]
- Add an AssaultPath near the right and center entrances, and give them
the same ObjectiveTag and an appropriate PathTag[0] (like RedRight and
RedCenter).
- Repeat this for the blue base (assigning blue-specific tag names) and
you have a basic varied attack plan.
To make more complex assaults, you'll need to understand all of the
properties. Here's a breakdown of what they all mean:
Format: Property (Default Value) Explanation...
- bEnabled (True) If false, bots will ignore this actor.
Triggering the AssaultPath will toggle this property.
- bNoGrouping (False) By default, bots will wait for
reinforcements before moving on. Set to true to disable this.
- bNoReturn (False) By default, bots will use this path
for attacking and for returning with the flag. Set this to true if you
want bots to ignore this path on their way out. Useful for maps like
CTF-Citdel where bots drop down into the flag room, but can't get back up.
- bReturnOnly (False) The opposite of bNoReturn. Set this
to true if this is strictly a path for the flag runner, and not for
attackers approaching the flag.
- ObjectiveTag None The Events->tag property of the
objective being attacked. Usually, the FlagBase or BombDelivery.
- PathTag[4] (None) There are 4 available slots for path
tags. This is the name of the route the bots are following. Multiple
routes can run through the same AssaultPath. The route will branch
randomly based on the Priority of the available routes.
- Position (0) Only relevant if you are using multiple
AssaultPaths on your route. Set the one farthest from the objective to the
lowest number, and increase as you get closer. You can have more
than one AssaultPath with the same position (up to 16), in which case, the
next path will be randomly selected based on priority.
- Priority (1.000000) Only relevant if you are using
multiple AssaultPaths on your route. Break up your priorities for each
position along the same path so that the sum of the priorities adds up to
1. This then gives you the percentage chance that the current AssaultPath
will be chosen.
Now that you understand all the properties, let's walk through
a complex example. Take a look at the picture on the right, and imagine
this is a top view of our CTF map and the colored lines represent routes
the bots can take. The letters represent points where we will add our
AssaultPaths. Also assume that there is an intersection at point B,
so bots can continue along either route.
First, we'll add the paths for attacking the red base. We have placed
our flag somewhere in the base, and given it a name by setting its
Events->Tag property to "RedFlag" (without the quotes). For the sake of
our example, we'll assume our base has two entrances near points D and E.
Step one will be to place AssaultPaths at points A, B and C with the
following properties:
AssaultPath A
- ObjectiveTag=RedFlag
- PathTag[0]=RedLeft
- Position=0
- Priority=.25
AssaultPath B
- bNoGrouping=True
- ObjectiveTag=RedFlag
- PathTag[0]=RedCenter
- Position=0
- Priority=.5
AssaultPath C
- ObjectiveTag=RedFlag
- PathTag[0]=RedRight
- Position=0
- Priority=.25
Our initial AssaultPath setup causes the bots to chose the center path
about 50% of the time, and each of the side routes about 25% of the time.
Because we anticipate our center route being a high traffic area, we
decided not to allow the bots to group at this spot. They will press on
and attack without necessarily waiting for reinforcements. On the brown
and grey paths, the bots will wait at points A and C, respectively until
they have sufficient numbers for the attack. The actual number that will
group is based on the number of bots that are currently in "attack" mode.
Note that all three paths have the same position. This is important,
because when beginning the attack, bots will only consider AssaultPaths
with the lowest position number.
Now that we have our initial routes defined, we need to give the bots some
direction for continuing on. We'll set up AssaultPaths at points D and E
on our diagram with the following parameters:
AssaultPath D
- bNoGrouping=True
- ObjectiveTag=RedFlag
- PathTag[0]=RedLeft
- PathTag[1]=RedCenter
- Position=1
- Priority=.5
AssaultPath E
- bNoGrouping=True
- ObjectiveTag=RedFlag
- PathTag[0]=RedRight
- PathTag[1]=RedCenter
- Position=1
- Priority=.5
Bots use the PathTag property to determine which AssaultPath's they will
consider when continuing on. So, bots at point A will continue only to
point D, and bots at point C will continue only to point E. However,
bots at point B will choose between points D and E (50% each). We don't
want our bots to congregate this close to the enemy base, so we set
bNoGrouping to True. Next, we would set up our blue base following
basically the same steps as above.
Now let us suppose that we want our bots to favor the two side routes when
returning with the flag. Still working on the red base, let's make some
changes. First, we'll add another AssaultPath at point B and call it B1.
We'll change the properties of AssaultPath B so the two paths will end up
as follows:
AssaultPath B
- bNoGrouping=True
- bNoReturn=True
- ObjectiveTag=RedFlag
- PathTag[0]=RedCenter
- Position=0
- Priority=.5
AssaultPath B1
- bNoGrouping=True
- bReturnOnly=True
- ObjectiveTag=RedFlag
- PathTag[0]=RedCenter
- Position=0
- Priority=.1
Now AssaultPath B will be used only for attacking, and will be used 50% of
the time. AssaultPath B1 (whose priority is only .1 instead of .5) will
be used only for returning and will be used about 17% of the time
(.1 / (.25 + .1 + .25) = .1666, or about 17%). Obviously, you can tweak
the priorities however you like.
Remember that when starting an attack on the flag, bots will run to the lowest
position numbered AssaultPath. This means that if they spawn closer to the
enemy base, or on the opposite side of the map, they may need to go out of
their way to begin the attack. Keep this in mind when placing both PlayerStart
and AssaultPath actors.
Don't read this section if you are easily confused. There are some nuances
to AssaultPath positions that I have not pointed out because they can be
rather confusing. For those that require an exact explanation, I have
included this section. You may safely skip this section if you are only
interested in a basic assault plan, as all of the previous advice will
work, even if the explanations were inexact.
When your map is loaded, the first and last AssaultPath for each unique
PathTag is marked. A path is first as long as it has the lowest position
number among all paths that have at least one tag in common with itself. A
path is last as long as it has the highest position number among all paths
that have at least one tag in common with itself.
Bots will begin their attack by randomly choosing among all of the paths
marked "first", based on priority, but ignoring paths flagged bReturnOnly.
Bots will return by randomly choosing among all of the paths marked "last",
based on priority, but ignoring paths flagged bNoReturn.
Once an attack or return path has been determined, one of the PathTags of
the selected path is randomly chosen, and the bot(s) will then follow the
paths matching this tag in order of position until no more paths with the
selected tag can be found. After that, bots will take the most direct
route to their objective.
UnrealScriptedSequences replace DefensePoints from UT. They are usually
used in CTF, BR and DOM maps, but can be used in Deathmatch as well. In
goal-based maps, USS actors are associated with a game objective, such as
a flag, bomb gate or domination point. In deathmatch, they are generally
placed at a good "ambush points" where bots might wait for unsuspecting
players to wander by. Many deathmatch maps (including some Epic) ignore
these actors completely.
You will find this actor under:
Keypoint->AIScript->ScriptedSequence->UnrealScriptedSequence
Strictly speaking, these are not really defense points, but scripts that
will interrupt the bot with an instruction to run over and defend a spot
for three seconds. To understand why this is useful, you need to
understand something of how the bots behave.
The AI in UT2003 is Squad-based. In a objective-based team game (CTF, BR),
bots fall into three groups: Defenders, Attackers and Freelancers. The
freelancers are the bots that wander the map, but are switched over to
support either the attackers or defenders whenever needed. Attackers and
Defenders will temporarily change roles at times too, but not as easily
as Freelancers. In Deathmatch, all bots are Freelancers.
Attackers use AssaultPaths to reach objectives. Defenders and Freelancers
wander around picking up items and looking out for the enemies. Combat
always takes precedence over whatever else the bot is trying to do, so
if you're wondering why your bots are not occupying your nice sniping
perch, it's probably because they're getting into fights on the way over.
Defenders more or less focus on staying near the flag, but they rely
on scripts to let them know what areas to concentrate on. As mentioned
before, the scripts really just summon the bot over for a moment or two,
and then control returns. So they are not really used as a place for the
bot to stand and wait, but a method for keeping the bots close to home. As
long as the defending bot isn't fighting, the script will periodically gain
control and tell the bot "c'mere a minute."
Freelancers usually do not require any scripting, but you can use scripts
for these bots. In this case, the scripts are not team-specific, so
freelance points can be used by any freelancing bot. These are probably
useful along assault paths where you want your freelance bots to harass
the attackers as they are attempting to reach the base. Again, the concept
of how they are used is the same. Freelancers are periodically summoned
to the script points for a period of 3 seconds.
Using UnrealScriptedSequences
Before I continue, let's find out about the properties we'll be using.
Along with the properties are comments on how these are generally used
on the Epic maps:
- bDontChangeScripts. Bot should go back to this script, not
look for other compatible scripts. Always left as False
- bRoamingScript. If true, roam after reaching. Always left as
False
- bSniping. If true, bots should snipe when using this script as
a defense point. Set this when you want your bots to snipe from this
location.
- EnemyAcquisitionScriptProbability. Likelihood that bot will
use acquisitionscript. Always left at 1
- EnemyAcquisitionScriptTag. Script to go to after leaving this
script for an acquisition. Always left as None
- Priority. Used when several scripts available (e.g. defense
scripts for an objective). In spite of this comment (which comes from the
UnrealScript code for the USS actor), Epic almost always leaves this at 0.
- SnipingVolumeTag. Area defined by volume in which to look for
(distant) sniping targets. If you want your snipers to snipe a specific
area of the map, put a SnipingVolume around that area, assign it a tag,
and then set this property to that tag.
- WeaponPreference. Bots using this defense point will
preferentially use this weapon. Bots with this weapon will favor this
spot, and bots whose favorite weapon matches this weapon will prefer this
spot even more.
To set up defense points around your base, place the USS actors wherever
you want your bots to stand. This is a directional actor, so be sure to
rotate it so that it faces where you want the bots to face. If a
particular weapon is advantageous from this position, set the
WeaponPreference to that weapon. It is helpful if the weapon and/or ammo
is available nearby. If you want bots to snipe from here, set bSniping to
true, and set up a sniping volume if your situation calls for it.
If you are setting up your defense point around a game objective
(flag, bomb delivery, dom point), then you need to set all the defense
points for that objective with the same tag and set that tag in the
objective's properties. For example, if we are defending the red base for
CTF, set up a bunch of USS actors in the base and on each one set the
property Events->tag=DefendRedFlag . Then, we would go into the
properties for the red flag and set
GameObjective->DefenseScriptTags=DefendRedFlag (this is the default, but
it never hurts to check).
If you are setting up freelance scripts (see the SquadAI section), you need
to give all the scripts the same tag, but not a tag used as a defense tag
by any GameObjective. For example, give them all the tag: Freelance,
or leave them all at the default tag. If you use more than one tag for
your freelance scripts, the bots will ignore all but one group of them
(where a group is a set of scripts with the same tag). There is no easy
way to control or predict which groups will be ignored in this situation.
Important note: if you use freelance scripts, it is important to use at least
5 or 6 scripts. Because of how the scripts are weighted and selected, it is better
to have none at all than to have 1-4.
If you've read this whole section, you should have a pretty good idea of
how UnrealScriptedSequences work. There are many possibilities for good
placement strategies, but the most common use is to place them at sniping
points, and in the flag rooms. One or two at each sniping point should be
sufficient. In the flag room, you'll want to put 4 or 5 around the
perimeter of the room so that the bots will vary their position, and are
also more likely to be somewhere in the room when the attackers arrive. I
have also found it useful to position weapons in logical "defense point"
locations within the flag room, exploiting the fact that bots sometimes
camp these locations.
As a final note, it is worth mentioning that you could play around with the
AIScript section of the UnrealScriptedSequence to give the bots more
complicated instructions. There is a very simple macro scripting language
available as an array of commands. The UDN Site describes all of the
commands (actions) in case you're curious.
GameObjective actors are objects that represent goals in a game. They are
flags, domination points, bomb gates, and ball spawns. This section covers
the objectives you will normally use when mapping DOM, BR or CTF. There
are some other objectives that Epic has provided, such as
DestroyableObjectives, LockedObjectives and TriggeredObjectives, but these
are beyond the scope of this tutorial.
When you place objectives on your map, be sure they are well connected
to your path network. Connecting your flag (for example) to a single
pathnode will make your bots attack in a predictable manner.
GameObjectives derive from JumpSpots, and can be found by expanding this
actor in the class browser. Bots will also make better attacks if you
force a couple of paths to the objective, just as you would to any other
JumpSpot. The only exception to this is the xBombDelivery, where you will
want to force a path from a single pathnode right in front of the objective
so bots will double jump into it and score a touchdown.
These are simply the blue and red flags for CTF maps. Place them in the
appropriate bases, and make sure they are attached to your path network.
Typically, you'll want to set the Events->tag to "RedFlag" or "BlueFlag",
and then use this tag when you set up your AssaultPaths. You'll also want
to check that the GameObjective->DefenseScriptTags is the appropriate tag
for your UnrealScriptedSequences. You may want to check the height of the
flags in game to make sure they are properly aligned with the ground.
Again, this is relatively straightforward. These are the two points used
in domination maps. Place them in the appropriate locations. If you set
up defense points around your domination points, then you'll want to make
sure to set the GameObjective->DefenseScriptTags property to the
appropriate name.
As you might suspect, these are used for Bombing Run. The xBombSpawn is
where the ball will appear at the start of the match, and whenever it is
reset. Place one in an appropriate location on your level.
The xBombDelivery is the gate or "goal" used in BR maps. Place one in each
base, and set the GameObjective->DefenseScriptTags, and Events->tag the
same way you would for the flag bases (see above). You also need to set
the GameObjective->DefenderTeamIndex to 0 for the goal in the red base and
1 for the goal in the blue base.
There are two other necessary steps for getting the bots to use the
xBombDelivery properly. First, you must force a path to the xBombDelivery
from a pathnode close enough so that bots can score a touchdown with a
double jump. Second, you must place one or more shootspots so that bots
know how to shoot field goals.
For each BombDelivery, place a shootspot equivalent to the defending
team's color (BlueShootSpot in the blue base and RedShootSpot in the red
base). This is where the bots will stand to attempt a field goal. When
bots decide to use a shootspot instead of trying for a touchdown, they will
try from the nearest shootspot along their current route. So if you
include more than 1 per goal, you will probably have to use AssaultPaths
to ensure that all of them are actually considered.
Finally, if you think your bots are trying for touchdowns too often (or not
enough), you can set the xBombDelivery->TouchdownDifficulty property. Set
it somewhere between 0 and 1 where .1 is very easy and .9 is very difficult.
In most cases, the default of .5 should work fine. Bots will decide to try
touchdowns for a variety of reasons, based on the current score, health of
the ballcarrier, time remaining, etc. The TouchdownDifficulty is used in
conjunction with some of these other factors.
As mentioned above, it is
very important to connect your vehicles to all of your game objectives via
white paths.
If you don't have a road path directly connected to your GameObjective, you must
set the GameObjective->VehiclePathName property to the name of the nearest
RoadPathNode (supply the Object->name, not the tag of the RoadPathNode).
This section is meant to reinforce some of the principals explained in
other parts of this tutorial. Be sure you read and understand the rest
of this tutorial before reading this section.
Bots generally wander because the path network is not completely connected.
Particularly, if you have PlayerStarts or GameObjectives disconnected from
the rest of the map, you will see this issue. The Tools->Review Paths menu
option will warn you of these issues, so if you are experiencing trouble,
that is a good first step (see above for more details).
In Deathmatch, bots may wander if they have nothing better to do. If a bot
is loaded up on weapons and ammo, or has no one nearby to shoot, it may just
stand around. Also, it will not be able to chase human players who have
wandered off the path network. Bots will take shots at you if you are in
their line of site, but will not come after you unless they can map a route
there using the path network.
The answer to this differs for Deathmatch and Objective-based games. In
deathmatch, there is a real art to balancing item placement and
PlayerStarts to achieve a balanced map. If areas are difficult to reach,
bots may ignore them. As mentioned earlier, bots will sometimes ignore
blue and green paths in favor of white paths. Another problem could be
one-way paths. Make sure your navigation points are connected by lines
going in both directions. Sometimes a pathnode links down to another on
a lower level, but there is no path back up. Bots that spawn below can
become trapped, while bots outside this area may avoid it completely.
Bots of lower skills will not make tricky jumps, or even translocations.
If you have areas that are reachable with a quick translocation, consider
a longer, slower walking route for lowly bots. In DOM and DM, you should
never assume that the translocator is available, as many people play
without it. Even in CTF or BR, this is true since mutators like Instagib
turn off the translocator. In CTF, areas that require translocation are
not usable by the flag carrier, so keep this in mind as well.
In objective-based games, attacking bots will always take the shortest
route to the game objective. The only way to control this is with
AssaultPaths (see above). Defending bots will wander between defense
points and generally stand guard. They will fan out a little and grab
nearby weapons, ammo and other pickups, so put these along your defensive
and attacking routes, rather than some out-of-the-way corner.
In team games, particularly CTF, sometimes you'll find bots that are just
crouching and not doing anything productive. This may be because they can't
reach one of two things; the enemy objective, or a defense point for your
base. Make sure that these are available and connected to the path network.
If you have defense points and some bots are still crouching and ignoring
them, you may need more. For a map targeting 16 players, it is not
unreasonable to have as many as 5 or 6 (or more) defense points in each base.
Another thing to keep in mind is that bots will go into "stakeout" mode
periodically while defending or freelancing. This means crouching down and
looking out for an enemy. In the normal course of things, they'll snap out
of it in 5 seconds or so. If they are crouching longer, then you may need to
adjust your weapon and PlayerStart positions. If your map uses "spawn rooms,"
try to keep them behind the flag (i.e. so the bots will have to move past the
flag they are defending before getting into the action). You can put ammo in
the spawn rooms, but if you put in weapons, the bots may stake out the spawn
points. Try putting your weapons further out into the map. If you're worried
about spawn camping, try using several spawn rooms instead of just one.
This problem is named for the map that I first encountered it in, CTF-PhaseShift
by Rachel Cordone. In the first version of this map, despite the best efforts
of both Rachel and myself, the bots would not capture the flag. The blue
team would reach the red flag, and then freeze, unable to find a route back
to the blue base. The red team rarely found the blue base at all. All ordinary
pathing problems were investigated, but no errors were found.
The bases in PhaseShift are essentially islands in the editor, connected only
by teleporters. This in itself is not a problem, but they were unusually far
apart in this map (over 60,000 unreal units), which turned out to be the
cause of the bots' navigational problems. Moving the teleporters closer
(just under 30,000 unreal units) solved the problem. I am not certain whether
this is because of a problem specific to the teleporters, the overall path
distance, or the distance between the flags. My primary suspect is the
teleporters, so keep that in mind if you encounter this sort of problem.
Update: A licensee emailed me with a little more information on this
problem. The licensee writes, "...it appears that the problem is caused when the
distance between the pathnodes at the extremities of the path 'network' in the
map exceed 60 000 units, a negative integer is returned and the path building
process fails." I am not certain whether this was the UT2003 engine, UT2004
engine, or (most likely) something in between. Since I've seen working UT2004
maps with path networks larger than 60,000 units in diameter, it is possible
that this issue has been resolved in that version of the engine.
First, bots are happiest with Doors that use TriggerControl. With doors that
use TriggerOpenTimed, or any other opening method, the bots will sometimes have
trouble. If you can get away with TriggerControl doors in your design, then
use them. If you have to use something else, spectate your bots and watch
carefully for problems. Sometimes, with diligence, you can get them to behave.
I have heard from a few mappers who have had nothing but bad luck with doors.
In spite of my best advice, they continue to complain that the bots won't
recognize their doors. While wrestling with this issue recently, I realized
a possible solution. In my map, the Door navigation point and the door itself
were being bisected by a ZonePortal sheet. The Door was omitted from the path
network, and the bots would not recognize it. When I moved the sheet back so
that it was touching neither the mover nor the navigation point, the paths
connected properly, and the bots used the door without trouble. Since doorways
are always a likely spot for ZonePortals, I can certainly see why some mappers
have encountered this problem over and over.
Many mappers have complained of bots standing, apparently transfixed, next to the
Hellbender. To avoid this, place a few ordinary pathnodes in the area around the door
so that bots have room to maneuver around one another and jump in. Make sure the Hellbender
connnects to your white road.
Sometimes bots will sit in the gunner's seat of the Hellbender and wait. Normally, another
bot will hop in and drive away, but sometimes the gunner gets stuck. I have not yet found a
solution for this, but I believe it is an AI problem that will hopefully be corrected in a
future patch.
Sometimes bots will hop in a vehicle and hop right back out again, taking off on foot
or moving on to another vehicle. When this happens, the most likely cause is that the vehicle is
not connected to the objective the bot is seeking. Again, see the
white road section for more details.
I hope you found this tutorial helpful. I spent a good deal of time
testing and researching many of these topics, but I am only human. If you
find errors or items in need of clarification, please email me at:
blitzthethief@delta-quadrant.net.
Mike 'Blitz' Breuer
blitzthethief@delta-quadrant.net
http://www.unrealplayground.com/mapper.php?id=1685
|