Summary Screen


In this Tutorial I will focus on basic summary screen and game loop:

  • Showing player score and hi-score,
  • Saving hi-score,
  • Communicating between widgets and game to create simple loop main menu -> gameplay -> main menu,

Stats and leaderboards will be added in separated tutorials as I will do much more complicated stuff there.

This Tutorial has been created using Unreal Engine 4.10
Make sure you are working on the same version of the engine.

Live Stream

You can watch Live Stream of developing this Tutorial:

Game Instance

Hi Score

In ShooterGameInstance there is Levels array which stores hi-score for each level. Before moving forward open Save_Instance save class and add the same Levels array.

Now update Save and Load functions to store / get Levels array:

instance_save instance_load

Now create new function named CheckIfNewHiScore? It should be pure:


Add another function named GetCurrentLevelHiscore. Pure as well:


And the most important one: SubmitHiScore. With one local int variable named Index:


Please read the comments on the blocks as it is critical how to use Find In Array node after changing some values.

Functions to open Menu or Gameplay

Next part is to create functions that will open main menu map and gameplay map selected by player.

Create new function named OpenMainMenu:


And function OpenGameplayLevel:


That’s all in Game Instance!

Summary Screen UMG

This UMG is complicated and the best way would be watch Live Stream.

Before moving forward Widget_AnimatedText need to be updated. Open it and these variables:

Var Name Var Type DefaultValue  Description
ShouldAnimOnBeginPlay bool Editable. This will trigger animation without calling function.
CustomText string Editable. This will be used for text if ShouldAnimOnBeginPlay will be true.
FontSize int 24 Editable.

Now just use Construct to check the bool:


If you don’t have Anim Text function you should read tutorial about Level Selection. (Creating Animated Text Widget part)

Now create new widget named UI_SummaryScreen.

Hierarchy can be found here:

Now open Event Graph and add those variables:

Var Name Var Type DefaultValue  Description
bNewHiScore bool Editable. Expose on Spawn. We will know if show new hi score text.
bPlayerWasDead bool Editable. Expose on Spawn. We will know which title UI should have.
Points float 24 Editable. Expose on Spawn. Just storing points.
HiScore float Editable. Expose on Spawn. Just storing hi-score.

Now create new custom event named WasNewHiScore:


Another one named CheckIfPlayerWasDead:


And another one named UpdatePointsAndHiScore:


These are just simple events changing widgets on variables changes.

Now UpdateData custom event which will call all of those events:


Now in Construct call UpdateData and bind buttons:



Game Ended Events

We need to know when game ended and if player was killed.

Open GameplayCharacter and add OnPlayerDeath dispatcher. Open GameplayGameState and add OnGameEnded dispatcher with one bool input named byPlayerDeath.

Still in GameplayGameState add one new bool variable named isGameEnded. Then add new function named SubmitScore with:

  • Output: CurrentHiScore (float),
  • Output: WasNewHiScore (bool),
  • Local Variable: NewHiScore (bool),


This is basically checking if there is new hi score – if yes it’s submitting it to ShooterGameInstance.

Create another function named ShowSummaryScreen with:

  • Input: WasPlayerDead (bool),
  • Input: NewHiScore (bool),
  • Input: HiScore (float),


Create new custom event named OnGameEnded with one bool input named ByPlayerDeath:


Add another custom event named BindOnPlayerDeath:


Now make sure you call OnGameEnded dispatcher and custom event on pattern manager finish:


Now just bind OnPlayerDeath in Begin Play:


Now we have end game communication. Both for player death and level finished from pattern manager.

Updating GameplayCharacter

Open GameplayCharacter and add one new bool variable named isGameEnded. Next add new function named HideHud:


Its just hiding all 3d widgets.

Character should know when game ends from Pattern Manager that’s why create new custom event named BindOnGameEnded:


Now let’s use earlier created PlayDying event to call dispatcher and hide hud as well:


Make sure your begin play calls BindOnGameEnded and earlier created function Spawn Weapons (did was called by Debug UI, now it’s time to call it properly)


Last thing is enemy target health hud update (UpdateEnemyTargetHUD):


So it won’t be shown if player is dead or patter manager ended.

Updating UI_LevelSelectionActor

Now it’s time to update Level Selection UI and Actor to pass the chosen level data to Game Instance.

First open the UMG – UI_LevelSelection and add OnClickedPlay dispatcher which should be called on Play button:


In UI_LevelSelectionActor there is a lot of bindings in Begin Play to communicate between level selection and weapon selection. The problem is that 3d Widgets in Standalone Game aren’t loaded in Begin Play, they need more time to load so Get Widget Class will result Null.

Delete Begin Play event and add new custom event named BindWidgetsEvents. Just replace Begin Play with that.

In the end of BindWidgetEvents (which was Begin Play earlier) make sure you bind your OnClickedPlay from UI_LevelSelection:


This way I’m passing the data to Game Instance.

But if we don’t have Begin Play now all of the bindings won’t be called. In this example I’m triggering the Widgets when player is near so I can use this event to call BindWidgetsEvents.


This way Widgets will work in Standalone Game.

Final Result:

Creating ShooterTutorial takes a lot of my free time.
donateIf 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!

10 thoughts on “Summary Screen

  1. Pingback: Adding PlayFab Online Leaderboards | Shooter Tutorial

  2. Pingback: Adding Player Stats | Shooter Tutorial

  3. execute console command “RestartLevel” is restarting the level but the player character controller is seams to be null because I can’t move with the mouse and any hotkey like “G” for weapon selection is not working. maybe there any other way of accomplishing Restart?

      • thanks I made the following: before the executing the console command I have used Set input mode Game Only. And everything is working fine!))) Thanks a lot again man)

  4. And my High Score is always is illustrated as 0. Maybe you didn’t mentioned where you assigned the velue of the Current points to the HighScore variable?

    • I dont know is it right or no but my own solution was the following: when we are checking “NewHiScore?” in WasNewHighScore (UI_SummaryScreen), when the contion is true, at the end of the line I am setting the value of the points to the HighScore

      • it is assigning the value to the high score but whenever you restart all data lost and event less score is evaluated as Highscore. help please

  5. Another issue, Sorry for that man)) and thanks for your great tutorials))
    when i am clicking the play in weaponselection umg, where we select the weapon for playing and shooting with them, on click that button I am doing there the same casting to the shootergameinstance and getting from there the OpenGamePlayLevel function, as we did in SummaryScreen, it is not working and not loading but closing the playWindow. Can you please explain why that issue is happening?

  6. Hi Farrukh, sorry for the incredibly late reply but I’m way, way behind you guys. To fix that I did the following –

    – Add OnClickedPlay event handler to UI_WeaponSelection, instead of LevelSelection
    – Hook up the same “Bind Event to OnClickedPlay” nodes as pictured, but make sure your ‘target’ pin is linked to the cast to UI_WeaponSelection, instead of LevelSelection
    – Everything else should be same as pictured

    Now, in your Game Instance node, find the “Levels” array variable, and populate all the “Level to Load” fields. If this is left blank the PIE window will simply close, complaining about invalid URL path. Filling these in with map name(s), you should be good to go.

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.