Tutorials‎ > ‎

How to Create a Custom Enemy in UDK


Programs Required:

  • UDK Editor:  The September 2011 version is being used in this tutorial
  • Unreal Frontend:  Start Menu > All Programs > Unreal Development Kit > Whatever Version You Have > Tools > "Unreal Frontend"
  • 3D Modeling Program:  3D Studio Max 2012, Student Version, is being used in this tutorial
  • A program that can read UDK Script:  ConTEXT is being used in this tutorial (Download ConTEXT for Free)
    This tutorial will explain how to import your own custom mesh into UDK and use it as an enemy and not as a player.  This tutorial uses the default animations in UDK and does not show you how to create your own animations.  With that said, I'd recommend using a bipedal, humanoid character.

Create Your Enemy's Mesh

    Now I won't walk you through on how to create a character, there are plenty of tutorials (like this one, this one, and this one) about that.  However, it is important that you build your character in proportion to the skeletons provided by UDK.  Below are the master skeleton 2009 max files generously provided by EpicGames.

UT3_Male.max (Recommended)
UT3_Female.max
UT3_Krall.max
UT3_Corrupt.max

    When you're done creating the 3D mesh of your character, you'll want to skin him/her/it to the correct bones (again, I'm not teaching you how to skin a character in this particular tutorial).  Now pay attention because there are literally two sets of bones and you need to make sure you're skinning the correct ones!

    Click on the button "Manage Layers..." (found on top right of your main toolbar in 3Ds Max).  Expand the layer named "0 (default)" and you'll see a big list of all of the stuff in the scene.  You'll notice there are bone objects that start with "b_blahblah" and "Bip01_blahblah".  Skin your character to the bone objects that start with "b_".

Showing the Layers window with the differently named bone objects.

    When your character has been modeled and skinned (and textured if you want to go that far, but it won't be covered in this tutorial), then you're ready for the next step.

Exporting The Mesh

    Recently, UDK has stopped supporting the ActiveX plugin (if you're familiar with it).  Fortunately, they started supporting the FBX file type - so that's what we will be using.  Select only your character mesh (you can collapse it's modifiers so it's only "Edit Poly" if you want to, as long as it has been skinned at some point, that data will be stored).

    In the same place where you'd save file, instead go to "Export > Export Selected..." and save it out as an FBX file.  Another window will prompt you for your export settings.  At this point, I only check "Geometry > Smoothing Groups."

Showing the export settings, checking smoothing groups.

    Hit OK and you're ready for the next step.  You can close out of 3D Studio Max if you want.  If you ever make changes to your character later, you can just re-export and then re-import him/her/it later.  If you use the same naming conventions and just replace files, it will update to the newer file automatically.

Importing The Mesh

    Now you're ready to start working with the UDK editor.  Open it up and go to your level.  At this point, I am assuming that you either have your own level and package started or you're working with one already made.  In any case, you need to decide where you want to import your character to.  This is important information that you'll need to know later when you start scripting.  For the sake of the tutorial, the name of my package is going to be "TessasPackage" (haha, she said she had a package!).

    Open your Content Editor (if it's not already open) and hit the huge button on the bottom left that says "Import."  Use the browsing window to navigate to your FBX file and hit ok.

Showing the import settings, specifically looking at the Package, Grouping, and Name.

    I've decided to import my character to my package called "TessasPackage," in the group called "Skeletal_Mesh," and it will be named "BossMan."  Neither my package or it's group have been created, but they will be upon importing this object.  Save your package (I commonly save mine to the "TestPackages" folder).  You now have enough ready to begin the next step.

    You can always return to to your object within the Content Editor to edit your character later (such as applying a material to the character mesh, adjusting his/her/it's position and rotation within the world, etc.)  You can exit out of UDK too, as long as your package is saved.  We'll come back to it in step 5.

Scripting Your Enemy's Codes

    For me, this was the fun part!  In this step, we have to create some working scripts so that the editor will be able to use your character and define properties that your character can possess.  So now, open up ConTEXT.

Let's start with this first script; it's job (for us) is just to point out that your mesh is to be used as a pawn/bot/enemy and not a playable character.

 TessasPawn_NPC.uc
 
class TessasPawn_NPC extends UTPawn
  placeable;
   
var(NPC) SkeletalMeshComponent NPCMesh;
var(NPC) class<AIController> NPCController;

simulated event PostBeginPlay()
{
  if(NPCController != none)
  {
    //set the existing ControllerClass to our new NPCController class
    ControllerClass = NPCController;
  }
   
  Super.PostBeginPlay();
}

//override to do nothing
simulated function SetCharacterClassFromInfo(class<UTFamilyInfo> Info)
{
}

defaultproperties
{
  //Setup default NPC mesh
  Begin Object Class=SkeletalMeshComponent Name=NPCMesh0
    SkeletalMesh=SkeletalMesh'TessasPackage.Skeletal_Mesh.BossMan'
    PhysicsAsset=PhysicsAsset'CH_AnimCorrupt.Mesh.SK_CH_Corrupt_Male_Physics'
    AnimSets(0)=AnimSet'CH_AnimHuman.Anims.K_AnimHuman_BaseMale'
    AnimtreeTemplate=AnimTree'CH_AnimHuman_Tree.AT_CH_Human'
  End Object
  NPCMesh=NPCMesh0
  Mesh=NPCMesh0
  Components.Add(NPCMesh0)

  //Points to your custom AIController class - as the default value
  NPCController=class'TessasBot'
  SuperHealthMax=300
}

    I've highlighted parts of the script that you should change according to your naming conventions.  The first one "TessasPawn_NPC" is the same name as the file.  That is a very important step because the script will not work otherwise.

    The second highlighted part points to my mesh within my package.  Remember, "TessasPackage" is the name of the package that I saved my mesh, "Skeletal_Mesh" is the group, and finally "BossMan" is what I named it.

    The second to last highlighted part is actually pointing to a script we did not make yet.  When creating an enemy, you need a script to point to the physicality of the enemy and a script to control it's artificial intelligence (AI).  "TessasBot" is the name of the script that controls my enemy's AI.  We'll be doing that next.  The 300 is just what I wanted my enemy's health to be.  If I give mine more health, BossMan be a bit harder to kill.

    This next script controls the AI of your custom enemy.

 TessasBot.uc
 class TessasBot extends UTBot;

var Actor Destination;

protected event ExecuteWhatToDoNext()
{
  //Go to the roaming state
  GotoState('Roaming');
}

state Roaming
{
Begin:
  //If we just began or we have reached the Destination
  //pick a new destination - at random
  if(Destination == none || Pawn.ReachedDestination(Destination))
  {
    Destination = FindRandomDest();
  }

  //Find a path to the destination and move to the next node in the path
  MoveToward(FindPathToward(Destination), FindPathToward(Destination));

  //fire off next decision loop
  LatentWhatToDoNext();
}

defaultproperties
{
}

    I did not make any changes to this script except for the fact that it exists as my custom AI script.  However, this at least opens the opportunity for you to tamper with it later if you're into doing more research regarding AI scripting.  This script is functional for our purposes, at least.

    So now that we have two scripts that make our enemy functional, this final script is to tell the editor that we should use it.  Essentially, we are defining a new game type, but we're using all of the other game's properties that we're technically only making one difference - using our custom enemy.

 TessasGame.uc
class TessasGame extends UTDeathMatch;

defaultproperties
{
    DefaultPawnClass=class'TessasPawn_NPC'
}

   
This is a very short and easy script.  We simply rip off of the DeathMatch's game since my game is actually a single player game and these are the scripts for my final boss.  We also make sure to point to the first script we made.

Compiling Your Scripts

    Now after all of your scripts have been made, you need to save them.  If you've noticed, all of my scripts were titled with the ".uc" extension.  So when you save out your script, save it as the name of the class you're creating with .uc as the extension.  This is the script file type that is special to UDK (just as a PSD is special to photoshop, DOC is special to microsoft word, etc.).  Once they're saved, put your scripts in the following location:

My Computer > Local Disk (C:) (or where ever you installed UDK) > UDK > UDK-2011-09 (or whatever version you have) > Development > Src > YourCustomFolder > Classes > YourCustomFiles.uc

Note:  A lot of tutorials will tell you to create your own folder, including mine, to put all of your custom scripts in because it makes for better practices and organization, but I've found that to be troublesome sometimes for newer programmers.  If you find yourself having compiling issues because it's not finding your custom scripts, then place your scripts with UDK's for now.  It's not the best practice, but it should help it work.  If you still find some errors, then it's a possibility that you're extending a class that is being compiled after yours (think alphabetically), so rename your class so that it gets compiled last.

My Computer > Local Disk (C:) (or wherever you installed UDK) > UDK > UDK-2011-09 (or whatever version you have) > Development > Src > UTGame > Classes > YourFilesHere.uc

    For example, my custom folder will be called "myScripts".  Once that is created, you need to tell the engine to compile your scripts.  Navigate to, and open the file:

My Computer > Local Disk (C:) (or where ever you installed UDK) > UDK > UDK-2011-09 (or whatever version you have) > UDKGame > Config > DefaultEngine.ini

    Scroll down to the section labeled [UnrealEd.EditorEngine] (line 25 if it's not been edited before).  By default, the section has two "EditPackages" to be compiled, UTGame and UTGameContent.  You want to add a line similar to theirs that points to your scripts.  So, beneath both of those lines (if you press enter after "UTGame Content, your line number will be 28), add in "+ModEditPackages=myScripts".  The section should look like this:

DefaultEngine.ini

23.     ...etc.
24.     
25.     [UnrealEd.EditorEngine]
26.     +EditPackages=UTGame
27.     +EditPackages=UTGameContent
28.     +ModEditPackages=myScripts
29.
30.     [Engine.Engine]
31.     ... etc.


Now we have one final step that deals with scripts!  You have to compile them.  You can close ConTEXT after all of your scripts are saved and in their proper places, and open Unreal Frontend.  When it's opened, just hit the scripts button, and then compile scripts.

Showing the location of the Compile scripts button in Unreal Frontend.

    Hopefully you are not met with any errors or warnings, and happily greeted with a big giant, SUCCEEDED!  If that's the case, then you can just hit the button "Unreal Ed" and it will initiate the editor.  You can close out of Frontend now.

Spawning Your Enemy Using Kismet

    Finally, all of the tricky stuff is done.  All you have to do is set up the spawn point and spawn your enemy!  Create a pathnode (right click > Add Actor > Add Pathnode) in your level.  The placement and rotation will act as the spawn position and rotation for your enemy.  Now open up the kismet screen.

    With the pathnode in the level selected, right click in the gray Kismet stage and choose "New Object Var Using PathNode_0" (or whatever number of pathnode it is).  Now right click the gray Kismet stage again, and this time, choose "New Action > Actor > Actor Factory."  Link the "Spawn Point" on the bottom of your Actor Factory box to the little circle that represents your PathNode.

    When you have the Actor Factory selected, you can see it's properties in the lower left corner of the Kismet window.  You can see all of the properties I tampered with show up in bold text.

Showing the properties I changed for the Actor Factory.

    I changed the "Factory" (that was previously none) to "UTActorFactoryAI."  Extend it to see it's properties (click the arrow next to "Factory").  I marked "Force Deathmatch AI."  This makes your enemies fight back.  I also changed the Controller Class to "TessasBot" (yours should also appear in the drop-down menus now) as well as the Pawn Class to "TessasPawn_NPC".  I typed in a name for my Pawn, this is the name that appears when you kill it (Player kills Evil Enemy, for example).  I checked "Give Default Inventory" so the enemy will have a gun and changed their team index to 1 (the red team because player always spawns on blue).

    You'll see I also put a little Obj Comment and checked the box beneath it.  That just means when he/she/it is spawned, that text will show up in the bottom left corner of the screen during gameplay.

Once all of your settings are good, there is one more thing.  You need an event to trigger your action.  I simply just made it so my enemy will trigger at the start of the level by right clicking the gray Kismet area, "New Event > Level Loaded" and then linked that event to my spawn box like the picture below.

Showing how my Kismet event is linked to my Actor Factory.

    Now if you play your level, your custom enemy will spawn at the point where you placed that PathNode at the beginning of the level!  Of course, you can use all sorts of other triggers to spawn your enemy, depending on your design.

Hope this tutorial helps!!! (:
Comments