How to implement score and combo system


In this tutorial I will implement score system which:

  • Should be intuitive for player,
  • Will reward players with good accuracy,
  • Will reward players who play fast,

It won’t be so hard so let’s go!

UE4Editor 2015-08-22 12-42-36-972


First of all some theory. I think that the best way for calculating score here is to take which body part was hit and calculate points added to score using multiplier.

This will look like this:
BasePointValue * BodyPartHit. For example: 10 * Head = 20 or 10 * Leg = 5

To add more “gameplay” element to score it should have some sort of combo system. The idea here is:

  • Every time we hit an enemy combo bar will increase,
  • Combo bar is decreasing over time,
  • Each time combo bar will be full player will get next combo level. Combo bar will reset,
  • If our accuracy is bad (we haven’t hit anything) combo level will go back to 1,
  • Combo level will be used as multiplier for points,

So here’s how it should look in theory: BasePointValue * ComboLevel * BodyPartHit.

Thanks to this player will need to aim and will get more points if shooting fast. Sounds good enough.

Implementing score and combo

We will use GameState class for this. You should have GameplayGameState ( UE4 classes explanation) and assigned to your level.

Open it and add those variables:

  • CurrentPoints (float),
  • CurrentComboLevel (int, default: 1),
  • BasePointsToAdd (float, default: 15) this means each time we hit we will add 15 points as a base,
  • ComboBarDecreasingSpeed (float, default: 0.1),
  • ComboBarIncreasingValue (float, default: 0.35) – the base value for how much we will add to combo bar when hit an enemy,
  • DeltaTime (float),
  • isDecreasingComboBar (bool, default: true) this will be used later when I will have gameplay phases implemented,
  • CurrentComboBarValue, (float),
  • MissDecreaseValue (float, default: 0.25) – how much combo bar should decrease if we miss,

Then add those event dispatchers:

  • ComboLevelIncreased (with one input: CurrentComboLevel int),
  • ComboLevelDecreased (with one input: CurrentComboLevel int),
  • ComboBarBulletMiss,

Now it’s time for new functions.

IncreaseComboBar function with one input Hit Result:


This function is responsible for managing combo bar, combo level and adding points. Earlier theory is implemented here.

DecreaseComboBar function:


It’s straightforward – decreasing Combo Bar Value and call Miss dispatcher.

Now go to your Event Graph and add Tick event with UpdateComboBar custom event.


This is making sure combo bar is decreasing over time and manage combo level.

That’s all in GameState – make sure this game state is connected with your level!

Creating UMG

UMG will show us the combo bar, combo level and current points. I’m using K-Spree GUI, you can read the implementation here.

Create new widget named HUD_Points. Try to recreate this hierarchy:

Now bindings. Select ProgressBar and bind a function to Percent.


Just getting the CurrentComboBarValue and passing it to ProgressBar percent.

Select TextBlock_Points and create binding for the Text.


You could manage points by using dispatchers as well because we know when we will hit, but I’m not sure when points will be added later on that’s why binding is safer.

Now go to your event graph and bind gamestate dispatchers:


We will play feedback animations on UMG and update ComboLevel text thanks to those dispatchers.

That’s all in UMG.

Adding UMG to player

Open GameplayCharacter and add new Widget Component named HUD_Poinst. It need to be attached as the rest UMG Widget.


  • Location :(X=-7.986703,Y=-27.562475,Z=35.536598)
  • Rotation: (Pitch=-12.431763,Yaw=60.849777,Roll=85.633919)
  • Scale: (X=0.034050,Y=0.034050,Z=0.034050)
  • Widget Class: HUD_Points,
  • Draw Size: 500 x 200,
  • Pivot: 0, 0,
  • Collision Presets: No Collision,


Using score and combo

Now we need to start using this system. Open BP_BaseWeapon and add two new variables:

  • HitActorsResults (Hit Result ARRAY),
  • NumberOfHitEnemies (int),

Now functions.

Get Best Hit Result (input: Results, HitResult ARRAY) with two local variables:

  • CurrentBestHitResult (Hit Result),
  • CurrentBestValue (float),


Why we need this function? Imagine that you are shooting using Shotgun – one bullet hit an head an one bullet hit leg, which bullet should be taken for points and combo system? This function will return the best hit result.

New function: Calculate Points


This function is responsible for letting GameState know if should increase combo bar or decrease it.

Now we need to drive HitActorResults array variable and those functions. The best place for this is Fire function. It need to be updated.



I will try to explain. Before we do damage we are calculating the points, that’s because we are checking isDead variable. If were calculating points after AddDamage player won’t be getting points when killing an enemy.

Each time we shoot we are adding HitResult to HitActorResults array and in the end of Burst Count Loop we are iterating points over one of them and deal damage to all of them.

Updating Projectile

The last thing to do is to update BP_BaseProjectile to update the score and combo as well.

Go to OnProjectileStop function and add a sequence:


Final Effect


We are done but there will be couple of things to do later:

  • Hi score should be saved in levels, not in GameplayGameState,
  • Basically without level system we can’t create “new hi-score” and leaderboards functionalities yet. This will be done later,
  • We could add another multiplier for score – player level. This will reward active players,

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 it is taking much more effort!

3 thoughts on “How to implement score and combo system

  1. Pingback: Display target information | Shooter Game Tutorial

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.