I’ve just used the LazyValue and event Sam taught and the design pattern Brain mentioned to rewrite the following HealthBar script, it’s working as expected but not sure if this is a correct way to write (as this is first time I’ve learned such thing like LazyValue and event). Would like to get some feedbacks if possible:
-
Is it necessary for using LazyValue here because I’m not sure if there is a racing condition for child component to get the component in parent by invoking GetComponentInParent() in Awake, but didn’t experience any issue if not using LazyValue.
-
Is my event pattern used here ok or needed any correction?
Thank you in advance if anyone could provide some feedbacks.
public class HealthBar : MonoBehaviour
{
[SerializeField] RectTransform imgRectTransform = null;
LazyValue<Health> healthComponent;
void Awake()
{
healthComponent = new LazyValue<Health>(() => GetComponentInParent<Health>());
}
void OnEnable()
{
healthComponent.value.onHealthUpdateEvent += UpdateImageBar;
}
void OnDisable()
{
healthComponent.value.onHealthUpdateEvent += UpdateImageBar;
}
void Start()
{
healthComponent.ForceInit();
}
private void UpdateImageBar()
{
imgRectTransform.localScale = new Vector3(healthComponent.value.GetHealthFraction(), 1, 1);
}
}
The event was in Health script:
public class Health : MonoBehaviour, ISaveable
{
// event:
public event Action onHealthUpdateEvent;
...
public void TakeDamage(GameObject instigator, float damage)
{
healthPoints.value = Mathf.Max(healthPoints.value - damage, 0);
if (healthPoints.value <= 0)
{
Die();
AwardExperience(instigator);
}
takeDamageEvent.Invoke(damage);
onHealthUpdateEvent(); // here invoking the onHealthUpdateEvent;
}
...
}
NEW UPDATE:
I just noticed that we can just using our already defined “[SerializeField] UnityEvent takeDamageEvent;” in Health.cs script and hook the UpdateImageBar() defined in HealthBar.cs script as the following, so we can do both in one event. Just wondering which approach would be better. Thank you.