Getting Started with UDK – UnrealScript

us_demo_top

This post will be the most useful for those who have already read or are currently reading my latest book, Getting Started with UDK. In the book I go through how to create a Tower Defense game from scratch in UDK using Kismet and Scaleform to create custom GUI elements. I actually wrote a basis for this Tower Defense book as a series of tutorials that I wanted to put on my site before I wrote my first book but Packt asked me to hold onto it as they’d like to publish it…. which has now happened. I also had around ~60 pages I wanted to add to the book with additional features, pictures, and content that I felt would help the book, but I tried to jam pack as much as I could into the 140 page limit I was given without skimping on additional details.

That being said, for those that have read the book, what follows is an additional chapter which may allow you to do even more things with the project you created in the book or for those that are starting out with UnrealScript a bit of a quick guide. If you read my second book, Mastering UDK Game Development, you may notice the beginning of this being very similar to the beginning of Chapter 8, but I’ll be moving on to more advanced things later on this post. I’m not diving into too much details on the why things do what they do aside from my code comments, but if you have questions on anything, feel free to comment and I’ll be happy to elaborate and update the post. Without further ado, here’s a freebie after the jump:

Using UnrealScript

We have learned about a lot of things that aren’t covered very much elsewhere but to truly exploit UDK to its fullest potential you will have to touch UnrealScript.

UnrealScript (also known as Uscript) was a programming language developed and designed by Epic Games as a way for people to make it possible to modify what the Unreal Engine does without recompiling the engine’s source code which was made in C++, in this way it is similar to a scripting language such as Java, Lua, C#,  and Python however, it is not a scripting or interpreted language by the fact that you have to actually compile UnrealScript in order for changes to be made. For those familiar with object-oriented programming, UnrealScript shouldn’t be too difficult to pick up as most functionality is based on expanding code already written, but I’m sure that a majority of you have only touched UDK for the most part and are interested in learning more. If that’s the case, this chapter is for you!

If you have some experience coding in the past, I recommend reading this article from Cédric Hauteville explaining the differences between Java and UnrealScript.

Now, I could easily write a book about UnrealScript and how to use it, and Packt already has two books and a video series purely based on it (two of which I was a Technical Reviewer of)  which should you be more interested in it you are definitely welcome to pick up and I’ll also have links at the end of the chapter for references. If you’d like to see a great reference on UnrealScript, I suggest checking out the UDN’s UnrealScript Reference which you can check out here.

Introduction

In the game industry, it is not uncommon for designers to first implement something and make sure that it is fun to work with. While it technically works, designers typically aren’t as tech savvy as people hired as programmers in terms of making things efficient. This is perfectly fine for things such as one off events or things that are only going to happen in one level, but for things such as game mechanics that are used in multiple levels for the entire game it may not cut it, you’re going to want to program the functionality into the engine. Once the prototype is finished, they pass their work onto the programmers who will then write the code in an efficient way that can be used in multiple levels. In this chapter, we are going to take on the role of a programmer taking the previous Kismet provided to us by our designer and implement it in a more efficient fashion. In this chapter we will first gain an understanding on when to use UnrealScript for projects. We will then set up some tools to help us gain an understanding of the code that Epic provided and give some guidance on how object-oriented programming works. After that, we will learn about and install and IDE and write a simple “Hello world!” object. Then, after that we will move on to do another more complicated object recreating our turret’s behavior using UnrealScript and putting it back into our game!

Why Is It Awesome?

After this chapter you should have the fundamental knowledge to go out and create your own custom game types, objects, characters, and more within UDK. The code written in this chapter can also be easily expanded to create additional content such as multiple tower types and perhaps an Upgrade tree in the future.

Now with that all taken care of, let’s get down to buisness!

Installing UnCodeX

For newcomers and veteran programmers, reading someone else’s code is often the majority of your job, after all you don’t want to rewrite something that’s already provided to you (unless you have a reason to do so).

Having an understanding of the code base you’re working is paramount to writing code that doesn’t conflict with stuff that is written. In order to help you when starting out, I have two tools which you can use in your daily workflow to make your life much easier.

The first of which, is called UnCodeX. UnCodeX organized all of the 2000+ files that are located within our UDK’s Development\Src folder and displays them in a way that is easy to see relationships between classes.

Engage Thrusters

1. First, open up your web browser of choice (I personally use Chrome) and go to http://sourceforge.net/projects/uncodex/. Once there, click on the green Download button.

 5602OT_08_02

 

2. Once it has finished installing double click on the UnCodeX-v241-setup.exe file in your Downloads folder.

3. Go through the installer, and when you are finished make sure the Launch UnCodeX option is selected and select Finish.

4. You will then get a dialog box to pop up asking to change the settings, select Yes.

5602OT_08_03

5. At this point we will get the UnCodeX window to pop up with the Source Paths tab selected. Click on the Add button and select the Development\Src folder  within your UDK install path and then select OK. After this click on Yes on the dialog box that asks us to scan the directory.

5602OT_08_04

 

6. At this point you should see UnCodeX scan and organize all of the files within our folder and display them for us to see and enjoy.

5602OT_08_05

 

Objective Complete

UnCodeX has now been configured properly and is available for us to use!

Classified Info

Now, let’s go over what UnCodeX is actually showing us and what we can use it for.

The window on the left show each Package in our source and the classes contained in them. A package acts similarly to a folder in Windows in that it holds things that can be used. We’ve actually used packages already whenever we imported new content to our projects.

In the middle you will see the Class Tree, which organizes all of the objects based off of their relationship to each other.  You will see at the very top the Object class. This class is inherited by all other objects in UDK which means every object that is inherited from has all of the data and functionality that its parent has. All classes must be inherited from another class, with the exception of the Object which everything is built from.

The right window shows the actual code of whatever item we have selected. Unlike opening the file within a text file or our IDE you will notice some Hyperlinks located in the file. If you click on a hyperlink it will take you to wherever that class is instantly so there is no need to have to look around for things.

For those that are programmers, or know how to read code, I would suggest starting out by looking at the Actor, Object, Controller, Pawn, and Weapon scripts as that will explain how a lot of things are done within the engine gameplay-wise. If not, no worries I will be explaining things as we go along.

There are a lot of other functionalities within UnCodeX that are quite useful, but I leave that for you to explore; just know that as you get familiar with Unrealscript and write your own code, it will be quite a useful tool to bring into your workflow.

Sometimes when you’re coding you forget where that one specific variable is or are in general wanting to search for if something may exist or not and while you can search for things in UnCodeX, it doesn’t really make it obvious where something is aside from what line its one. Thankfully, there are tools that are there to help us with that exact thing.

Agent Ransack is a free file searching utility that looks for things exactly as you type them and will even show you exactly within code where your stuff is located bolding it and coloring it for you making it quite easy to see. It’s a  free download at www.mythicsoft.com/agentransack/ .

 

Setting up our IDE

Technically, all you need to write UnrealScript is a way to compile code (called a compiler) and a text editor of some sort such as Notepad and all of the code I will be providing will work perfectly fine with it. However, programmers are inherently lazy, (otherwise we’d still be writing in binary or assembly code) so over the years we have developed tools to make our lives easier. An Integrated Development Environment (IDE) is one such piece of software that provides a lot of functionality to make programming a much easier and enjoyable experience.

If you happen to get a job working in the game industry that happens to use Unreal as their engine (as a licensee), you’ll most likely use nFringe (http://pixelminegames.com/nfringe/) and Visual Studio (http://www.microsoft.com/visualstudio/eng/downloads) as your IDE of choice and while Visual Studio offers a free version it is quite expensive to use nFringe for commercial projects, even for an Indie game license.

With that in mind, we will be using an IDE that is free for use and contains most of the functionality that the other provides which is the appropriately named and open source Unreal Script IDE.

Engage Thrusters

1. First, go into the web browser of your choice and go to http://uside.codeplex.com/. From there click on the purple Download button.

 5602OT_08_06

 

2. Once it has finished installing double click on the UnrealScriptIDEInstall.exe file in your Downloads folder.
3. Say Yes to the question if you want to install the Unreal Script IDE.
4. Next you will see a question asking if you’d like to install the Microsoft Visual Studio 2010 Shell (Isolated) Redistributable Package to which you will hit Install and wait for the download to finish.

It kind of goes without saying, but you should have UDK installed prior to your installing of the Unreal Script IDE.

5602OT_08_07

5. Once the download completes you will be brought to the Visual Studio 2010 shell download. Uncheck the sending information to Microsoft if you’d like and then click the Next button.

5602OT_08_08

 

6. Accept the licence agreement and select to install the Full version of the program. When the installation completes, it will request for you to Restart your computer. Do so.
7. With your computer Restarted, double click once again on the UnrealScriptIDEInstall.exe file to enter the real installer.

 5602OT_08_09

 

8. Follow the installer until you see Select UDK Binary Win32 Folder section. At this point, make sure that you select the Binaries\Win32 folder  within your UDK install path and then select Next and complete the installer.

 5602OT_08_10

 

9. Now, go to your Desktop and double click on the Unreal Script IDE shortcut to start the program.

5602OT_08_11

 

Objective Complete

At this point we have our IDE installed and ready to be used! It may look a bit complicated at first glance, but just like UDK it’s very powerful once we learn a bit about how it’s used!

Classified Info

Now, before we start coding at all, it is important to go over some fundamentals on coding.

The Golden Rule

When dealing with UnrealScript the most important thing to remember is to never directly alter any code provided to us by Epic. A lot of the stuff they have done connects to C++ code within the engine to have the game work and may very well break the things that hold UDK together. All of the work that we will do and that you should do in the future should be from our own files that we created.

Code Commenting

When I formally sat down to learn how to code, I was stressed the importance of creating clean code that is easy for someone to sit down and understand what you are doing.

Commenting by using the /* and */ or // symbols removes whatever is written in-between the /* and */ or the whole line with //. This can be very useful in terms of having a certain piece of code not get called, but the primary use of comments is telling things to whomever may read your code (including your future self).

This way if you have to come back to a piece of code down the road, you have some idea of what you were doing previously or if you are asking for help on something you’re writing, making your code as readable as possible will increase your chances of being helped as finding the problem will be exceptionally easier.

You should always comment the code that you write. Programming at it’s very core is solving problems that have not been solved already. Code can only tell you how the program works; comments can tell you why it works.

That being said, it is possible to comment TOO much, or tell the reader something that is obvious or that can be understood easily. It’s all about finding a balance.

Though this is about C/C++, this article about how to go about commenting code is very good at explaining what is and isn’t worth commenting: http://www.cprogramming.com/tutorial/comments.html

“Hello world!” To UnrealScript

Now that we have all of the things required to write our code, it’s time for us to write our first program! Since it was first written 40 years ago, it has been a tradition for beginning programmers to write a function that display “Hello world” on the screen. Let’s do that now!

Engage Thrusters

1. Back in the Unreal Script IDE, go into the Solution Explorer on the right side of the screen. Under the UDKConfigProject1 section find the DefaultEngine.ini file and double click to open it. Hit Ctrl + F to go to the Find window and search for [UnrealEd.EditorEngine] . When  you get to that section add the line  +EditPackages=TowerDefScripts after the bottom of the +EditPackages.

You can use the Find window to search for things within a single file, or even all of the files within your two projects if you are trying to find something specific.

us_demo_1

2. We are now done with the UDKConfigProject1 so click on the down-pointing arrow on the UDKConfigProject1 in order to collapse it down. Next right click on the UDKSourceProject1 and select Add | New Folder which you will name TowerDefScripts.

us_demo_2

 

3. Right click on the TowerDefScripts folder and create another folder called Classes. After that right click once one on the folder and select Add | New Item… and then in the window that pops up under Name put MyGameInfo.uc then click Add.

us_demo_3

 

UnrealScript is built upon inheritance where code is built on top of already existing code so a lot of the time working in uScript is going to be reading existing code and picking the class that is the most similar to what you are trying to do and then extending it.

For our TowerDefense game, we are going to use the UTDeathmatch GameType as a basis since that’s the GameType we based our previous code upon.

4. Now you should see the left side of the screen now have a tab with our new filename and some code included on it. Replace all of that code with the following:

class MyGameInfo extends UTDeathmatch;
 
function StartMatch()
{
	// Do whatever the UTGame class does normally for the StartMatch function
	super(UTGame).StartMatch();
 
	// Execute our own code
	OurCode();
}
 
function OurCode()
{
	// Print a message to our program's log
	`log("Match Started");
}
 
//Any default values we want to be different than parent classes we set here
DefaultProperties
{
	bDelayedStart=false
}

StartMatch is called as soon as the first player joins the game, as you can see by looking at GameInfo.PostLogin. However, this only happens if bDelayedStart is false, whereas is is true by default.

This is mostly for a test to make sure that we can see that the code that we have created is actually going to run, we will be coming back to it later with some changes.

5. Now right click on the UDKSourceProject1 project and select Properties.

5602OT_08_15

 

6. Under the Properties menu add editor to the Additional Command Line Arguments.

5602OT_08_16

 

7. Start up the Editor now by Starting Debugging by either clicking on the green arrow button or pressing F5. This will compile the newly created UnrealScript that we’ve created and open the editor for us.

This is the same as creating a shortcut with the additional argument editor to it. With this you can do whatever else you can do using the Command line for with the UDK executable. Note that -log does not work as the output is captured by the IDE in the Output tab.

8. Now open up our map that we created for our project and inside of there go to View | World Properties. In the options there is a section called Default Game Type. Set it to “MyGameInfo” as well as in GameType for PIE.

us_demo_4
For those of you who have not read my book, feel free to pick up the example code that I provide at the book’s site, move the Chapter 4 files to your UDKGame\Content\Maps folder. Then open up the Content browser and open the packages that were created. Then open up the Chapter04_TDGame.udk file.

9. Now, go into the Unreal Script IDE and go into the  properties  of the UDKSourceProject1 project once more. Under the Properties menu replace what was there with “MapName.udk -resX=896 -resY=504″ in the Additional Command Line Arguments where MapName.udk is the name of your actual map.

In order for a map name to be passed as a command argument it has to be somewhere within the UDKGame\Content\Maps folder or something within it.

10. Start the program once again by either pressing F4 or pressing the green arrow. Press the green arrow again if the code pauses for a second. Now, once the game has started on the bottom right you should see a tab called Output. This is the debug output and where everytime you use ‘log where the output will go to. You’ll notice in the script:
Log:

>

[0015.92] Log: Bringing up level for play took: 0.018663
[0015.95] Cmd: SETSOUNDMODE Default
[0015.95] ScriptLog: START MATCH
[0015.95] ScriptLog: Match Started

 Note that the log may not appear inside of the UnrealScript IDE. If that’s the case, the logs are located within your UDKGame\Logs folder

Great! It’s looks like our “Match Started” text was indeed called as we wanted it to!

us_demo_5

 

Objective Complete

We have now written our very first program within UnrealScript and have a way of outputting information to ourselves. Though you may not think it, we’ve also learned a lot about how working with UnrealScript works.

Homing Missiles

You may notice in our current iteration of the tower defense game that occasionally the missles miss our enemies. Well, we really don’t want that to actually happen, so I wrote this Homing Missile class which should fix that for us.  We want the same behavior as before, except we want to add a few things, namely that it follows a target that we give it which we will do by changing the bullet’s Velocity and move it towards the target using the function VInterpTo.

1. Create a new class file called UTProj_HomingMissile.uc in the way described previously.

2. Now you should see the left side of the screen now have a tab with our new filename and some code included on it. Replace all of that code with the following:

class UTProj_HomingMissile extends UTProj_LinkPlasma;
 
var float  HomingInterpSpeed;
var float  EarlyHomingInterpSpeed;
var float  EarlyHomingTime;
var float  EarlyNoHomingTime;
var Vector HomingDirOffset;
var float  HomingDuration;
 
var Actor HomingTarget;
 
function Tick(float DeltaTime)
{
	//Do what the normal ShockBall would do
	super.Tick(DeltaTime);
 
	//And if we have a target, go towards it
	DoHoming(DeltaTime);
}
 
simulated function DoHoming(float DeltaTime)
{
	if(HomingTarget != none && `TimeSince(CreationTime) > EarlyNoHomingTime && `TimeSince(CreationTime) < (EarlyNoHomingTime+HomingDuration)) 	{ 		//Set our velocity to be traveling towards our target 		Velocity = VInterpTo(Normal(Velocity), 							 Normal(Normal(HomingTarget.Location - Location) + HomingDirOffset), 							 DeltaTime, 							 (`TimeSince(CreationTime) > EarlyHomingTime + EarlyNoHomingTime ? HomingInterpSpeed : EarlyHomingInterpSpeed))*Speed;		
	}
}
 
defaultproperties
{
	//Editor category for this object. Determines which Kismet submenu this object should be placed in
	ObjCategory="TowerDef"
 
	HomingInterpSpeed=20.5
	EarlyHomingInterpSpeed=50
	EarlyNoHomingTime=0.01
	HomingDuration=9999
	HomingTarget = None
	bCollideWorld=false
	Speed=1000
	MaxSpeed=1500
}

If you continue in the tutorial from here you will be unable to run the game for awhile as I will be referencing things that we haven’t created yet. I suggest you read everything through here before starting so that you understand what is going on.

Turrets Part 1 – The Base

Our turrets are going to be available for players to have at certain points by using the E key to activate them. Later we can have the players purchase them but right now our goal is getting functionality in first. Once a base is activated we will spawn a turret into the position of our base which will then be in charge of finding our enemies and attacking them.

So our first question is how to make an actor that can be used? Simple, we create a trigger that has a mesh attached to it.

1. First off, we are going to need to create our Base class by making a newfile called TurretBaseActor.uc:

2. Now you should see the left side of the screen now have a tab with our new filename and some code included on it. Replace all of that code with the following:

class TurretBaseActor extends Trigger;
 
// This will just create a turret of TurretOneClass.
function bool UsedBy(Pawn User)
{
 
    local bool used;
	local TurretOneClass a;
    used = super.UsedBy(User);
    //If it matters, you might want to double check here that the user is a player-controlled pawn.
    PlaySound(SoundCue'A_Pickups.ShieldBelt.Cue.A_Pickups_Shieldbelt_Activate_Cue');
 
	//Now Spawn the actual turret
	a = Spawn(class'TurretOneClass',,, self.Location, self.Rotation,,);
 
    return used;
}
 
//UnrealScript is case insensitive, so this is perfectly fine
DefaultProperties
{
 
	//Set the hidden values to true if you want to not see the sprite, I left them there for debugging purposes
    begin object Name=Sprite
        HiddenGame=false
		HiddenEditor=false
	Translation=(X=0.0,Y=0.0,Z=-50.0)//Moves the image from where it originally is as it would otherwise be inside the mesh
    end object
 
	Begin Object NAME=CollisionCylinder //Same as Trigger's code except I made the radius and height much larger
		CollideActors=true
		CollisionRadius=+1040.000000
		CollisionHeight=+1040.000000
		bAlwaysRenderIfSelected=true
		BlockZeroExtent=false
	End Object
	CollisionComponent=CollisionCylinder
	CylinderComponent=CollisionCylinder
	Components.Add(CollisionCylinder)
 
	//Create a new component with a name
    Begin Object class=StaticMeshComponent Name=MyMesh
		StaticMesh=StaticMesh'Pickups.jump_pad.S_Pickups_Jump_Pad'
		CollideActors=true
		Translation=(X=0.0,Y=0.0,Z=-150.0)
		Scale = 2.0 //Make the object twice as big as before
		bUsePrecomputedShadows = true; //So the object works with shadows in the enviroment
    End Object
 
	//Add that component to this object
    Components.Add(MyMesh)
 
    bBlockActors=true
    bHidden=false
	Translation = (X=0.0,Y=0.0,Z=0.0)
	bProjTarget=false // For the beam weapon to not autolock on us
}

Custom Player Controller Class

And now that we have this created, we are going to edit our Player Controller class to enable our useable objects to actually be useable.

Inside the PlayerController class there exists a function called GetTriggerUseList which will determine if Use events can be used or not, we’ll need to alter it.

1. Create a new class file called TowerDefensePlayerController.uc in the way described previously.

2. Replace all of the given code with the following:

class TowerDefensePlayerController extends UTPlayerController;
 
function GetTriggerUseList(float interactDistanceToCheck, float crosshairDist, float minDot, bool bUsuableOnly, out array out_useList)
{
	local int Idx;
	local vector cameraLoc;
	local rotator cameraRot;
	local Trigger checkTrigger;
	local SeqEvent_Used	UseSeq;
 
	super.GetTriggerUseList(interactDistanceToCheck, crosshairDist,  minDot, bUsuableOnly, out_useList);
 
	if (Pawn != None)
	{
		// grab camera location/rotation for checking crosshairDist
		GetPlayerViewPoint(cameraLoc, cameraRot);
 
		// search of nearby actors that have use events
		foreach Pawn.CollidingActors(class'Trigger',checkTrigger,interactDistanceToCheck)
		{
			for (Idx = 0; Idx < checkTrigger.GeneratedEvents.Length; Idx++)
			{
				//If we have a TurretBaseActor let's add it to the use list
				if (TurretBaseActor(checkTrigger) != None && (out_useList.Length == 0 || out_useList[out_useList.Length-1] != checkTrigger))
				{
					out_useList[out_useList.Length] = checkTrigger;
				}
			}
		}
	}
}
 
DefaultProperties
{
 
}

Turrets Part 2 – Tower

Now we are going to create our first tower class which I have named TurretOneClass. Basically, I created another trigger with a larger radius than before. When something touches the trigger that isn’t the player I set it as the target for it to kill. If the target leaves the radius of the turret, it is able to find a new target and it shoots the projectile that we created earlier.

1. Create a new class file called TurretOneClass.uc in the way described previously.

2. Replace all of the given code with the following:

class TurretOneClass extends Trigger;
var float fireTime;           // Time until we can fire again
var float timeBetweenFires;   // Time between fires
var Actor HomingTarget;       // Target for our bullets to go to
 
function Tick(float DeltaTime)
{
	//Do what the normal Actor would do
	super.Tick(DeltaTime);
 
	//check if our Target is dead
	if(HomingTarget != none)
	{
		if(UTPawn(HomingTarget) != none)
		{
			 if(UTPawn(HomingTarget).bPlayedDeath)
				HomingTarget = none;
		}
	}
 
	//Decrement our firetime by the length of this frame
	fireTime-=DeltaTime;
 
	//If it's time to fire a bullet, fire one and reset our timer
	if(fireTime < 0.0)
	{
		fireBullet();
		fireTime = timeBetweenFires;
	}
}
 
function fireBullet()
{
	local UTProj_HomingMissile Proj;
	local Vector myLocation;
	local Vector AtoB;
	local Vector direction;
 
	//Set the location we want to fire from to our tower's location
	myLocation = self.Location;
	myLocation.Z = myLocation.Z + 40; // Make it higher than the middle of the tower, but not too high
	if(HomingTarget != none)
	{
		//First we get the vector for A to B
		AtoB = HomingTarget.Location - myLocation;
 
		//Divide the vector by the magnitude of the vector to get the direction to travel in
		direction = AtoB/VSize(AtoB);
 
		//This will travel from the tower in the direction for a set distance (or else the bullet will be stuck inside the tower)
		myLocation = myLocation + (direction * 125);
 
		// spawn a projectile at the requested location and point it at the requested target
		Proj = Spawn(class'UTProj_HomingMissile',,, myLocation );
 
		//Initialize our turret, and give it the target to kill
		Proj.Init(Normal(HomingTarget.Location - myLocation ));
		Proj.HomingTarget = HomingTarget;
 
	}
}
 
DefaultProperties
{
	HomingTarget = none;
	fireTime = 0.0; 
	timeBetweenFires = .4; //How many frames before we shoot again
	bStatic = false;
	bNoDelete = false;
 
	// Colliding with this sets the target of the homing unless you are a player
	Begin Object NAME=CollisionCylinder LegacyClassName=Trigger_TriggerCylinderComponent_Class
		CollideActors=true
		CollisionRadius=+512.000000
		CollisionHeight=+128.000000
		bAlwaysRenderIfSelected=true
		BlockZeroExtent=false
	End Object
	CollisionComponent=CollisionCylinder
	CylinderComponent=CollisionCylinder
	Components.Add(CollisionCylinder)
 
	begin object class=StaticMeshComponent Name=MyMesh
	StaticMesh=StaticMesh'NEC_Deco.SM.Mesh.S_NEC_Supports_SM_BabelSpireA7'
	CollideActors=true
	Translation=(X=0.0,Y=0.0,Z=-170.0)
 
	CastShadow=FALSE
	bCastDynamicShadow=FALSE
	bAcceptsLights=TRUE
	bForceDirectLightMap=TRUE
 
	LightingChannels=(BSP=TRUE,Dynamic=FALSE,Static=TRUE,CompositeDynamic=TRUE)
	LightEnvironment=JumpPadLightEnvironment
 
	End Object
 
    Components.Add(MyMesh)
    bBlockActors=true
    bHidden=false
	Translation = (X=0.0,Y=0.0,Z=0.0)
	bProjTarget=false // For the beam weapon to not autolock on us
 
}
 
event Touch(Actor Other, PrimitiveComponent OtherComp, Vector HitLocation, Vector HitNormal)
{
	local Pawn Recipient;
	local Controller PickupController;
 
    super.Touch(Other, OtherComp, HitLocation, HitNormal);
 
	//If actor is a player we don't want to use him as our target.
	Recipient = Pawn(Other);
	if( (Recipient != None) )
	{
		PickupController = Recipient.Controller;
 
		//This may not work for multiplayer, but I have not been able to test.
		if ( (PickupController != None) && PickupController.IsLocalPlayerController() )
		{
			return;
		}
	}
 
    if (Pawn(Other) != none)
    {
		//If we don't already have one, we have a new Target
		if(HomingTarget == none)
			HomingTarget = Other;
    }
}
 
event UnTouch(Actor Other)
{
    super.UnTouch(Other);
 
    if (Pawn(Other) == HomingTarget)
    {
		//We are able to get a new Target
		HomingTarget = none;
    }
}

Custom Player Pawn Class

We will be doing other things in this later on, but for right now we just want the player not to die if they take damage from our towers. (After all, they’re friendly)

1. Create a new class file called TowerDefense_Player.uc in the way described previously.

2. Replace all of the given code with the following:

class TowerDefense_Player extends UTPawn;
 
event TakeDamage(int Damage, Controller EventInstigator, vector HitLocation, vector Momentum, class DamageType, optional TraceHitInfo HitInfo, optional Actor DamageCauser)
{
	//Shouldn't take damage from our towers but right now the player will not recieve any damage at all.
	//Doesn't matter now, but if we have the enemies fight player too, will need to adapt.
	//Super.TakeDamage(Damage, EventInstigator, HitLocation, Momentum, DamageType, HitInfo, DamageCauser);
}
 
DefaultProperties
{
}

Updating MyGameInfo

Okay, finally we need to add two lines to set some new default values within our MyGameInfo class:

1. Open up our MyGameInfo.uc file.

2. Replace all of the given code with the following:

class MyGameInfo extends UTDeathmatch;
 
function StartMatch()
{
	// Do whatever the UTGame class does normally for the StartMatch function
	super(UTGame).StartMatch();
 
	// Execute our own code
	OurCode();
}
 
function OurCode()
{
	// Print a message to our program's log
	`log("Match Started");
}
 
DefaultProperties
{
	bDelayedStart=false
	PlayerControllerClass=class'TowerDefScripts.TowerDefensePlayerController'
	DefaultPawnClass=class'TowerDefense_Player'
}

Change the Properties back to editor and press F5 to once again run the editor from our UnrealScript IDE.

 

1. Open up our previous map and resave it as a new file (always important to have backups especially when working with UDK).

2. The first thing that we are going to do is delete all of the previous things that we used in doing the towers. (The base, blocking volume, trigger, and trigger volume) This is because we are going to be replacing them with our own TurretBaseActors.  You will also delete all of the kismet nodes that we used previously that had to do with those objects.

3. To do this, left click on one of the Prefab objects that we created previously. With it selected, right click and select Select | Select Matching Static Mesh (This Class) then delete them by pressing the Delete key.

Remember, you can use CTRL+ALT and select multiple objects at a time to make it easier to delete the turrets (I used the top-down view)

us_demo_7

4. Now go into the Actor Classes menu and type “turret” into the search bar which will show you our TurretBaseActor.

us_demo_8

 

5. With it selected go to the level and right click and select “Add TurretBaseActor Here”

You should now see something that looks like a Trigger with a mesh in it. You will probably have to drop the object to fit the level correctly to have the mesh on the ground. If you were to compile and run the game now you’d be able to touch the object and it’d realize you did but we’d be unable to run our “Use” code.

6. To fix this, left click on the TurretBase and go open the Kismet editor. From there right click and select “New Event using TurretBaseActor_0 | Use” and besides creating it there is nothing else needed to do because the PlayerController and BaseClass is taking care of making the code work.

Or you can wait till you create all the TurretBaseActors and then with one selected right click and click on “Select All TurretBase Actors” then create a Use Event for each of them all at once.

us_demo_6

 

us_demo_11

 

After that, simply save your level, Build All, and then Run it!

Objective Complete

Now if you were to go into the game you’d be able to go up to a turret and hold the E key on it and upon that it will summon a turret which will attack an enemy when it comes into range!

Mission Accomplished

With this project, we should have a fundamental understanding on how powerful UnrealScript can be and a hint at what can be done with it, as well as a glance at tools that will make our lives much easier as UnrealScript developers. Let’s take one final look at our project:

us_demo_10

 

Classified Info

For those wishing to learn more about UnrealScript, here are some additional webpages that I recommend that you check out:

- The Unreal Developer’s Network has a whole entire section on their site devoted to UnrealScript at http://udn.epicgames.com/Three/UnrealScriptHome.html.
- Also on UDN, this is a great primer on creating UnrealScript and when to use certain parameters and what they mean. In particular the chapter on Classes in Unreal is recommended reading: http://udn.epicgames.com/Three/MasteringUnrealScriptClasses.html
- Once you feel confident enough, check out the UnrealScript Reference, also on UDK. It 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 and is located at http://udn.epicgames.com/Three/UnrealScriptReference.html
- Some frequently asked questions about coding in UnrealScript can be found at http://wiki.beyondunreal.com/Legacy:Unreal_Coding_FAQ
- And for those wanting to have more specific questions, Epic Games has a fairly large community which can be found at http://forums.epicgames.com/forums/367-UDK-Programming-and-Unrealscript.
- Packt has two books out solely about UnrealScript. I very much recommend this, and there is also this.

Depending on how this goes, I may start posting new tutorials up on my site to help others with UDK. Cheers!

No comments

WP SlimStat