You guys requested melee tutorial and I’m right after game jam where my colleague (cheers Tomek!) did really simple but powerful melee weapon. This tutorial will be about:
- How to do melee damage,
- Create basic weapon class to drive melee damage,
- Weapons can be added to AI characters as well and they will do melee damage to others as well (Player and other AI)
- There will be two versions: one without any additional preparation and second one in which you need to add sockets to weapon mesh.
So, lets go!
In this tutorial I have used Animated Medieval Bludgeoning Weapons Pack which basically isn’t needed in this tutorial but with animations it’s easier to show you guys how to do melee damage. (btw hope Ironbelly will do more first person medieval animations like two handed swords, dual weld weapons etc.
So basically what you need is:
- Weapon Mesh – as skeletal mesh,
- Hands with some animation because information when to start/end melee will come from animation,
Base Weapon Class
Create new Blueprint extending from Actor named BP_BaseWeapon. For now leave it blank.
Structure with weapon data
It isn’t needed for melee but I would like to show you guys how I’m creating weapons to be easy modified by designers.
Create new structure named FWeaponInfo and add those variables:
|Damage||float||Base damage for weapon. Default 1.|
|DistanceModifier||float||Melee range modifier for this weapon. It’s important that default will be 1.|
|WeaponMesh||Skeletal Mesh||Reference to Skeletal Mesh weapon. Default should be leaved as blank.|
Basically here you can put all of your mesh statistics and data which you are interested in. (eg. UI texture reference, weapon type enum, attack speed etc)
Data Table to store all weapons data
After creating structure create new Data Table:
Which will use FWeaponInfo:
Pick some name for your Weapons Data Table.
Open it and add one weapon. Make sure it will have Skeletal Mesh assigned to WeaponMesh.
Why you should use DataTables? It’s really fast to iterate while using them. You can have one folder in your Content named Data with all of your data tables (eg. enemies stats, perks, level informations) so people won’t be searching in your code / blueprints to change some variable they will have one place with all of them.
You can find more information about Data Tables here.
Next create new Blueprint Interface named IDamage. It should have two functions:
TakeDamage – with 3 inputs:
- Damage, float
- HitResult, Hit Result
- Instigator, Actor Reference
And GetHoldingWeapon function with one output:
- Weapon, BP_BaseWeapon reference
Interfaces are used to communicate between classes. You can create function with output as well which is super useful.
Weapon Class / Melee Here
Now go back to your BP_BaseWeapon and add some variables:
|WeaponInfo||FWeaponInfo||This will store weapon information which will be populated from Data Table.|
|WeaponInDataTable||DataTableRowHandle||This is the link to Data Table and specific weapon. Make sure you have selected your data table and pick some weapon!|
|isInAttack||bool||This bool will represent if this weapon is in attack and we should trace for melee.|
|isUsingSockets||bool||This will indicate if melee trace will use sockets or not. We will try to find sockets in weapon and use them if added.|
|HitActors||Actor Reference Array||This array will store all actors that have been hit by melee.|
In Viewport tab make sure you have added Skeletal Mesh Component which will be root.
Now let’s add some Functions.
Sockets names are hard coded as you see. If you want to use them for trace start / end – just put them into your skeletal mesh.
Note: You don’t need to add them – we will have small algorithm to get mesh bounds and calculate start end trace. It’s optional but you will have more control of melee trace with them.
GetTraceLocations – Pure Function with two outputs:
- TraceStart, Vector
- TraceEnd, Vector
This part is important take some time to figure out what it does. Part with sockets is simple but without them it’s more complicated but still with small amount of calculations.
I’m taking box extend of a weapon which will give me lenght on X. Then I need to get the same direction vector (and it depend on weapon – read comments) to multiply my extend with it – so it will point end of the weapon.
What you can do here is to add Socket as Root and rotate your mesh, but more pro way is to have the same rotation for all of the imported weapons. If you are using Infinity Blade weapons they will use Up Vector and if you are using Medieval Bludgeoning Weapons Pack they are using Right Vector multiplied by -1.
GiveDamageOnce with two inputs:
- To, Actor Reference
- HitResult, Hit Result
This is making sure we won’t add damage twice to the same actor in the same attack swipe.
We will be calling this function in tick, during animation that’s why it’s needed.
Now go to Event Graph and add some Events.
As you can see it’s responsible for weapon configuration.
This should be self explanatory. Basically weapon is waiting (IsInAttack) to check what is under line trace.
Configuring Character – Attach mesh to hands
Now when we have weapon class ready we need to attach weapon somehow to our character.
I’m using Character with hands (FirstPersonCharacter_MedievalBludgeoningPack) from Medieval Bludgeoning Weapons Pack but it is doable in any assets that you have.
First your Character need to have HoldingWeapon variable – of course extending from BP_BaseWeapon.
Next your Character (or any actor that will use weapons – enemies for example) need to have IDamage interface implemented. So go to your class settings and add IDamage interface.
Then double click on GetHoldingWeapon to override interface function and return HoldingWeapon.
Now in your Begin Play you need to:
- Spawn the weapon,
- Make sure spawned weapon is Holding Weapon,
- Attach it into hands,
Let weapon know to trace and do damage
Now we need to inform holding weapon that we would like to trace and do melee damage. What’s the best way to do this? Use animations and anim notifies.
Pack that I’m using have couple of attack animation and I will use them, but you can use any animation you have.
First create new Blueprint extending from AnimNotifyState named Notify_MeleeDamage. Open it and Override two functions:
Now open some attack animations and add you notify when attack should appear.
And that’s it! If you want to add damage to actors/enemies you need to add IDamage interface to them and add Event Take Damage. AI isn’t in scope of this tutorial but it’s on my list 😉