Experience, Health and Mana Display - Please Help

Hi,

May I please have some help with my UI code?

Having completed the course I am working on fleshing out some additional areas. I have built a experience, health and mana UI display.

For example in the health bar, the size of the bar increases based on the max health the player has, with the fill amount based on the current health the player has.

When the game loads the player is level 1 with the level 1 health:

image

As the player levels up and gains more health, the bar expands and the health fill changes:

image

This all works fine when working with just the 1 scene.

However if I move to the next scene, everything seems to go back to the values held in the prefab:

image

Then when I continue to level up, the bar does not seem to update its size further even though the values have changed (note the experience fill value also doesnt seem to update, which is odd as the fill value seems to still work in health and mana, I imagine its the same type of problem):

image

Potentially I need to be using the ISaveable system? Here is my code. Thanks in advance,

Health Display:

using UnityEngine;

using UnityEngine.UI;

using System;

using RPG.Stats;

using GameDevTV.Saving;

namespace RPG.Attributes

{

    public class HealthDisplay : MonoBehaviour

    {

        Health health;

        [SerializeField] Image cooldownOverlay = null;

        [SerializeField] float baseWidth = 200f;

        RectTransform rectTransform;

        private void Awake()

        {

            health = GameObject.FindWithTag("Player").GetComponent<Health>();

            rectTransform = GetComponent<RectTransform>();

            rectTransform.sizeDelta = new Vector2(baseWidth, rectTransform.sizeDelta.y);

        }

        private void Start()

        {

            UpdateHealthBar();

        }

        void Update()

        {

            UpdateHealthBar();

        }

        private void UpdateHealthBar()

        {

            cooldownOverlay.fillAmount = health.GetHealthPoints() / health.GetMaxHealthPoints();

            float widthMultiplier = health.GetMaxHealthPoints() / health.GetLevelOneMaxHealth();

            float currentWidth = baseWidth * widthMultiplier;

            rectTransform.sizeDelta = new Vector2(currentWidth, rectTransform.sizeDelta.y);

        }

    }

}

ExperienceDisplay:

using UnityEngine;
using UnityEngine.UI;
using System;
using GameDevTV.Saving;

namespace RPG.Stats
{
    public class ExperienceDisplay : MonoBehaviour, ISaveable
    {
        Experience experience;
        [SerializeField] Image cooldownOverlay = null;

        private void Awake()
        {
            experience = GameObject.FindWithTag("Player").GetComponent<Experience>();
        }

        void Start()
        {
            CheckExprience();
        }

        void Update()
        {
            CheckExprience();
        }

        private void CheckExprience()
        {
            cooldownOverlay.fillAmount = (experience.GetExperience() / experience.GetExperienceToLevelUp());
        }

        public object CaptureState()
        {
            return cooldownOverlay.fillAmount;
        }

        public void RestoreState(object state)
        {
            cooldownOverlay.fillAmount = (float)state;
            CheckExprience();
        }
    }

}

The ISaveable is probably the wrong track for this, as to even work, there would have to be a SaveableEntity on the same GameObject for the Saving System to capture.

It’s better not to cache state that’s the domain of another component anyways. Your display’s job is to report what the component it’s tracking says, not to save or restore it.

Let’s get to the root of the problem, though… Is there, by chance a small stack of Null Reference exceptions when you go to the second scene?

My first guess is that your Player in the second scene doesn’t have a Tag of Player… or… my second guess is that something else in your scene has a tag of Player.

1 Like

Thanks Brian! You helped me realise the error might not be on the display script, but the methods the display script was calling.

It was a Null Reference driven by the fact I am using a SerializeField to reference the progression asset to identify the max health of level 1, as this is used to set the size of the original width.

I had assigned the progression asset in the original scene I was working in but not the player prefab. Once updated in the prefab it works a charm.

Thank you!

script below - I am likely doing this a backwards way but it seems to work :slight_smile:


        [SerializeField] Progression progression = null;

        public float GetLevelOneMaxHealth()
        {
            BaseStats baseStats = GetComponent<BaseStats>();

            int currentLevel = baseStats.GetLevel();

            if (currentLevel > 1)
            {
                int firstLevel = 1;
                float levelOneMaxHealthPoints = progression.GetStat(Stat.Health, CharacterClass.Player, firstLevel);
                return levelOneMaxHealthPoints;
            }
            return GetMaxHealthPoints();
        }

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.