Tuesday, 6 September 2011

Tutorial HL2: Getting Your NPC's Moving

Here's the first draft of a tutorial I'm writing. It needs lots of images adding but hopefully should be helpful for some of you in it's present form.

One of my biggest frustrations when I first started mapping was trying to get my NPCs moving around in a convincing manner. I wanted my NPCs to move into an area and attack the player, or open doors and run away but they just don't do that by default.

So how do we get NPCs to start moving around rather than just attacking the player when they move into their point of view.


Before Left 4 Dead, valve games relied on the mapper placing nodes on the ground to produce a series of points that the NPCs could follow.

Left 4 Dead and games after that from Valve use the nav mesh method of NPC navigation. So if your mapping for HL2 then you need to add info_nodes to your map. Add nodes to any areas you want NPCs to move through. For ground based NPCs (combine S etc...) use info_node, for flying NPCs use info_node_air and for hybrids who fly and walk (e.g. antlions) you ll need to add both. When you run the map in game for the first time in game the engine connects all the nodes together to create a nav mesh.

NPCs use all these connections to find paths to goals in the game. A goal might be the player or any other entity you choose as a mapper.
All nodes must be less than xxx units apart or a connection wont be made. That goes for info_node_air too!

Scripted_sequence vs AIscripted_schedule

I see many people suggest on forums suggesting that others use scripted_sequence to move their NPCs around but unfortunately its usually the wrong option under the circumstances.

Its a fairly straightforward rule to follow when choosing which of these two direction entities to use.
Basically, if the NPC can be interrupted or attacked, you should use aiecripted_schedule, if they cannot be interrupted or attacked then you can use scripted_sequence.
Scripted_sequence is intended more for getting the NPCs to play animations (best for cutscenes) where as aiscripted_schedule is to issue instruction during gameplay...

The reason for this is that while an NPC is following directions from a scripted_sequence they will be locked into an animation until its complete. So they wont react to being attacked and can often stand there looking dumb while the AI takes a a few seconds to kick back in.

With aiscripted_schedule you can get them to move around the battlefield with their AI fully intact and they can react to any event.

All clear? I hope so.


AIscriptedschedule is a godsend for making firefights more interactive. It basically encourages or forces NPCs to perform a specific action without switching off the NPC AI.

You can make the NPC run or walk to a specific place in the map or move to a specific target. You can direct them to move to and attack a specfic target, including the player.

To set it up, you just need to place an AIscripted_schedule entity in your map, give it a name, name the NPC who will follow its instructions. Set the instruction (move to goal entity for example) and then set the goal entity.

The goal entity can be any named entity in your map. If the goal entity is the player then just type in !player. If you just want the NPC to move to a specific location then use a named info_target to mark the location and use that as the goal entity.

You can trigger the schedule with any output but normally you'll be using a trigger brush. If you are using a trigger you can make your schedules a little more dynamic by using the !activator value as the goal entity.

By typing in !activator the schedule will set the target to whatever triggered the trigger.

I add an antlion to my map and set it to start burrowed. I name it antlion1. I set its sleep state to ignorePVS, Wait For Input. I set a trigger_once around it and add an AIacriptedschedule and name it AntSchedule1.

I set AntSchedule1 to direct antlion1 to Set Goal Entity As Enemy. I then set the goal entity to !activator.

I set my trigger_once to wake the antlion onTrigger and then 0.1 seconds later (its good to leave a gap) I set an onTrigger to StartSchedule on AntSchedule1.

I then place a group of friendly rebel NPCs in my map who will form a squad to help the player.

When I run the map, as the player and the team move across the map, whichever entity (the player or a member of the squad) hits the trigger first will wake the antlion and be attacked, like a trapdoor spider.


The interruptibility option on an AIscriptedSchedule is really important.

If you leave it set to General this then leaves it to the NPC AI to decide if there is anything more important it should be doing (i.e. defending itself) rather than follow the instruction. In my experience, general should only be used to direct friendly NPCs when there are no enemy units in that area.

On Damage is a clever option and very useful for certain gameplay types. Basically an NPC will carry out instructions unless it is damaged while in the process of carrying out that instruction.
What this means is that you can set up nice areas where enemies attempt to reach a certain goal and the player has to stop them by shooting at them... or say you want NPCs to run past the player but not attack them, it would be farely unrealistic if the NPC didn't respond at all to being shot, so the On Damaged option will make them attack the player if shot. Handy!

On Death is the daddy. An NPC will follow direction given by the schedule no matter what happens. This is the one to use if you want to move an NPC into the area of play. From outside of the players viewpoint.
With On Death you can have NPCs moving all over the place and because the AI is still switched on, they will continue to fire on the player whilst moving. So you can make Combine soldiers retreat to a certain point, or make Antlions fly up to a high ledge etc...

The info_nodes

In order for your NPCs to follow instructions from an AIscripted_schedule they need to be able to find a route to their goal through the info_nodes you have placed in your map. If your NPCs are not following direction from your schedule, an incomplete node path is probably the reason why.
You can check your node connections by activating sv_cheats 1 in the command console and then typing in ai_show_connect


Annoyingly, things like doors can break a node path. The reason for this is because the node graph is built at the point the map is launched in the editor. Its then saved as a data file in the graphs directory of your maps folder.
If all the doors in your map are closed at the time when the map is first loaded then the node graph will not connect nodes on either side of a closed door because the door would stop the NPC from moving between them.
For this reason, its often handy to set all of your doors to the open position when your map spawns then close them using a delayed logic_auto after 1 second. As long as the door is not in the players view when they spawn in the map you should get away with it.

If you want doors to open and close when NPCs approach them then you can add a trigger multiple that is only triggered by NPCs. Expand the trigger so that it reaches out on both sides of the door. Now just add an OnTouching output to the trigger to open the door. You may need to play with the size of your trigger in order to get it working properly.
Note that this will only work of your doors were open when the nodegraph was built.

The NPC Clip Texture

NPCs are sometimes a little dumb and need some extra help to keep them out of areas of your map you don't want them in.
Obviously you wont need info_nodes in areas where you don't want NPCs to go but sometimes they decide.. to hell with it and follow the player there anyway. This is where brushes covered entirely in the NPCclip texture come in very handy. NPC clip brushes act like invisible walls that are non-existent to the player keeping NPCs away from dodgy areas.
The uses for NPC clip brushes can really be quite varied. You can make NPCs seemingly walk on air if you like... or use them to funnel NPCs in the right direction.

Player clip brushes

Equally, sometimes you may want an NPC to ignore the fact that theres a fence model between them and the player and go for the player anyway.
In a recent map of mine I had a situation where a fast zombie runs and jumps at the player across a fan shaft. The player is behind a fence so they cant accidentally fall in. As the zombie jumps at the player, a trigger push whips them away into the fan blades to their doom.
I achieved this by setting the fence to be not solid and then covering it in a thin brush of player clip. As far as the zombie is concerned theres nothing in the way and the node graph is connected so he goes for the kill yet the player finds the fence to be normal.

Getting NPCs to jump.

Go read this tutorial...

Now I will explain whats missing. Some NPCs can jump a really long way... like fast zombies. To encourage them to make those jumps you can add a few info_node_air entities to their jump path to encourage them to make that leap.

Climbing NPCs

Oooh this is where things get a little tricky... well fiddly...
Some NPCs do have climbing animations and can climb up special ladders with their AI in tact all the way.
NPCs that can climb are the following:
NPC_Fast Zombie

In order to set up these special ladders go read this tutorial... then come back here and I'll tell you a little more...

Go on...

Off you go...

Back? Good.

There are a few things missing from that tutorial that you need to understand when it comes to NPC climbing. Heres da rules.

1. If your NPC ladder is higher than 128 units high you'll need to add info_node_airs at regular intervals up the ladder. Like this...

Add image!

... so that the node graph is still connected all the way up and a path can be found.

2: Your info_node_climb nodes must be lined up exactly in a straight line. Like this...

Add image!

NPCs can only climb straight upwards.

3. The NPC must exit the ladder in the direction they started it in. Like this...

Add Image!

4. NPCs can die and fall off ladders if shot but cannot fight while climbing. They just dont have the animations for that... sorry.

5: NPCs can climb downwards but it aint pretty. Fast zombies for example simply play the upward climbing animation when climbing downwards... always keep them climbing upwards.


geotavros said...

Thanks, nice tutorial.
However, one part is not covered. If I have npc_maker, how can I force spawned NPCs to move to the position I specified?

Aazell said...

In your NPC_maker you should have a parameter for the name of the spawned entity. Then set up an ai_scriptedschedule that is fired just after the spawner spawns a new entity.
Im assuming you want all spawned npcs to head for the same spot.. if you want them to head for different locations then things get way more complex and you're best off using multiple spawners.

You could also try using the target path value if there is one and just enter the name of a path corner youve placed in your map.