ProgressBar in Godot – Complete Guide

Progress bars are ubiquitous UI elements that users encounter almost daily, whether they’re waiting for a file to download, a game level to load, or monitoring progress in a task. In game development, particularly when using Godot Engine 4, the ProgressBar class serves as a vital component in relaying information to the player visually and engagingly.

What is ProgressBar in Godot 4?

A ProgressBar is a visual component that represents a percentage, showing how much of a task has been completed or how much of a resource, such as health or mana, is left. In Godot 4, the ProgressBar node inherits from the Range class, ensuring that it’s not just a static bar but one that responds to the variables and parameters of the game.

What is it for?

This control is designed to visually communicate progress, often enhancing the player’s experience by providing clear and immediate feedback. Whether it’s displaying a character’s health declining in a battle or showing the loading progress of the next scene, the ProgressBar is an essential tool in the game developer’s UI kit.

Why should I learn it?

Mastering the ProgressBar class and understanding how to customize it to fit your game’s aesthetic and feedback requirements will elevate the player’s experience. It’s a versatile UI element that, when used correctly, can inform, motivate, and guide the player. Plus, learning how to use such components effectively is a stepping stone to creating more complex UI systems in your games.

CTA Small Image - ProgressBar in Godot - Complete Guide
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Developer API

For the latest version please visit the official documentation.

Example Project

You can download the project files here.

Let us begin with creating the user interface, create a new scene with the root node of type Control. Lets save it as user_interface.tscn.

Create a ProgressBar node and set it’s anchor preset to ‘Top Wide’ so that it spans across the whole viewport. Set it’s custom_minimum.y (Under Layout) to 35 so that it has some thickness.

Screenshot 2024 06 18 101045 - ProgressBar in Godot - Complete Guide

The 3 main properties you’ll need to pay attention to are min_value, max_value and value.

  • min_value defines the lower extent of the progress bar’s value.
  • max_value defines the upper extent of the progress bar’s value.
  • value is a float value between the min and max values, it determines how much of the ProgressBar is filled.

For example, by default min_value and max_value are set to 0 and 100 respectively. So a value of 50 here would mean that the ProgressBar will be filled exactly half way through.

Feel free to experiment with changing each of these properties to get a feel for how it works!

Setting up the ProgressBars

Let us set the min_value and max_value to 0 and 1 respectively, so that our range is ‘normalized’. This isn’t always necessary but it is common to work with a normalized range of 0 to 1, since we can now think of our progressbar in terms of a percentage where it is easy to calculate our final value.

Now, a value of 0.5 would would be 50% of the progress, i.e exactly half.

You might think that this might be a bit convoluted to not simply use a range of 0 – 100 to visualize 0 – 100%, but it will become apparant why the 0 – 1 range is useful as you read on.

Let us take a quick look to see how we can make our ProgressBar look a little bit better. Under ‘Theme Overrides → Styles’, we can create individual styleboxes for the background as well as the filled portion of the stylebox. Create a StyleBoxFlat for each of the styles and set their bg_color values to something that looks nice!

We will be using the colors #72303b and #dc4848 for the background and fill respectively.

Screenshot 2024 06 18 101046 - ProgressBar in Godot - Complete Guide

A few more properties that you should be aware of:

  • fill_mode defines the visual direction of progress on the bar.
  • show_percentage shows the percentage of value in the middle of the bar.
  • step will have the value be rounded to multiples of it’s value.

Lets turn off show_percentage so that we just see a clean bar with no text on it. Duplicate the ProgressBar node by selecting it and pressing Ctrl + D, set the new bar’s anchor preset to ‘BottomWide’ and it’s custom_minimum to 100.

Coding the ProgressBar logic

We should now have two progress bars in our user interface. Lets rename them to ‘MinionHealthBar’ and ‘BossHealthBar’. Create a script called enemy_health_bar.gd that extends ProgressBar and attach it to both the ProgressBars.

Screenshot 2024 06 18 102335 - ProgressBar in Godot - Complete Guide

Let us create an @exported float variable called max_health to store the starting health of each enemy and health to store the enemy’s current health.

Assign the value of max_health to health inside of _ready() so that the current health is at the max value at the beginning. Lets also set the ProgressBar’s value to 1 so that the bars start completely filled.

Create a take_damage function, that takes in a float parameter called damage. We can now decrement our health and set the value of the ProgressBar to show that the enemy has taken damage. Print the health after taking a damage to make sure that the code is running correctly.

extends ProgressBar

@export var max_health: float
var health

func _ready():
  health = max_health
  value = 1

func take_damage(damage):
  health = health - damage
  print(name + ": "+ str(health))

In the inspector, set the max_health value of each enemy to 250 and 750 respectively.

Head to the Project Settings and navigate to the ‘Input Map’ tab, create a new action called ‘damage’ and bind it to the space key.

Screenshot 2024 06 18 102419 - ProgressBar in Godot - Complete Guide

In the _process() method, lets check if this action was just pressed and call our take_damage() method. Let pass in an arbitrary amount of damage into it as an argument (say 110).

func _process(delta: float):
  if Input.is_action_just_pressed("damage"):
    take_damage(110)

Lets run this code to make sure that our code works so far. We should see our health values being decremented correctly in the output.

Screenshot 2024 06 18 102519 - ProgressBar in Godot - Complete Guide

Now, we cannot set the ProgressBar’s value to our health directly, since they have a range of 0 – 1. We can normalize our current health to the same range by dividing our current health by the max_health.

Let us do this inside of the take_damage() method. We can now set the normalized value as our ProgressBar’s value!

func take_damage(damage):
  health = health - damage
  print(name + ": "+ str(health))
  
  var health_normalized = health/max_health
  value = health_normalized

You can optionally print the value of health_normalized to see its exact value, if you’re confused about what we’re calculating here. Just to keep things clean, lets limit our health value to not be able to go lower than 0. We can use the max() method for this, which returns the higher value of the two parameters you pass in. We can pass in health - damage and 0, and it will return the higher value of the two.

func take_damage(damage):
  health = max(health - damage, 0)
  print(name + ": "+ str(health))
  
  var health_normalized = health/max_health
  value = health_normalized

Now, when we run our game, we should see that our progress bars respond to the health changes correctly! Since we’ve normalized our bar to a range of 0 – 1, and also our health value, both the bars respond correctly, even if each of them have different health values!

Full Script Code

You can download the Godot project here. The project was developed and tested in version 4.2.

extends ProgressBar

@export var max_health: float
var health

func _ready() -> void:
  health = max_health
  value = 1

func _process(delta: float):
  if Input.is_action_just_pressed("damage"):
    take_damage(110)

func take_damage(damage):
  health = max(health - damage, 0)
  print(name + ": "+ str(health))
  
  var health_normalized = health/max_health
  value = health_normalized

Conclusion

Now that you’ve seen the versatility and capabilities of the ProgressBar node in Godot 4, it’s time to take your game development skills to the next level. Harnessing the power of dynamic UI elements is key to crafting immersive and interactive gaming experiences. Remember, the ProgressBar is just the tip of the iceberg when it comes to the vast potential of Godot Engine 4.

For example, you could build up a health system that integrates with the bar, which we cover in the free bonus video tutorial below!

We at Zenva are committed to providing you with high-quality, practical tutorials and courses tailored for real-world application. Dive deeper into Godot and beyond with our Godot Game Development Mini-Degree, where we’ll guide you through every step of the way as you bring your creative visions to life. Don’t just play games—create them and shape the future of gaming with your own unique touch. Embark on your journey with us today and be the game developer you’ve always wanted to be!

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FREE COURSES
Python Blog Image - ProgressBar in Godot - Complete Guide

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.