Tutorials‎ > ‎

Import your Custom Weapon into 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 weapon mesh into UDK.  I leave room for you to explore with your own particle systems and effects, but our main focus is the weapon's 3D mesh.  Keep in mind that we'll be exploring the properties of ranged weapons such as the three main guns (link gun, shock rifle, and rocket launcher) and not melee weapons.  Perhaps I'll make a tutorial on that some other time.

Preparing your Gun (And Exporting It)

    The first thing you need to do after modeling your gun mesh is to set it up with the proper bones and skin your mesh to them.  If you want your gun to work with pre-made scripts (which, yes, we do actually), then the naming conventions of these bones are very important.  Since a gun is unlike a character in the sense that it does not need to move appendages, only identify key points, I used point objects (with the box shape checked for them) as my bones.

    There are four bones that are essential to every gun; b_gun_root, b_gun_barrelRoot, b_gun_barrel, and b_gun_lefthand.  As their name would imply, you place these points where they need to be on your gun (also, if you didn't already, it helps that your pivot point is where your right hand/trigger would be, as well as positioning this point of your weapon to the world's origin).

    You also have to link them to each other appropriately.  The b_gun_barrelRoot (child) and b_gun_lefthand (child) are both linked to the b_gun_root (parent).  The b_gun_barrel (child) is then linked to the b_gun_barrelRoot (parent).  There's no "special" link.  You can just use the simple link tool to do this.

Showing Ryan's Arrow gun with the bones in place.

    The mesh that I'll be using for my tutorial was modeled and textured by my friend, Ryan Allgeier.  Thanks, Ryan!  Once you have all of the bones of your gun in place, go ahead and add the skin modifier to your mesh and add the bones of your gun.  You do not have to weight anything because your gun will not being moving like a character.

    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 gun 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 FBX export settings for 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 gun later, you can just re-export and then re-import it later.  If you use the same naming conventions and just replace files, it will update to the newer file automatically.

Import your Gun

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 gun.  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."

    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.
    I've decided to import my gun to my package called "TessasPackage," in the group called "Skeletal_Mesh," and it will be named "RyansGun_1p."  Neither my package nor 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.

Adding Sockets

    In UDK, when you would create a character, that character would have bones driving their animations for walking, crouching, and even to feign death.  With weapons, UDK needs to you to identify the point on your gun where all of the pretty shooty effects come from, known as the Muzzle Flash.  Double click your newly imported weapon, and then open the Sockets Manager.

Showing the location of the Socket Manager button.

    The Sockets Manager button is the one that looks like an arrow is point down into a red bowl (I like to think of it as a little boat).  The first (and really only socket you need to progress in this tutorial) is the Muzzle Flash Socket.


    Click "New Socket"



    Choose the bone you want your socket connected to.  In this case, it's the "b_gun_barrel" (You can ignore the A at the end, because Ryan's gun had barrels A, B, and C, similar to the rocket launcher).



    Name the Socket "MuzzleFlashSocket" exactly like that.  This will be used in your scripting later.

    You can add the Grip socket if you'd like, it's attached to the "b_gun_root" bone, but I've found no significant purpose for this socket other than to make me feel good by putting more than just one socket on my gun to say I did something.

    Now when they put them on the bones, they may not be exactly in the correct place.  The Muzzle Flash Socket ought to be right where your flashy gun particle systems will emit from.  So you can edit the placement of your sockets after adding them to your gun.

Showing Ryan's gun (textured too) with the sockets in place.

    Ryan's weapon is textured in the above image, but don't worry about that right now.  Your next step is to turn your gun into two guns for scripting purposes!

First Person and Third Person Meshes

    In UDK, the game shows you a low poly, full version of the gun to spin around on it's little pedestal before you pick it up.  It also shows you a nice, higher poly gun when playing in first person (and it's usually not even the whole gun, but just the part you see is modeled).  In this tutorial, I'm not going to make you create two versions of the gun (you can do that if you want to though), but for the script to work, you need two versions in your package.

    So go ahead and duplicate your weapon, and change the name from "1p" to "3p" (hence the reason I named it "1p" when importing to begin with).  As you can see, I'm already making it so that I can tell which one I'm using for my first person mesh, and which one I'm using for my third person mesh.  A big difference in these two guns is actually the location within the world map.  Take a good look at the Rocket Launcher or Link Gun's 1P and their 3P versions.  You'll see they're facing completely different ways, and that the 1P version isn't even set at the origin!! (and don't use the Shock Rifle as an example, because they corrected it in the scripting which we won't go over)

    You can adjust your weapon's placement and rotation all in it's properties in the AnimSet Editor.  This is what Ryan's gun's properties were set to.

Ryan's First Person weapon was changed along the x, y, and z axis, and even had to adjust its yaw.

Ryan's Third Person weapon only needed to change it's yaw because it's grip was already at the origin upon exporting.

    Once you have your two weapons in the content browser set up, you're ready for the next step.

Scripting the Weapon

    You can close out of UDK (save your level and package, first!) for this step and open ConTEXT.  Weapons are by far the easiest to script in all of my tutorials.  You could actually do it all in just one script.  This is what my script looked like for Ryan's gun.

UTWeap_RyansGun.uc

class UTWeap_RyansGun extends UTWeapon;

defaultproperties
{
    Begin Object class=AnimNodeSequence Name=MeshSequenceA
        bCauseActorAnimEnd=true
    End Object

    Begin Object Name=FirstPersonMesh  // Weapon SkeletalMesh
        SkeletalMesh=SkeletalMesh'TessasPackage.Skeletal_Mesh.RyansGun_1p'
        AnimSets(0)=AnimSet'WP_LinkGun.Anims.K_WP_LinkGun_1P_Base'
        Animations=MeshSequenceA
        Scale=0.9
    End Object

    Begin Object Name=PickupMesh  // Pickup staticmesh
        SkeletalMesh=SkeletalMesh'TessasPackage.Skeletal_Mesh.RyansGun_3p'
    End Object

    AmmoCount=500
    LockerAmmoCount=500
    MaxAmmoCount=500
    
    WeaponFireTypes(0)=EWFT_Projectile
    WeaponProjectiles(0)=class'UTProj_Rocket'
   
    WeaponEquipSnd=SoundCue'A_Weapon_Link.Cue.A_Weapon_Link_RaiseCue'
    WeaponPutDownSnd=SoundCue'A_Weapon_Link.Cue.A_Weapon_Link_LowerCue'
    WeaponFireSnd(0)=SoundCue'A_Weapon_Link.Cue.A_Weapon_Link_FireCue'
    PickupSound=SoundCue'A_Pickups.Weapons.Cue.A_Pickup_Weapons_Link_Cue'

    MuzzleFlashSocket=MuzzleFlashSocket'
    MuzzleFlashPSCTemplate=ParticleSystem'WP_LinkGun.Effects.P_FX_LinkGun_MF_Primary'

    InventoryGroup=3

    AttachmentClass=class'myScripts.UTAttachment_RyansGun'
}
    The first highlighted piece of text is the same name as the file.  This is an important step because if it is not, the script will not work at all.  The next two pieces of highlighted text is where I've placed the location of ryan's guns into the script, "TessasPackage' being my package, "Skeletal_Mesh" being my group, and the last part is is the name of the mesh (the first being the 1p and the second being the 3p).

    The numbers I've highlighted are sort of self-explanatory.  They're the ammo counts and whatnot.  You can play with them as you please.  The last one I've highlighted is the projectile that is getting shot.  I'll go over with the projectile script next, but if you don't have one, then you can use any of the ones already in the game.  As you can see, this script is just using the Rocket Launcher's projectile, and since that script already exists, this script is finished and ready to be compiled.

    The last highlighted piece points to a script that does not yet exist.  You'll be making it in a later step (the step is optional, so if you don't create the script, then you can comment out the line or simply delete it from this script).

Scripting a Custom Projectile

    Creating a script for your custom projectile is a very similar process as the one for your weapon.  Below is my script:

UTProj_RyansArrow.uc

class UTProj_RyansArrow extends UTProjectile;

simulated function PostBeginPlay()
{
    // force ambient sound if not vehicle game mode
    bImportantAmbientSound = !WorldInfo.bDropDetail;
    Super.PostBeginPlay();
}

defaultproperties
{
    ProjFlightTemplate=ParticleSystem'WP_RocketLauncher.Effects.P_WP_RocketLauncher_RocketTrail'
    ProjExplosionTemplate=ParticleSystem'WP_RocketLauncher.Effects.P_WP_RocketLauncher_RocketExplosion'
    ExplosionDecal=MaterialInstanceTimeVarying'WP_RocketLauncher.Decals.MITV_WP_RocketLauncher_Impact_Decal01'
    DecalWidth=128.0
    DecalHeight=128.0
    speed=1000.0
    MaxSpeed=1000.0
    Damage=200.0
    DamageRadius=300.0
    MomentumTransfer=85000
    MyDamageType=class'UTDmgType_Rocket'
    LifeSpan=8.0
    AmbientSound=SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_Travel_Cue'
    ExplosionSound=SoundCue'A_Weapon_RocketLauncher.Cue.A_Weapon_RL_Impact_Cue'
    RotationRate=(Roll=50000)
    bCollideWorld=true
    CheckRadius=42.0
    bCheckProjectileLight=true
    ProjectileLightClass=class'UTGame.UTRocketLight'
    ExplosionLightClass=class'UTGame.UTRocketExplosionLight'

    bWaitForEffects=true
    bAttachExplosionToVehicles=false
}
    As you can see, I put in three different highlights in this code.  Except for the first blue highlight that highlights my new class's name (which should be changed for everybody depending on your naming conventions), all of the text highlighted in blue are variables that I recommend you changing if you're very new to scripting.  They're pretty self-explanatory and won't do much damage to the code if you really mess it up.

    The text highlighted in orange are bits of code that actually point to something you've uploaded to your package.  The first one is a particle system that shows the explosion from your gun's muzzle socket when it's initially fired from the gun.  The next one is the explosion decal, which is a temporary texture (usually a square in a the power of two) that gets thrown on objects when your projectile explodes on or near them, aka the "big burn marks."  The next two bits of code highlighted in orange are sound files that you can customize with your own here's-what-my-bullet-sounds-like-when-it's-coming-at-you as well as here's-what-my-bullet-sounds-like-when-it-hits-you!  Finally, the last two represent the lights associated with your projectile.  However, these are not pointing to objects in your package, but to two other scripts.  So you'd actually have to create new scripts if you wanted total and complete custom lights for it.

    Now the code that I've highlighted in green is very important.  This code points to a particle system that you've uploaded to your package.  If you've scripted for in-game objects before, then you may notice that this particular script does not point to a mesh object for your projectile.  That's because the mesh data is part of the particle system that you point to in this green code.  Below is the image of the Rocket Launcher's projectile particle system that's mentioned in the code above and where the mesh actually comes into play (you can see there are actually two mesh data's in this particle system).

Showing the Mesh Data within the particle system in UDK.  Click to view Larger.

    Now forgive me for not explaining to you how to create a custom particle system or incorporate mesh data into one such as this, because this is not that type of tutorial.  However, if you already know how to create particle systems in UDK, my above scripts will help you use them for your level.  If you're new to scripting, I'd start out with simply borrowing UDK's particle systems for your custom projectile.  When you're done with your projectile script, then you're ready to compile.

Weapon Attachment: What is That?

    This script, like the projectile script, is optional for your custom weapon to function.  It does, however, give you the option to customize your weapon a little further.  If you made your weapon script, compiled, and entered your weapon into the game, it should work fine... unless you play in third person.  Your weapon script only tells the engine what your weapon looks like when it's spinning around in the weapon locker or pick-up or what it looks like in your hands in first person view.  The attachment script takes care of what your weapon will look like in third person view (command: BehindView).  In the event that you never need to play in third person view, then you may not need this script.  Otherwise, your character may look like they're a magician and are shooting bullets out of their face.

    For a starting script, this is what I found in my research to work with, especially considering many of the UDK weapons do not have an attachment script.

UTAttachment_RyansGun.uc

class UTAttachment_RyansGun extends UTWeaponAttachment;

var ParticleSystem BeamTemplate;
var class<UTTExplosionLight> ImpactLightClass;//Works for this version of UDK
//var class<UDKExplosionLight> ImpactLightClass;//Works for new versions of UDK if the first one doesn't

var int CurrentPath;

simulated function bool AllowImpactEffects(Actor HitActor, vector HitLocation, vector HitNormal)
{
return (HitActor != None && UTProj_ShockBall(HitActor) == None && Super.AllowImpactEffects(HitActor, HitLocation, HitNormal));
}

simulated function SetMuzzleFlashParams(ParticleSystemComponent PSC)
{
local float PathValues[3];
local int NewPath;
Super.SetMuzzleFlashparams(PSC);
if (Instigator.FiringMode == 0)
{
NewPath = Rand(3);
if (NewPath == CurrentPath)
{
NewPath++;
}
CurrentPath = NewPath % 3;

PathValues[CurrentPath % 3] = 1.0;
PSC.SetFloatParameter('Path1',PathValues[0]);
PSC.SetFloatParameter('Path2',PathValues[1]);
PSC.SetFloatParameter('Path3',PathValues[2]);
// CurrentPath++;
}
else if (Instigator.FiringMode == 3)
{
PSC.SetFloatParameter('Path1',1.0);
PSC.SetFloatParameter('Path2',1.0);
PSC.SetFloatParameter('Path3',1.0);
}
else
{
PSC.SetFloatParameter('Path1',0.0);
PSC.SetFloatParameter('Path2',0.0);
PSC.SetFloatParameter('Path3',0.0);
}

}
defaultproperties
{
    // Weapon SkeletalMesh
Begin Object Name=SkeletalMeshComponent0
SkeletalMesh=SkeletalMesh'TessasPackage.Skeletal_Mesh.RyansGun_3P'
End Object

MuzzleFlashSocket=MuzzleFlashSocket
MuzzleFlashPSCTemplate(0)=ParticleSystem'WP_LinkGun.Effects.P_FX_LinkGun_MF_Primary'
MuzzleFlashColor=(R=255,G=120,B=255,A=255)
MuzzleFlashDuration=.33;
MuzzleFlashLightClass=class'UTGame.UTShockMuzzleFlashLight'
bMuzzleFlashPSCLoops=true
WeaponClass=class'UTWeap_RyansGun'
ImpactLightClass=class'UTShockImpactLight'
}

Note:  The text highlighted in green was added in by a user of this tutorial, Stephen.  He noticed the difference in a newer version of UDK.  So if the code above doesn't work, try un-commenting the green line, and comment out the line above it.

    I honestly don't know a whole lot about this script, but the bits highlighted in blue are pieces you'd need to change according to your weapon's naming conventions, except that particle system - you can leave it like that if you haven't made a custom one.  The skeletal mesh that we point to in the default properties is the third person mesh in your content browser.  The weapon class that is also mentioned in the default properties is simply the name of your weapon's main script (the very first one 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

    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.

Placing your New Weapon in the Level

    Now that all the codes are written and compiled, open up the UDK Editor (you can click on the "UnrealEd" button in Frontend for easy access) and load up your level.

    You can now use your weapon just like any other weapon.  Place a Locker or Pick-Up Factory in your level.  To do that, open the Content Browser, navigate to the Actor Classes Tab, scroll down and expand "Pickups", scroll down and expand "Weapon" and choose whichever one tickles your fancy.

Where to find the weapon pickups in the Actor Factory menu.

    If you're unsure of which one to use, the Pick-Up Factory can only hold one weapon type at a time, while the Locker can hold as many different weapon types as you deem fit (I wouldn't go for more than six for aesthetic purposes).

    With the Locker or Pickup Factory selected (I'm using the Pickup Factory as an example here), you can right click it and go into it's properties, or press the shortcut F4.  In the first section, "UTWeapon Pickup Factory", there is a field for "Weapon Pickup Class".  If everything worked properly, you should see your class in the drop-down menu.

My class, UTWeap_RyansGun, is in the drop-down menu for the Pickup Factory.


Et voila! Your weapon can now be picked up in the game!

Ryan's gun spinning around, untouched, in the weapon pickup factory.
Player using Ryan's gun in first person POV.

Use Your Custom Weapon as the Default Starting Weapon

    By default, the player starts out with a Link Gun.  If you navigate to, and open, the file located here:

... > Development > Src > UTGame > Classes > UTGame.uc

    Then scroll down to the "defaultproperties" section (line 3294), and you will find an entry like this:

DefaultInventory(0)=class'UTWeap_LinkGun'

    The zero actually refers to the first inventory slot (counting in programming starts at zero, not at one).  Instead of editing this script, I would recommend you create another script that changes your default inventory (this script will also be located in the "Classes" folder of your custom scripts.  What we'll be doing here is creating a new game type.  If you already have one, that's great.  You'll just need to add a few lines to it.  For example, my file will be called "TL_Game.uc" and this is what the script looks like:

TL_Game.uc

class TL_Game extends UTGame;

DefaultProperties
{
    //Establish Prefixes for Maps
    Acronym="TL"
    MapPrefixes(0)="TL"

    //Create Inventory
    DefaultInventory(0)=class'myScripts.UTWeap_RyansGun'
    //DefaultInventory(1)=class'UTWeap_LinkGun'
}

    The first text highlighted in orange is the script's name, as you should be familiar with by now.  The second text highlighted in orange is the name of the weapon's script.
    All of the lines highlighted in green are comments.  Anything followed by two slashes (//) are ignored by the program running this script.  If you remove the two slashes from the second "DefaultInventory" line, your player will be spawned by the custom weapon, and then be able to switch between that weapon and the Link Gun without having to pick up anything.
    The lines highlighted in blue I put in for funsies.  You may know that Death Match games have "DM-" in front of the names.  For example, you have the starter map DM-Deck.udk.  For my custom gametype, I put in "TL" so that any map I create using that prefix, it will have the properties outlined in this script.

    If you don't have a game type created, then you'll need to do this last step to get everything working.  Just like the engine needed to be told to compile your custom scripts, the engine also needs to be told to recognize your custom game type.  In the same folder that you found "DefaultEngine.ini", open up the file called "DefaultGame.ini" (In case you've forgotten the location, ... > UDKGame > Config > DefaultGame.ini)

    There are two ways you can do it.  You can make your custom game type the default game type (unless specified otherwise via prefix), or allow the default to remain as it is and include your game's prefix to specify the game type (or you can do both, it's really up to you.  I like doing both).

Note:  If you want your player to start off with nothing, simply use this:  DefaultInventory(0)=none

Make your Game Type the Default

On line 10 of DefaultGame.ini, you'll see this:   DefaultGameType="UTGame.UTDeathMatch";

Edit the line so that it says something like this:   DefaultGameType="myScripts.TL_Game";

    The next time you run the editor and/or the game, allow the scripts to recompile (or return to Frontend and manually compile them).  Your game type file will be important in the future if you plan on creating other custom content such as characters and enemies.

Recognize your Game Type's Prefix

    In the event that your game type is not the default game type, but you still want to access it, your script will look more like this:

DefaultGame.ini

  1. [Configuration]
  2. BasedOn=..\UDKGame\Config\DefaultGameUDK.ini

  3. [Engine.GameInfo]
  4. DefaultGame=UDKBase.SimpleGame
  5. DefaultServerGame=UDKBase.SimpleGame
  6. PlayerControllerClassName=UDKBase.SimplePC
  7. GameDifficulty=+1.0
  8. MaxPlayers=32
  9. DefaultGameType="UTGame.UTDeathmatch";
  10. +DefaultMapPrefixes=(Prefix="DM",bUsesCommonPackage=FALSE,GameType="UTGame.UTDeathmatch")
  11. +DefaultMapPrefixes=(Prefix="CTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTCTFGame_Content")
  12. +DefaultMapPrefixes=(Prefix="VCTF",bUsesCommonPackage=FALSE,GameType="UTGameContent.UTVehicleCTFGame_Content")
  13. +DefaultMapPrefixes=(Prefix="TL",bUsesCommonPackage=FALSE,GameType="myScripts.TL_Game")

Just add in line 14 with your game type's script and prefixes.

I hope this tutorial was helpful!
Comments