Unity2D Player Health Bar Tutorial | Unity Tutorial
In this Unity2D tutorial, we’ll create a dynamic health bar for your game, covering everything from setting up the UI to scripting player health management. You’ll learn how to implement a health system that updates in real-time as the player takes damage and revives, including integrating a revival mechanism using rewarded ads. By the end, you'll have a fully functional health bar that enhances your game's user experience.
WATCH FULL TUTORIAL ON YOUTUBE
=========================================================
Unity Projects - ON SALE!!!
1. Water Sort Puzzle 9000 Levels
2. Ball Sort Puzzle 9000 Levels
3. Sling Shot
=========================================================
Scripts:
PlayerController.cs
using System.Collections;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private float movementInput;
public float walkSpeed = 8f;
public float jumpStrength = 16f;
private bool facingRight = true;
private bool canPerformDash = true;
private bool isCurrentlyDashing;
private float dashStrength = 24f;
private float dashDuration = 0.2f;
private float dashCooldownTime = 1f;
private float dashInvincibilityDuration = 0.2f;
[SerializeField] private Rigidbody2D playerRigidbody;
[SerializeField] private Transform groundChecker;
[SerializeField] private LayerMask groundMask;
[SerializeField] private TrailRenderer dashTrail;
[SerializeField] private Animator characterAnimator;
[SerializeField] private AudioSource dashAudio;
private bool isPaused = false; // New variable to manage pause state
private void Update()
{
if (isPaused || isCurrentlyDashing)
{
return; // Skip processing if paused or dashing
}
movementInput = Input.GetAxisRaw("Horizontal");
if (Input.GetButtonDown("Jump") && CheckIfGrounded())
{
playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, jumpStrength);
}
if (Input.GetButtonUp("Jump") && playerRigidbody.velocity.y > 0f)
{
playerRigidbody.velocity = new Vector2(playerRigidbody.velocity.x, playerRigidbody.velocity.y * 0.5f);
}
if (Input.GetKeyDown(KeyCode.LeftShift) && canPerformDash)
{
StartCoroutine(ExecuteDash());
}
HandleCharacterFlip();
}
private void FixedUpdate()
{
if (isPaused || isCurrentlyDashing)
{
return; // Skip processing if paused or dashing
}
playerRigidbody.velocity = new Vector2(movementInput * walkSpeed, playerRigidbody.velocity.y);
}
private bool CheckIfGrounded()
{
return Physics2D.OverlapCircle(groundChecker.position, 0.2f, groundMask);
}
private void HandleCharacterFlip()
{
if (facingRight && movementInput < 0f || !facingRight && movementInput > 0f)
{
Vector3 localScale = transform.localScale;
facingRight = !facingRight;
localScale.x *= -1f;
transform.localScale = localScale;
}
}
private IEnumerator ExecuteDash()
{
canPerformDash = false;
isCurrentlyDashing = true;
// Trigger dash animation
if (characterAnimator != null)
{
characterAnimator.SetTrigger("Dash");
}
// Play dash sound effect
if (dashAudio != null)
{
dashAudio.Play();
}
float initialGravity = playerRigidbody.gravityScale;
playerRigidbody.gravityScale = 0f;
// Determine dash direction based on character's facing direction
float dashDirection = facingRight ? 1f : -1f;
playerRigidbody.velocity = new Vector2(dashDirection * dashStrength, 0f);
// Activate trail effect
if (dashTrail != null)
{
dashTrail.emitting = true;
}
// Optional: Handle dash invincibility or other effects here
Collider2D[] nearbyEnemies = Physics2D.OverlapCircleAll(transform.position, 0.5f, LayerMask.GetMask("Enemy"));
foreach (var enemy in nearbyEnemies)
{
// Implement logic for interaction with enemies
}
yield return new WaitForSeconds(dashDuration);
// Deactivate trail effect
if (dashTrail != null)
{
dashTrail.emitting = false;
}
playerRigidbody.gravityScale = initialGravity;
isCurrentlyDashing = false;
yield return new WaitForSeconds(dashCooldownTime);
canPerformDash = true;
}
// Method to set the pause state
public void SetPause(bool pause)
{
isPaused = pause;
if (pause)
{
// Optional: Stop player movement immediately
playerRigidbody.velocity = Vector2.zero;
}
}
}
------------------------------------------------------------------------------------------------------------------------------------------
PlayerHealth.cs
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
public int maxHealth = 100;
public int damage = 10;
public int reviveAmount = 50; // Single revive amount value
private int currentHealth;
public Slider healthSlider;
public GameObject deathPopup;
private PlayerController playerController;
private Vector3 respawnPosition;
private GameManager gameManager;
void Start()
{
currentHealth = maxHealth;
respawnPosition = transform.position;
gameManager = FindObjectOfType<GameManager>();
if (healthSlider != null)
{
healthSlider.maxValue = maxHealth;
healthSlider.value = currentHealth;
}
if (deathPopup != null)
{
deathPopup.SetActive(false);
}
playerController = GetComponent<PlayerController>();
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Enemy"))
{
TakeDamage(damage);
}
}
void TakeDamage(int damage)
{
currentHealth -= damage;
if (currentHealth < 0) currentHealth = 0;
if (healthSlider != null)
{
healthSlider.value = currentHealth;
}
if (currentHealth <= 0)
{
Die();
}
}
void Die()
{
if (deathPopup != null)
{
deathPopup.SetActive(true);
}
if (playerController != null)
{
playerController.SetPause(true);
}
respawnPosition = transform.position;
if (gameManager != null)
{
gameManager.SaveScore();
}
Debug.Log("Player is dead!");
}
public void Revive()
{
currentHealth = Mathf.Clamp(currentHealth + reviveAmount, 0, maxHealth);
if (healthSlider != null)
{
healthSlider.value = currentHealth;
}
if (deathPopup != null)
{
deathPopup.SetActive(false); // Deactivate the death popup
}
if (playerController != null)
{
playerController.SetPause(false);
}
transform.position = respawnPosition;
if (gameManager != null)
{
gameManager.RestoreScore();
}
}
}
--------------------------------------------------------------------------------------------------------------------------------------------
GameManager.cs
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
public int currentScore;
public void SaveScore()
{
// Save the score to a persistent storage if needed
PlayerPrefs.SetInt("SavedScore", currentScore);
PlayerPrefs.Save();
}
public void RestoreScore()
{
// Restore the score from persistent storage
if (PlayerPrefs.HasKey("SavedScore"))
{
currentScore = PlayerPrefs.GetInt("SavedScore");
}
}
public void RestartLevel()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void Home()
{
//SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
-------------------------------------------------------------------------------------------------------------------------------------------
AdsManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GoogleMobileAds;
using GoogleMobileAds.Api;
using System;
public class AdsManager : MonoBehaviour
{
private RewardedAd rewardedAd;
public string rewardedId = "";
private PlayerHealth playerHealth;
void Start()
{
MobileAds.Initialize((InitializationStatus initStatus) =>
{
// This callback is called once the MobileAds SDK is initialized.
LoadRewardedAd();
});
playerHealth = FindObjectOfType<PlayerHealth>();
}
void Awake()
{
//
}
public void LoadRewardedAd()
{
// Clean up the old ad before loading a new one.
if (rewardedAd != null)
{
rewardedAd.Destroy();
rewardedAd = null;
}
Debug.Log("Loading the rewarded ad.");
// create our request used to load the ad.
var adRequest = new AdRequest();
// send the request to load the ad.
RewardedAd.Load(rewardedId, adRequest,
(RewardedAd ad, LoadAdError error) =>
{
// if error is not null, the load request failed.
if (error != null || ad == null)
{
Debug.LogError("Rewarded ad failed to load an ad " +
"with error : " + error);
return;
}
Debug.Log("Rewarded ad loaded with response : "
+ ad.GetResponseInfo());
rewardedAd = ad;
RegisterEventHandlers(rewardedAd);
});
}
public void ShowRewardedAd()
{
const string rewardMsg =
"Rewarded ad rewarded the user. Type: {0}, amount: {1}.";
if (rewardedAd != null && rewardedAd.CanShowAd())
{
rewardedAd.Show((Reward reward) =>
{
// TODO: Reward the user.
Debug.Log(String.Format(rewardMsg, reward.Type, reward.Amount));
});
}
}
private void RegisterEventHandlers(RewardedAd ad)
{
// Raised when the ad is estimated to have earned money.
ad.OnAdPaid += (AdValue adValue) =>
{
Debug.Log(String.Format("Rewarded ad paid {0} {1}.",
adValue.Value,
adValue.CurrencyCode));
};
// Raised when an impression is recorded for an ad.
ad.OnAdImpressionRecorded += () =>
{
Debug.Log("Rewarded ad recorded an impression.");
//HERE WILL GO THE REWARDED VIDEO CALLBACK!!!!
if (playerHealth != null)
{
playerHealth.Revive();
}
};
// Raised when a click is recorded for an ad.
ad.OnAdClicked += () =>
{
Debug.Log("Rewarded ad was clicked.");
};
// Raised when an ad opened full screen content.
ad.OnAdFullScreenContentOpened += () =>
{
Debug.Log("Rewarded ad full screen content opened.");
};
// Raised when the ad closed full screen content.
ad.OnAdFullScreenContentClosed += () =>
{
Debug.Log("Rewarded ad full screen content closed.");
LoadRewardedAd();
};
// Raised when the ad failed to open full screen content.
ad.OnAdFullScreenContentFailed += (AdError error) =>
{
Debug.LogError("Rewarded ad failed to open full screen content " +
"with error : " + error);
LoadRewardedAd();
};
}
}