Why is Sam not using the TakeDamageEvent we set up instead of Update()

So in this section we were going to make our Health Bar reflect the actual health of the enemies and I went on and made a mini challenge to finish it beforehand, now when I see Sam’s solution I am so confused as to why we are using update() to update the Health Bar when we have a very distinct and clearly defined moment in time when the Health Bar needs to be updated from when we created the TakeDamageEvent (unity event in Health.cs)?

My solution:

namespace Scripts.Attributes
{
    public class HealthBar : MonoBehaviour
    {
        [SerializeField] GameObject healthBarImage = null;

        Vector3 _scalingVector;
        bool _healthBarEnabled = false;
        
        void Awake()
        {
            _scalingVector = new Vector3(1, 1, 1);
            healthBarImage.transform.localScale = _scalingVector;
            transform.GetChild(0).gameObject.SetActive(false);
        }

        public void UpdateHealthBar(GameObject character)
        {
            if (!_healthBarEnabled)
            {
                transform.GetChild(0).gameObject.SetActive(true);
                _healthBarEnabled = true;
            }
            _scalingVector = new Vector3(character.GetComponent<Health>().GetHealthPercentage(), 1, 1);
            healthBarImage.transform.localScale = _scalingVector;
            if (_scalingVector.x <= 0)
            {
                DeactivateHealthBar();
            }
        }

        void DeactivateHealthBar()
        { 
            transform.GetChild(0).gameObject.SetActive(false);
            _healthBarEnabled = false;
        }
    }
}

HealthBar.UpdateHealthBar() is called in Health.ApplyDamage() by the UnityEvent:

public void ApplyDamage(GameObject instigator, float damage)
        {
            _health.value = Mathf.Max(_health.value - damage, 0);
            takeDamage.Invoke(damage);
            if (_health.value == 0 && _isAlive)
            {
                GainExperience(instigator);
                TimeToDie();
            }
        }

And it is set up on my enemy prefab as such:
image

And Sam did:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace RPG.Attributes
{
    public class HealthBar : MonoBehaviour
    {
        [SerializeField] Health healthComponent = null;
        [SerializeField] RectTransform foreground = null;


        void Update()
        {
            foreground.localScale = new Vector3(healthComponent.GetFraction(), 1, 1);
        }
    }
} 

That is obviously much cleaner and easier to read even though he will probably add a way to deactivate the healthbar when enemies are dead though. But yeah, why had so many Updates running on all the enemies in a scene when we spent time setting up the Unity event previously? And tbh, even if we had NOT set that up I would still prefer to call a updatehealth() method from Health.ApplyDamage() since we do not need to update health elements constantly.

So am I wrong (I suspect I am) and if so, why? Can I keep my way or will it cause issues down the line in the course?

2 Likes

I’ve also refactored my UI updates to happen via events. I haven’t had any issues, you only have to figure out how to apply the code in Update in event functions. For the health bar, there will be a change to have it hide on 0% / 100% HP but for me, it was enough to just move the whole code from Update to my event function without any further changes and it works as intended. Also in order to check whether or not the health bar / other UI needs to show at the start of the game, your event function will need to be called once in the Start method, updated via events afterwards.

That’s pretty much what I do myself. Not only is there nothing wrong with your approach, it’s a good approach, and IMO the correct approach. Well done.
Sam’s approach isn’t neccesarily wrong, and in early prototyping, it’s fairly typical to throw these things in an Update() and then refactor later.

2 Likes

Thanks guys, that’s reassuring.

This topic was automatically closed after 9 hours. New replies are no longer allowed.

Privacy & Terms