How to do damage – advanced

There are lots of ways for dealing damages in games. I will do more advanced stuff:

  • Damage will be calculated from weapon and ammo type,
  • Critical Chance will be calculated,
  • I need to see what’s the damage and if there was a critical hit (UMG),
  • I need to see how much HP enemy have,
  • I want to have different damage depending on which body part I shoot, (eg head, leg etc)

Let’s gets started!

Unreal Engine 4 has damage system implemented. You can read about it here. I will use my own system in this tutorial because I have different data than ApplyDamage from engine.

Create Damage Interface.

Let’s create new Blueprint Interface named I_TakeDamage. You can read more about interfaces here. 

There should be one function: TakeDamage

I_TakeDamage

It will be used for all actors that implement this interface. For example if you want Bottle to take damage just implement this interface in its class preferences. Of course currently we aren’t firing this interface so it won’t work yet.


Updating BP_BaseWeapon. 

We need to do some changes to BP_BaseWeapon.

In CalculateShootInformations function we need to change Line Trace by Channel  to Line Trace for Objects.

LineTraceForObject

And add these variables:

  • MinWeaponDamageModifier (float, default 0.5),
  • MaxWeaponDamageModifier (float, default 1),
  • CritDamageModifier (float, default 2),

Now create new function AddDamageTo with inputs: Hit Result (Hit Result), EndLocation (vector)

We will call our interface from this function.

adddamageto

We need to update Fire function because some of the functionality (CalculateShootInformations) was implemented in BP_Weapon_Pistol. I want to have this in main class so I won’t be copying nodes to other weapons.

bp_mainweaponfire

So we are spawning effects and we are firing AddDamageTo function from here. After updating Fire function you would need to delete Fire events from BP_Weapon_Pistol and other weapons that extends BP_BaseWeapon.

So Fire in BP_Weapon_Pistol should look like this:

FireInWeaponPistol

Thanks to this change every weapon we will extend from BP_BaseWeapon will have deal damage functionality.


Create Damage Feedback UMG.

Create new Widget Blueprint named UI_Debug_DamageInfo. It shouldn’t have Canvas Panel. Root should be Overlay.

It contains two text block: TextBlock_Damage and TextBlock_TextCrit in this video you can see the widget. Hope you will be able to create something like this.


Creating Damage Feedback actor.

Create new blueprint based on Actor and name it DamageFeedback. Add some variables:

  • Damage (float, editable and expose on spawn),
  • WasCrit (bool, editable and expose on spawn),

And in components (Viewport) add Scene component as root and add Widget Component. In 4.8 Widget Components are still in experimental stage but they should work correctly with our simple graphical feedback.

Widget Properties:

widgetproperties

Widget shouldn’t have collision enabled! Create Begin Play and assign earlier created UI_Debug_DamageInfo widget.

set widget


Create Health Bar UMG

Create new Widget Blueprint named UI_Debug_EnemyHealth.

As in DamageInfo Widget this shouldn’t have canvas panel. Instead add Overlay. Add a progress bar to Overlay and set Alignments to fill. Now in Event Graph create new function UpdateHealthBar.

updatehealthbar

This will update progress bar depending on Current and Max variables. You could use UMG binding for this but I have seen that they are called on Tick so it isn’t so optimal.


Creating Enemy

Create new blueprint extending from Character name it BP_BaseEnemy and add variables:

  • isDead (bool),
  • CurrentHealth (default 100),
  • MaxHealth (default 100),

Add Begin Play and assing MaxHealth to CurrentHealth.

healthset

MaxHealth will be used in later posts as a gameplay balance value.

Now let’s add health progress bar as a Widget Component. Here’s the properties:

healthbarproperties

Change Collision for Mesh so traces from weapon will block on enemy mesh.

meshcollision

Create new function UpdateHealthBar:

updatehealthbarinenemy

And another function ModifyHealth. Input: HealthToModify (float) and Output: IsDead (bool)

modifyhealth

Last function: CalculateDamage.

Inputs:

  • Damage (float),
  • CritChance (float),
  • CritDamageModifier (float),
  • WeaponDamageModifier (float),
  • HitInfo (Hit Result)

Outputs:

  • DamageTaken (float),
  • WasCrit (bool),

Local variables:

  • Local_WasCrit (bool),
  • Local_CurrentDamage (float),

calculatedamage

This function is calculating damage and returning it.

Now in Class Settings add I_TakeDamage interface as implemented interfaces and create new event I_TakeDamage.

takedamage

That’s all here. Now the most time taking part…


Implementing Body Parts

I want to use Physical Materials to check which body part was hit instead of calculating length. It will be faster but it require some preparations.

Go to Project Settings -> Physics and add those to Surface Types:

surfacestypes

It can be done quicker if you go to Config folder (YourProject/Config) and in DefaultEngine.ini add those to [/Script/Engine.PhysicsSettings]

+PhysicalSurfaces=(Type=SurfaceType1,Name=”Metal”)
+PhysicalSurfaces=(Type=SurfaceType2,Name=”Flesh”)
+PhysicalSurfaces=(Type=SurfaceType3,Name=”Glass”)
+PhysicalSurfaces=(Type=SurfaceType4,Name=”Concrete”)
+PhysicalSurfaces=(Type=SurfaceType5,Name=”Flesh_Head”)
+PhysicalSurfaces=(Type=SurfaceType6,Name=”Flesh_Body”)
+PhysicalSurfaces=(Type=SurfaceType7,Name=”Flesh_LeftArm”)
+PhysicalSurfaces=(Type=SurfaceType8,Name=”Flesh_LeftForearm”)
+PhysicalSurfaces=(Type=SurfaceType9,Name=”Flesh_LeftHand”)
+PhysicalSurfaces=(Type=SurfaceType10,Name=”Flesh_LeftUpLeg”)
+PhysicalSurfaces=(Type=SurfaceType11,Name=”Flesh_LeftLeg”)
+PhysicalSurfaces=(Type=SurfaceType12,Name=”Flesh_LeftFoot”)
+PhysicalSurfaces=(Type=SurfaceType13,Name=”Flesh_RightArm”)
+PhysicalSurfaces=(Type=SurfaceType14,Name=”Flesh_RightForearm”)
+PhysicalSurfaces=(Type=SurfaceType15,Name=”Flesh_RightHand”)
+PhysicalSurfaces=(Type=SurfaceType16,Name=”Flesh_RightUpLeg”)
+PhysicalSurfaces=(Type=SurfaceType17,Name=”Flesh_RightLeg”)
+PhysicalSurfaces=(Type=SurfaceType18,Name=”Flesh_RightFoot”)
+PhysicalSurfaces=(Type=SurfaceType19,Name=”Metal_Head”)
+PhysicalSurfaces=(Type=SurfaceType20,Name=”Metal_Body”)
+PhysicalSurfaces=(Type=SurfaceType21,Name=”Metal_LeftArm”)
+PhysicalSurfaces=(Type=SurfaceType22,Name=”Metal_LeftForearm”)
+PhysicalSurfaces=(Type=SurfaceType23,Name=”Metal_LeftHand”)
+PhysicalSurfaces=(Type=SurfaceType24,Name=”Metal_LeftUpLeg”)
+PhysicalSurfaces=(Type=SurfaceType25,Name=”Metal_LeftLeg”)
+PhysicalSurfaces=(Type=SurfaceType26,Name=”Metal_LeftFoot”)
+PhysicalSurfaces=(Type=SurfaceType27,Name=”Metal_RightArm”)
+PhysicalSurfaces=(Type=SurfaceType28,Name=”Metal_RightForearm”)
+PhysicalSurfaces=(Type=SurfaceType29,Name=”Metal_RightHand”)
+PhysicalSurfaces=(Type=SurfaceType30,Name=”Metal_RightUpLeg”)
+PhysicalSurfaces=(Type=SurfaceType31,Name=”Metal_RightLeg”)
+PhysicalSurfaces=(Type=SurfaceType32,Name=”Metal_RightFoot”)

We have types added but now we need to create Physical Material for each of them. Names should be the same (PM_SurfaceTypeName) for example PM_Metal_RightFoot.

Open created Physical Mat and change Surface Type should correspond with name. For example here’s my PM_Flesh_RightFoot.

SurfaceTypeAndDamage

One important thing: we are using Desctructible Damage Threshold Scale as our Damage Scale. So for head it should be 1 and for foot it should be 0.1 – use values as you like!

I know – lot’s of clicking but this need to be done only once so be patient 🙂


Implementing Physical Materials

Create new blueprint extending from BP_BaseEnemy and name it as you wish – he will be used only for tests. Set mesh to hero TPP. Compile and add this character to your level so you can shoot at him.

Go toHeroTPP_Physics and when selecting bodies you can select Physical Material for the body.

bodypartsmat

Now assign Physical Materials to body parts and you are done! i know that we could create Head, Torso, Leg instead of LeftArm etc But these will be needed later when I will destroy body parts.


Updating ImpactEffect

If you want to see different effect on different body type of character you need to update your ImpactEffect actor.

impactactor

Thanks to this system I’m able to define body parts, calculate damage and crit chance!


Creating ShooterTutorial takes a lot of my free time.
Buy Now Button
If you want you can help me out! I will use your donation to buy better assets packs and you will be added to Credits /Backers page as well.

Implementing game is taking time but writing about this is taking much more effort!

25 thoughts on “How to do damage – advanced

  1. Pingback: First Enemy – Behavior Tree / Shooting at Player | Shooter Game Tutorial

  2. Pingback: Creating a Shotgun | Shooter Game Tutorial

  3. “Showing” how to do the UI widgets with video is just AWFUL. Please stop doing that and do proper written tutorials for these like you are doing for the othe blueprints.

    • To learn UMG I would need to create video tutorials. Unfortunately I don’t have time for it 🙁 UMG designer is simple to learn and I’m showing hierarchy in the video. If you don’t know how to create hierarchy just take your time and add some widgets in the designer – play with them. What I would like to learn is UMG communication, not visualization in designer. Hope you understand!

      • Even if you were to explain the entire process on how you created it in text would be better. Its frustrating going through a tutorial where there is randomly some bit that is included and automatically assumes you can easily create it without any knowledge of how to do so.

      • No, he’s right. It’s not that UMG is difficult to understand. I have a decentish grasp on how it works.

        The problem is that you can’t see what it is you’re doing in your videos. You’re not guiding us along with speech and the display is too small and quick to see what changes you’re making just by watching random elements getting highlighted as your invisible cursor darts about. Even with the video speed turned down to half, I still couldn’t see what changes you were making.

        Additionally, since you pre-built the animation and the blueprint, we don’t get the benefit of seeing how those parts are assembled. You really need to go through to process of putting all the parts together if you’re doing to do it in a video because you can’t assume people are going to know how you got there from where you left off in the text. This is especially true for animations and for timelines. I mean, if we knew exactly how those things were put together, we probably wouldn’t need to read a tutorial in the first place, you know?

        I absolutely appreciate all the time and effort you put into this tutorial, but I have to admit, I’ve had a lot of starts and stops with it because you do gloss over crucial parts.

  4. Need some help. I’m trying to shoot the enemy but no damage seems to be taken. Its showing 0 on the debug UI widget.. everything else, fleshFX, sound FX, all plays well. I tried giving max and current health = 0 for the baseenemyBP and then upon shooting I can see the health bar go empty in fraction of a second and the enemy disappears.. I tried messing with values on the physics material but none of that seems to do anything…

      • The problem is in the EventBeginPlay Node within the WeaponPistol Blueprint. If you look at it closely, he has it getting GameInstance and then passing AmmoConventional into SET-> AmmoData. This is not going to work because essentially what is taking place is that the original AmmoData STRUCT is overwriting the AmmoData STRUCT is WeaponPistol.

        So the solution is to disconnect the Parent:BeginPlay Node from the cast to BP_ShooterGameInstance Node.

        Also, if you are having problems debugging, try using printstrings and buildstrings… I am brand new to this and solved this problem in under an hour.

        • I tried this solution, and no help still generating 0’s with each shot, (crit constant as well with each shot [image]) and once i break the connection, ammo no longer works with pistol, I’ve quadruple checked all the imagery here, and did some digging elsewhere. Please anyone have any ideas? I’d like to get this figured out.

  5. I am using UE4.9 and even my enemy gets damage but the damage_UMG is not showing the damage to me. Could you advice or tell what is wrong?

  6. Can you add how to use actor projectile aside from line trace? Breaking hit info from the projectile collision return the deafult case

  7. I have everything working except “Crit!” appearing when it actually should. First it appeared no matter where I hit. Then I noticed in the UMG vid that the text block’s initial setting was supposed to be “Hidden”. So I changed that, but now it never shows up. I think it has to do with my UI_Debug_DamageInfo and the Wascrit variable near the end of the stream, am I supposed to be passing that from another Blueprint? Because that Branch always evaluates False.

  8. Hello ! Im having an issue with the collision ! I did exactly what you said in the mesh collisions and the physical materials. The trace hits normal in the ground and in another meshes but it just doesn’t hit the ”actor enemy test” that i put in level.

    What could this be ?

  9. Hi,

    I am curios why you would not use the TakeDamage from UE and do your own interface. It seems a bit over complicated to have different materials for each body part. (I’m not saying I know an easier way)

  10. Hey still getting this problem with only getting 0’s back when firing weapon, any guidance on this would be great I tried the above solution along with a few dozen others. I do at least get there error now:

    CallFunc_BreakHitResult_PhysMat

    I really like this damage setup here and would like to use it if can get past this hangup

  11. I like this tutorial very much so far, but i can not get futher the following problem:

    Iam in “BP_BaseEnemy” and trying to create the “I_TakeDamage” Event in the Event Graph.
    But i can not find any way to get to that node. All i found are the function calls (as “Interface Call” or “Message”) targetting the “I_Take_Damage” Interface Blueprint.

    Iam using Engine 4.8.3 and iam a beginner (maybe i have missed s.t.)

  12. Hello community,

    i had the problem myself with all those “Zeros” when firing the weapon.

    I realized, that my gun actually did no damage! That means, that all the “Zeros” were correct!
    The damage of a gun depends on the ammo it uses. Right now its the “conventional”. But where is the problem now?
    We initialize the ammo in the BP_BaseWeapon as a variable “AmmoData” of type “AmmoData”. All you need to do, is to give it some default values for “damage” etc. After that the healthbar should work correctly and the zeros are gone.

    • @DasMaeh & @Cinco: Thanks for the replies. I had the same ‘Zeroes’ problem: when my conventional ammo collided with my test enemy, I saw only zeroes. To fix it, I did what Cinco suggested: In my BP_Pistol, I unhooked the Parent: BeginPlay node from the CastToGameInstance node. After that, instead of adjusting the Damage and CritChance in the BP_BaseWeapon (like DasMaeh suggested) I adjusted those values in the BP_Pistol itself (i’m using 12 different weapons, so I’m adjusting each one for different Damage values). It now works. Thank you Andrze for these amazing tutorials!!!

      • I should also probably add that I zeroed out all of the values in BaseWeapon as well. It won’t work if you do not do that. For example, if I leave ‘Current Ammo’ set to 11 in BaseWeapon, and then in BP_Pistol I leave ‘Current Ammo’ set to 0, I will still see zeroes when I shoot my enemy. That is because the Pistol will be pulling values from BaseWeapon and will also pull the Ammo Data from BaseWeapon. In short, set all the values in BaseWeapon to zero!

  13. Quite useless tutorial since you are not explaining things… just showing how to do stuff that the reader has to follow in a brainless way…

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.