Effortlessly simulate health and damage for entities within your video game now in C#.
This component handles all aspects related to taking damage and managing health on the parent node. While typically added to a CharacterBody2D
, there are no limitations preventing its use with a StaticRigidBody2D
, allowing you to imbue life into objects like trees or other in-game elements.
- Requirements
- ✨Installation
- Getting Started
- Examples
- Exported parameters
- Accessible normal variables
- Functionality
- Invulnerability
- When health reachs zero
- Percentage of actual health
- Multiple health bars
- Signals
- ✌️You are welcome to
- 🤝Contribution guidelines
- 📇Contact us
📢 We don't currently give support to Godot 3+ as we focus on future stable versions from version 4 onwards
- Godot 4.0+
You can download this plugin from the official Godot asset library using the AssetLib tab in your godot editor. Once installed, you're ready to get started
To manually install the plugin, create an "addons" folder at the root of your Godot project and then download the contents from the "addons" folder of this repository
This plugin has also been written in GDscript and you can find it on HealthComponent
Incorporate this component as a child node in the location where you intend to implement life and damage mechanics. Simply define the initial values you wish to assign to this component.
When this component becomes ready in the scene tree, a series of steps are carried out:
- Ensure that the current health does not exceed the maximum health.
- Set up the health regeneration timer.
- Set up the invulnerability timer.
- If the health regeneration per second exceeds zero, activate health regeneration.
- Establish a connection to its own
HealthChanged
signal. Whenever the health changes, this signal is triggered. If health regeneration is enabled, it is also triggered, and if the current health reaches zero, aDied
signal is emitted. - Establish a connection to its own
Died
signal. Once this signal is emitted, the built-in timers within the component are halted.
We usually have an examples folder in our repositories to showcase how to use the plugin in a specific context.
In this case we have a available a simple progress bar that is monitoring the health component to update every time a change happen:
- Max health (its maximum achievable health)
- Health overflow percentage (health percentage that can be surpassed when life-enhancing methods such as healing or shielding are used)
- Current Health (the actual health of the node)
- Health regen (The amount of health regenerated each tick)
- Health regen tick time (tick time defined where the health regen is applied)
- Is Invulnerable (the invulnerability flag, when is true no damage is received but can be healed)
- Invulnerability time (how long the invulnerability will last, set this value as zero to be an indefinite period)
- MaxHealthOverflow
- enum TYPES {HEALTH, REGEN, DAMAGE}
- InvulnerabilityTimer
- HealthRegenTimer
The MaxHealthOverflow
is a computed variable that represents the sum of the maximum health and the applied HealthOverflowPercentage
.
Example: max_health of 120 and health overflow percentage of 15% = 138
You have a maximum normal health of 120 but can be surpassed a 15% so our new limit is 138. This can be useful to implement shield mechanics where you need to separate this type of health.
To subtract a specific amount of health, you can effortlessly invoke the Damage()
function within the component.
This triggers the emission of a HealthChanged
signal each time damage is inflicted. Moreover, the component constantly monitors if the current health has plummeted to zero, subsequently triggering a died signal.
It's worth noting that the component is autonomously connected to its own Died
signal, concurrently ceasing the HealthRegenTimer
and InvulnerabilityTimer
.
If the IsInvulnerable
variable is set to true, any incoming damage, regardless of its magnitude, will be disregarded. Nevertheless, the standard signal broadcasting will persist as expected.
private HealthComponent _healthComponent;
public override void _Ready()
{
_healthComponent = GetNode<HealthComponent>("GodotParadiseHealthComponent");
}
_healthComponent.Damage(10)
_healthComponent.Damage(99)
// Parameter is treated as absolute value
_healthComponent.Damage(-50) // translate to 50 inside the function
The functionality mirrors that of the damage function, but in this instance, health is added to the component. It's important to note that the healing process can never surpass the predetermined MaxHealthOverflow
.
Following each execution of the health function, a HealthChanged
signal is emitted.
private HealthComponent _healthComponent;
public override void _Ready()
{
_healthComponent = GetNode<HealthComponent>("GodotParadiseHealthComponent");
}
_healthComponent_.Health(25)
// Parameter is treated as absolute value:
_healthComponent.Health(-50) // Is translated as 50 inside the function
By default, health regeneration occurs every second. When the health component invokes the Damage()
function, regeneration is activated until the maximum health is reached, at which point it deactivates.
You have the flexibility to dynamically adjust the rate of regeneration per second using the EnableHealthRegen
function. Alternatively, you can set it to zero to disable health regeneration altogether:
private HealthComponent _healthComponent;
public override void _Ready()
{
_healthComponent = GetNode<HealthComponent>("GodotParadiseHealthComponent");
}
_healthComponent.EnableHealthRegen(10)
# or disable it
_healthComponent.EnableHealthRegen(0)
You have the ability to toggle invulnerability on or off through the EnableInvulnerability
function. By providing the enable parameter (a boolean), you can specify whether invulnerability is activated or not. Additionally, you can set a time duration (in seconds) during which the entity will be invulnerable. Once the specified time limit is reached, invulnerability will be deactivated:
private HealthComponent _healthComponent;
public override void _Ready()
{
_healthComponent = GetNode<HealthComponent>("GodotParadiseHealthComponent");
}
_healthComponent.EnableInvulnerability(true, 2.5)
# You can deactivating it manually with
_healthComponent.EnableInvulnerability(false)
This component solely emits a Died
signal, offering you the flexibility to tailor the behavior to your game's needs. By establishing a connection to this signal, you can trigger animations, function calls, collect statistics, and perform other relevant actions to customize the experience according to your game's requirements
Perform a manual check to ascertain if the entity has entered the death state. If you wish to manually determine this state, you can utilize the CheckIsDeath
function. This function emits the Died
signal if the current health reaches zero.
private HealthComponent _healthComponent;
public override void _Ready()
{
_healthComponent = GetNode<HealthComponent>("GodotParadiseHealthComponent");
}
bool isDead = _healthComponent.CheckIsDeath()
If you intend to exhibit a health bar UI, you can access the health percentage format through the GetHealthPercent()
function. This function returns a dictionary structured as follows:
# For instance, if 80% of the maximum health represents the current health:
{
"CurrentHealthPercentage": 0.8,
"OverflowHealthPercentage": 0.0,
"OverflowHealth": 0
}
# Similarly, considering a maximum health of 100, a health overflow percentage of 20.0, and a current health of 120:
{ "CurrentHealthPercentage": 1.0,
"OverflowHealthPercentage": 0.2,
"OverflowHealth": 20
}
This information can aid in accurately representing the health status and overflow in a visual health bar.
To achieve this mechanic you can simple add multiple health components as childs on the target node and create a basic chain responsibility logic using the died signal. This is a very basic example and we recommend that you adapt it to your needs if they are a little more complex, we just want to give you a basic idea.
private HealthComponent _healthComponent;
private List<HealthComponent> lifeBars;
public override void _Ready()
{
_healthComponent = GetNode<HealthComponent>("GodotParadiseHealthComponent");
_healthComponent2 = GetNode<HealthComponent>("GodotParadiseHealthComponent2");
_healthComponent3 = GetNode<HealthComponent>("GodotParadiseHealthComponent3");
lifeBars = new {_healthComponent, _healthComponent2, _healthComponent3}
lifeBars.Last().Died += OnLifeBarConsumed;
}
private void OnLifeBarConsumed() {
HealthComponent lastLifeBar = lifeBars.Last();
lastLifeBar.Died -= OnLifeBarConsumed; // or queue free this node if you don't need the component anymore
lifeBars.Remove(lastLifeBar)
if (lastLifeBar.Count > 0) {
lifeBars.Last() += OnLifeBarConsumed;
}
}
###
# You can access the action type in the HealthChanged signal
# to determine what kind of action was taken and act accordingly to the flow of your game.
###
public enum TYPES
{
DAMAGE,
HEALTH,
REGEN
}
[Signal]
public delegate void HealthChangedEventHandler(int amount, int type);
[Signal]
public delegate void InvulnerabilityChangedEventHandler(bool active);
[Signal]
public delegate void DiedEventHandler();
GodotParadise is available for free.
If you're grateful for what we're doing, please consider a donation. Developing GodotParadise requires massive amount of time and knowledge, especially when it comes to Godot. Even $1 is highly appreciated and shows that you care. Thank you!
Thank you for your interest in Godot Paradise!
To ensure a smooth and collaborative contribution process, please review our contribution guidelines before getting started. These guidelines outline the standards and expectations we uphold in this project.
📓Code of Conduct: We strictly adhere to the Godot code of conduct in this project. As a contributor, it is important to respect and follow this code to maintain a positive and inclusive community.
If you have built a project, demo, script or example with this plugin let us know and we can publish it here in the repository to help us to improve and to know that what we do is useful.