maxHealthPoints not updating in a timely manner

Hi!

So, I’ve been fiddling with this code for a while, and I think I get it, but I’m not sure how to resolve this, since it has to to with Unity’s order of operations. I can get max health to update in the inspector for a single scene, but when I load a scene my health points are reset to 50 (the value for level 1) no matter the current experience points / level.

It works when I kill something, which is fine, until I need to switch scenes. Putting maxHealthPoints = baseStats.GetStat(Stat.Health); in the RestoreState(state) method within the Health class returns 0, as though the lookupTable needs to be initialized.

In subsequent scenes, my exp and level are saved, but health does not update until I kill something, in line with my expectation of the code in AwardExperience updating. It’s just a problem with RestoreState().

Is there some trick to the order of operations that I’m missing?

Health.cs:

using UnityEngine;
using RPG.Saving;
using RPG.Stats;
using RPG.Core;

namespace RPG.Attributes
{
    public class Health : MonoBehaviour, ISaveable
    {
        [SerializeField] float damageTaken = 0;
        [SerializeField] float maxHealthPoints = 0f;
        bool isDead = false;
        BaseStats baseStats = null;
        public float MaxHealthPoints {get{ return maxHealthPoints;} set{maxHealthPoints = value;}}
        

        private void Awake() {
            baseStats = GetComponent<BaseStats>();
            maxHealthPoints = baseStats.GetStat(Stat.Health);
            
        }

        public bool IsDead()
        {
            return isDead;
        }


        public void TakeDamage(GameObject instigator, float damage) {

            damageTaken += damage;
            if(damageTaken > maxHealthPoints){
                damageTaken = maxHealthPoints;
            }
            // This is where they die or are revived based on current health.
            SetHealthState(instigator); 
            
        }

        public void Heal(float healValue){
            damageTaken -= healValue;
            if(damageTaken < 0){
                damageTaken = 0;
            }
        }

        public float GetPercentage(){
            return Mathf.Clamp((maxHealthPoints - damageTaken) / maxHealthPoints * 100,0,100);
        }

        private void SetHealthState(GameObject instigator)
        {
            if (instigator == gameObject) return;

            if (damageTaken >= maxHealthPoints)
            {
                Die();
                AwardExperience(instigator.gameObject);
            }
            else
            {
                Revive();
            }
        }

        private void AwardExperience(GameObject instigator)
        {
            Health instigatorHealth = instigator.GetComponent<Health>();
            Experience experience = instigator.GetComponent<Experience>();
            if(experience == null || instigatorHealth == null) return;

            instigator.GetComponent<Health>().MaxHealthPoints = instigatorHealth.baseStats.GetStat(Stat.Health);
            experience.GainExperience(baseStats.GetStat(Stat.ExperienceReward));
            
            print("Saved health: " + instigator.GetComponent<Health>().MaxHealthPoints);
            
        }


        private void Die()
        {
            if (isDead) return;

            isDead = true;
            GetComponent<Animator>().SetTrigger("die");
            GetComponent<ActionScheduler>().CancelCurrentAction();
            GetComponent<CapsuleCollider>().enabled = false;
        }
        private void Revive()
        {
            if (!isDead) return;

            isDead = false;
            GetComponent<Animator>().SetTrigger("revive");
                    
        }
        
        public object CaptureState()
        {
            return damageTaken;
        }

        public void RestoreState(object state)
        {
            damageTaken = (float)state;
            // Set max health from current level
            maxHealthPoints = baseStats.GetStat(Stat.Health);
            // Load the freshly set maxHealthPoints to see contents
            print("Loading: " + maxHealthPoints);
            if (damageTaken >= maxHealthPoints) {
                Die();
            }
        }
    }
}

Thanks for reading this far!

From your description, you may be fighting a race condition, where a component is calling on another component before it’s initialized.

We address this issue in the lecture Lazy Initialization

Privacy & Terms