Tutorials‎ > ‎UDK Melee Weapons‎ > ‎

UDK Melee Weapon Tutorial Part 3


Wrapping It Up

This is the final part in this tutorial series. We’ve covered the “meat and potatoes”, and now it’s time for the “dessert”. We have all the logic in place for the player to swing a melee weapon and hit things with it, but right now it doesn’t actually look that cool. We need animations, particle effects, sound effects – all those things that make a game entertaining to watch. In this final part of the series, we’ll go over how to import animations into an AnimSet and how to use those animations in our AnimTree. We’ll attach a swinging “slash” particle effect to our sword and go over how to activate it from within code. Finally, I’ll show you how to play a sound effect when the sword collides with something.

AnimSet

We’re going to create a new AnimSet that contains three animations – an idle animation, and two swing animations (because we’re allowing the player to swing twice). You’re free to create your own animations or you can use the sample ones I’ve provided (note that they aren't very good, I just needed something quick and dirty for this tutorial). Navigate to the MeleeWeaponContent package in the Content Browser, and right click in the content area. Select the entry for “New AnimSet”. For the grouping, type in “Animation” and for the name type “MeleeWeaponAnimSet”. When the AnimSet Editor opens, select the SK_CH_IronGuard_MaleA skeletal mesh.

Next, click the “Anim” tab to start importing your animations. Click on File -> Import FBX Animation and select the Idle.fbx (or whatever idle animation you made) and the two swing animations (SwingOne.fbx and SwingTwo.fbx). You can preview the animations by selecting them and hitting the play button below the preview window. Close the AnimSet editor and save your new AnimSet.

AnimTree

AnimTrees can be very involved and complicated and mostly out of the scope of this tutorial. For our purposes, all we need is a simple PlayCustomAnim node, an AnimNodeSequence for our idle animation, and a blank AnimNodeSequence to attach to the Custom input of the PlayCustomAnim node. If you need more information on AnimTrees, Wraiyth has an excellent video tutorial series that covers them in depth.

To create an AnimTree, right click in the content area of the Content Browser and click “New AnimTree”. Put it in the “Animation” group and call it “MeleeWeaponAnimTree”. Click on the AnimTree node and expand the “Anim Tree” category in the properties window below. Add a new item to the Preview Mesh List and go find the Iron Guard skeletal mesh in the Content Browser. Select the mesh and click the green arrow to bring it in. Add an item to the Preview Anim Set List and add a new item to the Preview Anim Sets item under the Preview Anim Set List. Select our newly created AnimSet and use the green arrow to bring it in.


You can change the Display Names if you want, but it’s not really necessary. Next, we’re going to create a new AnimNodePlayCustomAnimation. Right click in the work area and select New Animation Node -> AnimNodePlayCustomAnim. We need to rename this node so that we can access it from within our code, so with the custom animation node selected, expand the Anim Node section in the properties window and type in “SwingCustomAnim” in the Node Name property.

Next, we need to create two animation sequences – one for our idle animation and a blank one that basically gets assigned at runtime in code. Right click in the work area and select New Animation Sequence -> AnimNodeSequence. Select the node and expand the Anim Node Sequence section in the properties window and type in “Idle” for the Anim Seq Name property. The engine will search through our selected AnimSet and use the Idle animation for this sequence. Create another animation sequence node, but leave the Anim Seq Name property blank. Finally, connect the Idle sequence to the input labeled Normal on the custom anim node, and the blank sequence to the input labeled Custom. Finish it up by connecting the custom anim node to the AnimTree node. Close the AnimTree editor and save the package.

To assign the new AnimSet and AnimTree for our pawn to use, we just need to open up the MeleeWeaponPawn archetype and change the Anim Tree Template and Anim Sets properties in the Skeletal Mesh Component section to point to the new ones we just made. Save the package and close the editor.

Animations In Code

In order to access these animations from within our code, we need to grab the custom anim node so we can play the animation. Luckily, the custom anim node is stored in our pawn’s mesh, we just have to search for it by name and store it in an AnimNodePlayCustomAnim variable in our pawn class. Add this to your MeleeWeaponPawn class:

var AnimNodePlayCustomAnim SwingAnim; ... simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp) {     super.PostInitAnimTree(SkelComp);     if (SkelComp == Mesh)     {         SwingAnim = AnimNodePlayCustomAnim(SkelComp.FindAnimNode('SwingCustomAnim'));     } }

Now that our pawn has a reference to the custom anim node, we’re going to want to play one of our swing animations when we make the call to swing our sword. As any good programmer knows, there are always several ways to do things, and that is certainly the case here. We could write some states for our pawn and play the animation according to which state the pawn is in, or we could handle the animations entirely in the Player Controller class, but for simplicity’s sake and the purposes of this tutorial, I’m just going to do this in the MeleeWeaponSword class whenever we swing the sword instead. Normally I subscribe to the software design philosophies of the Single Responsibility Principle and the Law of Demeter, but for this simple demonstration and in order to keep this section short, I’ll bend the rules a little.

So that being said, add this grotesquely out-of-place code to your MeleeWeaponSword class' FireAmmunition function. Place it inside of the HasAmmo check just above the call to the Weapon class’ FireAmmunition function:

if (MaxSwings - Swings[0] == 0) {     MeleeWeaponPawn(Owner).SwingAnim.PlayCustomAnim('SwingOne', 1.0); } else {     MeleeWeaponPawn(Owner).SwingAnim.PlayCustomAnim('SwingTwo', 1.0); }

The first parameter is the name of the animation to play. We want to choose between SwingOne and SwingTwo according to how many swings we have left in our Swings array (our “ammo”). So we take the MaxSwings (2) – number of swings we have left to decide which one to play. We have to place this call before we’ve called the Weapon class’ FireAmmunition function so that we don't use one of our swings before, otherwise it would never be zero. It also has to go inside the HasAmmo check because we don’t want to play the animation if the player has already used up both swings. The second parameter is the rate to play the animation. You can also add some blend in and blend out times, but I found the animations that I'm using play better without them.

Now if you launch a level and click the mouse, you’ll see the player swing his sword. Note that in order to swing the second time, you have to double click and hold the button down on the second swing. The reason it won’t work if you let go of the button is because in the DefaultInput.ini configuration file, the StopFire function gets called OnRelease of the mouse buttons. You can change this in the configuration file by simply removing the OnRelease command from the GBA_Fire binding. Or, if you’re using PSMU, you can overwrite the binding in the MeleeWeaponInput.ini file.

Particle Effects

We want a nice little trail to stream behind our sword when we swing it. Different game engines handle the “trail” effect in different ways – some attach a static sprite to the mesh, others spawn particle effects behind the mesh. For a spaceship dog-fighting game I worked on in college called “The Last Pod Fighter” using the XNA game engine, I accomplished this effect by generating a colored vertex strip from the ships’ engines with a directional billboard. The UDK engine has it’s own way of doing this using what they call an AnimTrail, and it’s the first time I’d ever heard of it being done this way.

The idea behind the AnimTrail is basically to attach the particle effect to the mesh using three control points which tell the particle effect how wide it should be and how to map the UV’s along that width. The information that the particle effect needs (such as location, bill-boarding orientation, etc) actually gets updated through the use of AnimNotifies in the animation of the mesh. The first thought that came to my mind when I read about this was “the animation is coming from the player, not the sword, so how can I notify the sword to update the trail if it doesn’t have an animation?”

After some thought, I realized that I sort-of answered my own question – give the sword an animation. It doesn’t actually have to move, but if I give it an animation to play, I can set up a notify on that animation. So I busted out some Maya-Fu and quickly made the easiest animation I’ve ever done – two key-frames one second apart with no movement at all! :)

By now you should know how to make an AnimSet and and AnimTree for your sword. I saved mine in the Animation group with the names “MeleeWeaponSwordAnimSet” and “MeleeWeaponSwordAnimTree”. Note that in your AnimTree you won’t need a PlayCustomAnimNode, just one animation sequence named “SwordAnim” (if you’re using my animation) connected straight to the AnimTree node. To use this new animation, assign the AnimTree and AnimSet to the Anim Tree Template and Anim Sets properties in the Skeletal Mesh Component section of the MeleeWeaponSword archetype.

AnimNotify_Trails

The only thing left to do is set up the AnimNotify and attach an actual particle effect to our sword’s animation. Open up the MeleeWeaponSwordAnimSet and select the AnimSequence tab in the properties window. Expand the Anim Sequence section and add a new object to the Notifies list. Click the blue down arrow next to the Notify property, and select AnimNotify_Trails. This is the type of notify that the animation will fire.


For the PSTemplate, there is an example particle effect already made for sword trails in the UDK called “P_SwordTrail_01″, so we’ll just use that one instead of creating our own. We’ll leave the First Edge, Control Point and Second Edge Socket Names at their default values because those are the names of the three sockets on our sword mesh. We want the duration of the effect to last the entire animation, so under duration enter “1″. Now if you play the animation, you won’t actually see anything happen in the preview mode because the sword isn’t actually moving.

In our code, we need to add two lines in order to play the sword’s animation when we swing it. At the top of the MeleeWeaponSword class, add this variable:

var() const name SwordAnimationName;

This is where we’ll assign the name of the animation in the archetype. In the FireAmmunition function just below our call to play the pawn’s animation and still inside the HasAmmo check, add this line:

PlayWeaponAnimation(SwordAnimationName, GetFireInterval(CurrentFireMode));

We pass in the name of the animation to play and a duration. We don’t want to spawn the trail for the full one second of the animation, just the length of the swing animation (which I set up to be the same length as the fire interval). Compile the scripts, launch the editor, open up the MeleeWeaponSword archetype and type in “SwordAnim” for the SwordAnimationName property. Now when you swing your sword, you’ll see a nice white smokey trail behind it.

You might notice (depending on your system) that it doesn’t quite attach to the sword. There is a property in the particle system that supposedly helps with this and can be adjusted in cascade. You can uncheck the “Clip Source Segement” property in the Trail section of the AnimTrailData module to attach the effect to the sword. I didn't really notice any improvement, but this could just be based on my system.

Sound Effects

Sound Effects are very simple to implement in Unrealscript. All you need to do is assign a sound effect to play in the archetype and simply play it when you want in code. Add this variable to the top of your MeleeWeaponSword class:

var() const SoundCue SwordClank;

A SoundCue object is actually a collection of sounds. Playing the SoundCue will select one of those sounds to play randomly. If you wanted, you could make an array of SoundCue objects and select which one to play based on what material it collides with. For the tutorial, we’re just going to keep it simple and use one SoundCue.

Next, add this line to the TraceHit function just below the call to TakeDamage:

PlaySound(SwordClank);

That’s it for the code. Now we just need to go find a sound to play and assign it in the MeleeWeaponSword archetype. Compile the scripts, launch the editor and open up the Content Browser. To make the search easier, filter the content by "SoundCue". There are tons to choose from, but I’m going to use the A_Vehicle_Generic.Vehicle.VehicleImpact_MetalSmallCue because in my level, I’m batting around a metal barrel. Assign the Sound Cue in the archetype and you should hear a metal clank any time your sword hits an actor.

That does it for this series. Where you go from here depends on what kind of game you're making, but I hope that this has helped to point you in the right direction. Thanks for reading and I hope you enjoyed it.