Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.
Today we'll delve into UDK's Kismet and take a look at developing Events, what they are, how we can create them and how we can manage them. You'll learn how to create and manage nearly every type of Event in UDK in order to be able to build complete, complex and fully scripted levels starting with the simple level we'll be creating in this tutorial.
Introduction to UDK's Events
In UDK, an event is a particular situation that you define, (obviously in Unreal Kismet) which brings consequences to game play or to other game elements. You can create events anywhere in a level, without limitations. You can divide them into three different groups: Pre-Compiled Events, Trigger Events or InterpActor Events. In this tutorial we'll cover them all to give you a complete view of how an event is created and manipulated.
Pre-compiled events: If you open the Unreal Kismet (the green K on the top of the UDK window, near the Content browser's icon and the Matinee icon) and right-click on a blank space of the Kismet window, and you go under "New Event", you'll see a lot of ready-to-use events grouped together as "Actor", "AI" or "Pawn" for example. Actor, AI and Pawn are in this case, the triggering part of an event and without them, the event doesn't start at all. So, an example: if you want an event to start when an enemy dies, you'll have to go under "Pawn", because an enemy is called a pawn, and choose Death.
For our purpose, create a 512 x 512 x 256 Hollowed Cube.
Now, add a Point-Light into the room by holding the L key on the keyboard, and then left-clicking in the room we just created (the Cube.)
Move the light into the center of the room, and then rebuild the lighting (with or without Lightmass, it's not important.)
Done? Now, we can start with our first UDK event, a pre-compiled event in this case. The most common pre-compiled event used by a UDK coder is the "Level Loaded" event. As you can imagine, this event starts when the level is loaded. So, let's start with this: Go to Unreal Kismet, right-click on a blank space and go to New Event>Level Loaded.
Now, you should have a Node called "Level Loaded" in your Kismet. If so, then you can now see that this Node has three Outputs or, better in this case, three conditions to activate the event: When the level is Loaded and Visible, at the Beginning of the level or when there's a level Reset. These conditions are quite self-explanatory, in fact the only difference between "Loaded and Visible" and "Beginning of level" is a little delay of the second compared to the first. While the third is about a reload of the level, but we won't get into this feature now.
We're going to create a sort of alarm that tells the player to prepare himself because an enemy is arriving. In order to achieve this, let's create another Node by going (always with right-click), to New Action>Voice/Announcements>Play Announcement.
Now, click on this Node, and in the Announcement Text bar, write "Prepare yourself! A robot is coming to kill you!" With this, we are telling UDK to write a text in the center of the monitor that advises the player that a robot is coming to kill him, so he must prepares himself to fight.
Now, create another 6 Play Announcement Nodes, as we have done before.
In the last one, write under Announcement Text "Take the Shock Rifle and the fight will begin!".
In the other Nodes, we are going to use a sound countdown which is included in the UDK assets. So, go into the "Content Browser" and write in the search bar "countdown". A Ten Soundnode Wave will pop up, then select the "Countdown 5".
Now, return to Kismet and click on the first empty Play Announcement Node. Go into the Announcement Sound bar and click on the green arrow on the right. The name of the SoundNode Wave should appear in the bar. What you've just done is tell UDK to play the sound a number (five) of times in order to create a countdown.
So now, do what you just did with the previous Node, with the four remaining Play Announcement Nodes. Remembering that you must first select the number for the countdown in the Content Browser (the fourth, the third, the second and the first) and then click on the node in Kismet, and then in the Announcement Sound, click on the green arrow to insert it.
Done? Well. Now, it's time to connect the event to the nodes we have created. Connect the Output of "Beginning of Level" to the first Announcement Node.
Then, from the Output of your first Announcement Node to the Input of the second Announcement Node and so on (as shown below.)
Now, when the level begins we have a series of announcements that advise the player, but if we leave them the way they are, only one announcement will be displayed on the screen and the player won't get all the information we want give him. In order to display them all, we must set a delay between our Announcement Nodes. So, right-click on the Output (the black rectangle) of the first Announcement Node, and click on "Set Activate Delay". In the window that appears, set the delay to 2.0 and click OK.
Repeat the previous step for the connections between the other Nodes, but this time set the delay to 1.0, because there's the countdown!
Trigger Events: These are particular events used to trigger part of an element, which isn't shown during game play, called a "Trigger". Triggers are cylinders, but not proper cylinders. They have a radius and a height, but are not a brush or something you can apply a material to. The radius and height of these cylinders describe the area which a player, a pawn or anything you want, can activate the relative event. So in this case, players or pawns aren't directly responsible for the start of an event, but they trigger it through contact with the defined area of the Trigger's cylinder.
Remember that you wrote in the last announcement "Take the Shock Rifle..."? well I guess it's time to put one in your level. But first, let's put a Trigger in, which will help us to define the area in which the player will activate the next event, and where we will spawn our Rocket Launcher. So, right-click on the floor, go to "Add Actor" and select "Add Trigger". Now, you'll notice a strange icon has appeared, what seems to be a switch, with a red rectangle that wraps around a green cylinder.
Now, as I said before, the cylinder is the area that defines if there's contact with the player or not, and activates an event. Let's make it bigger. Right-click on the trigger, go to "Properties" and under "Cylinder Component", modify the Cylinder Radius and Height as you wish (I'll go for a 60-60.)
Probably as with mine, your Trigger's cylinder went down into the ground. So slide it up and when you're finished, return to Kismet.
On a blank space near the last Announcement, right-click and go to New Action>Actor and select "Actor Factory".
Click on this Node, and in the Factory bar, click on the blue arrow on the left and select "UTFactoryPickup". Then click on "Factory" to expand it, and in the Inventory bar select "Shock Rifle".
Then, select the Trigger in the level and return to Kismet, right-click on the "SpawnPoint" Input and click on "New Object Var using Trigger".
Now, connect the Output of the last Announcement Node to the Input of the Actor Factory Node. Well, we finally have our Shock Rifle that spawns after the last announcement.
Now, we have to spawn an enemy after the player has taken the Shock Rifle. To do this, we'll create a Trigger Event. With the Trigger selected in the level, go to Kismet and right-click on a blank space, then under "New Event Using Trigger", select "Touch". This means that the event will be activated when the player enters into the cylinder's area. Another common choice is "Used", it means that when the player is in front of the cylinder, and presses the E key he can activate an event. The others are minor choices, that aren't used frequently with a Trigger.
Now, create another "ActorFactory" Node, but this time in the Factory bar, select "UTActorAI". And in the Factory properties, set the ControllerClass: to "UTBot", the PawnClass: to "UTPawn" and check on the "GiveDefaultInventory" Property.
Then, give him a name (I will leave the decision to you ) and connect the "Trigger Touch" Event to "Actor Factory". Now, right-click on the "Spawned" Output and select "Create New Object Var".
In your level, on the opposite side of your Trigger, right-click on the floor, go to "Add Actor" and select "Add Pathnode".
Now, return to Kismet, right-click on "Spawn Point" and select New Object Var using Pathnode. Finally, you have created your first Trigger Event and have your enemy spawning after that the player has taken the weapon, the only thing that remains is to give the enemy a target.
In Kismet, right-click and go to New Action> Misc and select "Trace".
Connect the "Finished" Output of ActorFactory to the "Trace" Input, then connect the Start Input of "Trace" to the Object Variable of ActorFactory's "Spawned".
Now, right-click on a blank space, and go to New Action>AI and select "Start Firing At".
Then, right-click on a blank space, go to New Action>AI and this time select "Stop Firing".
Connect the "Not Obstructed" Output to "Start Firing At" and "Obstructed" to "Stop Firing".
Connect the Output of both "Start" and "Stop Firing" to the Input of "Trace" (as shown.)
Set their output delay to .5.
Connect the Target Input of both "Start" and "Stop Firing" to the Spawned's Object Variable.
Now, right-click on a blank space and go to New Variable>Player, and select "Player".
Connect the "Fire At" Input to the player variable. Suddenly, you have created a bot (an enemy) who spawns in the trigger cylinder and then searches for the player. And if he's obstructed by something, he doesn't shoot, while if he's not obstructed he can shoot freely at the player.
Now, if you try your level, you'll see that sometimes the enemy spawns before the end of the countdown. This happens because the Trigger is already enabled and it doesn't wait for the end of the previous Kismet sequence. In order to activate this only when the countdown is finished, let's go to Kismet, select "Trigger Event Touch" and uncheck "Enabled" in its properties.
Then right-click (as always in Kismet), and go to New Action>Toggle and choose "Toggle".
Now connect the Output of the last Play Announcement Node to the "Turn On" Input of the Toggle Node, and the "Event" Output of "Toggle" to the "Trigger Touch Event". Now you have a Trigger Event that is enabled when the Play Announcement's sequence has ended.
InterpActor, StaticMeshActor and Brush events: These ones are similar to trigger ones, in fact these events are always activated by contact with an area, but in this case not with a cylindrical area, but with a custom area relative to the InterpActor(or StaticMeshActor or Brush) chosen. The only big change, apart from the different area with which you can enter contact, is that the Trigger is visible during game play, and you can make physical contact with it while playing.
Finally, we have arrived at InterpActor Events. For this type of event, we'll create a sort of division between the level and split it up into two parts, but in a singular way! So, go to the "Content Browser" and search for "thinwire", when the search is completed, double-click on "Thinwire16" and do a right-click in your level and select "Add InterpActor".
Now, search for "connector" and select the first result of your search, add this InterpActor twice.
Adjust these three elements as shown in the image below, to divide the room in two parts. (For this purpose, scale the thinwire in Y by 1.2)
With these elements still selected, press F4 to open the Properties.
Now, go to "Collision" and set the "Collision Type" to "Touch All".
What you've just done is put three InterpActor's in the level with a Collision Type set to Touch All. Which means that in this case, an event will be activated if the Player or someone else touches the wires or the connectors. Now, we must create this event! Select the three actors we've created, go to Kismet, right-click on a blank space, and go to "New Event using InterpActor…", and select "Touch".
Right-click in Kismet, go to New Action>Actor and select "Modify Health".
Select the "Modify Health" Node, and set the Amount of damage to 100 (player's life) you can also set the Damage Type to Crushed or Telefragged if you want a sound played when the Player receives the damage.
Now, right-click in Kismet, go to New Variable> Player and select "Player".
Connect the "Target" Input of "Modify Health" to this variable.
Connect all the "Touched" Outputs of the InterpActor Events to the "Modify Health" Node. Now, when someone touches the wires or the connectors, the player will die. Not so equal, but in this level the enemy doesn't move himself, he just stands right in front of you and shoots you, so he can't touch the wires. While the player must be careful when he himself moves.
There's still a problem to be fixed, if you die by touching the wires or the connectors and respawn, touching the InterpActor that just killed you, won't kill you again. That's because our Events are set to be activated only once. To fix this, go to Kismet, select all the InterpActor Event Nodes and go under "Sequence Events".
These properties are the same in every event's starting node: "Max Trigger Count" means how many times the Event can be activated. "Trigger Delay" means how long does an activation last before the next one. "Enabled" obviously means that if it's checked, the event is activated, otherwise it's inactive. "Priority" is useful when you have many events that start at the same moment, and finally "Player or Client Side Only" means who can activate this event. For our purpose, set the "Max Trigger Count" to 0 (infinite).
Finally, the level is complete, so, save, rebuild your level lighting and paths and you're ready to try the level!
Now right-click, and go to "New Condition" and select "Is Alive".
Connect the Finished Output to "Is Alive's" Input and connect the "True" Output to "Trace", and "Start Fire At" and the "Stop Fire" to "Is Alive's" Input. Also connect "Is Alive's" Player to the "Spawned" object. Now, you have finally fixed the error (just try!) and you're ready to play your level!