I implemented the Health bar concept from the RPG Core Combat Creator course into a Health bar HUD, and I did the same for Mana and Experience. It was all working so I saved the project and closed Unity, then I opened and it was still working. I added some icons (Inventory, Quests, and Pause) to the HUD, also I changed the name of the UI prefab. Because, I designed 5 other HUDs (on google drive) so I could playtest them to get feedback on which HUD the player testers liked. It was still working, and I saved the project and closed Unity. I opened Unity to do some more work, and that is when things got buggy.
First the trail of the arrows are colliding off of the arrow, but that is not my main concern. My main concern is the Health bar HUD isn’t working, the health display is working fine but not the bar. Also, the health bar from the enemies is working. Here is the code and a screenshot of the console.
using UnityEngine;
using RPG.Saving;
using RPG.Stats;
using RPG.Core;
using System;
using RPG.Utils;
using UnityEngine.Events;
namespace RPG.Attributes
{
public class Health : MonoBehaviour, ISaveable
{
[SerializeField] float regenerationPercentage = 70;
[SerializeField] TakeDamageEvent takeDamage;
public UnityEvent onDie;
[System.Serializable]
public class TakeDamageEvent : UnityEvent<float>
{
}
LazyValue <float> healthPoints;
bool wasDeadLastFrame = false;
void Awake()
{
healthPoints = new LazyValue<float>(GetInitialHealth);
}
private float GetInitialHealth()
{
return GetComponent<BaseStats>().GetStat(Stat.Health);
}
void Start()
{
healthPoints.ForceInit();
}
void OnEnable()
{
GetComponent<BaseStats>().onLevelUp += RegenerateHealth;
}
void OnDisable()
{
GetComponent<BaseStats>().onLevelUp -= RegenerateHealth;
}
public bool IsDead()
{
return healthPoints.value <=0;
}
public void TakeDamage(GameObject instigator, float damage)
{
healthPoints.value = Mathf.Max(healthPoints.value - damage, 0);
if(IsDead())
{
onDie.Invoke();
AwardExperience(instigator);
}
else
{
takeDamage.Invoke(damage);
}
UpdateState();
}
public void Heal(float healthToRestore)
{
healthPoints.value = Mathf.Min(healthPoints.value + healthToRestore, GetMaxHealthPoints());
UpdateState();
}
public float GetHealthPoints()
{
return healthPoints.value;
}
public float GetMaxHealthPoints()
{
return GetComponent<BaseStats>().GetStat(Stat.Health);
}
public float GetPercentage() //To Display the health percentage in text. Subject to change.
{
return 100 * GetFraction();
}
public float GetFraction()
{
return healthPoints.value / GetComponent<BaseStats>().GetStat(Stat.Health);
}
private void UpdateState()
{
Animator animator = GetComponent<Animator>();
if (!wasDeadLastFrame && IsDead())
{
GetComponent<Animator>().SetTrigger("Die");
GetComponent<ActionScheduler>().CancelCurrentAction();
}
if(wasDeadLastFrame && !IsDead())
{
animator.Rebind();
}
wasDeadLastFrame = IsDead();
}
private void AwardExperience(GameObject instigator)
{
Experience experience = instigator.GetComponent<Experience>();
if (experience == null) return;
experience.GainExperience(GetComponent<BaseStats>().GetStat(Stat.ExperienceReward));
}
private void RegenerateHealth()
{
float regenHealthPoints = GetComponent<BaseStats>().GetStat(Stat.Health) * (regenerationPercentage / 100);
healthPoints.value = Mathf.Max(healthPoints.value, regenHealthPoints);
}
public object CaptureState()
{
return healthPoints.value;
}
public void RestoreState(object state)
{
healthPoints.value = (float)state;
UpdateState();
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace RPG.Attributes
{
public class HealthBarHUD : MonoBehaviour
{
[SerializeField] Health healthComponent = null;
[SerializeField] RectTransform foreground = null;
void Update()
{
foreground.localScale = new Vector3(healthComponent.GetFraction(), 1, 1);
}
}
}
Thank you,
Eric