Reputation: 19
I just implemented a heal overtime to my unity project and I was wondering how do I stop the heal overtime while the player in in range of the enemy.. and then start the heal overtime when the player is out of range of the enemy? I tried using a bool and it didn't work.. I also tried using StopCoroutine what also didn't work
Here is my code:
private void Awake()
{
if (currentHealth < 100)
{
StartCoroutine(HealCo());
}
healDuration = new WaitForSeconds(2f);
}
private void Update()
{
healthbar.value = currentHealth;
if (currentHealth > maxHealth)
{
currentHealth = 100;
}
}
private IEnumerator HealCo()
{
currentHealth += healAmount;
yield return healDuration;
StartCoroutine(HealCo());
}
Upvotes: 0
Views: 391
Reputation: 729
One option would be to use the enabled flag that all MonoBehaviours already have.
private void OnEnable()
{
StartCoroutine(HealingLoop());
}
public void SetHealth(float value)
{
currentHealth = Mathf.Clamp(value, 0f, 100f);
healthbar.value = currentHealth;
}
private IEnumerator HealingLoop()
{
while(enabled)
{
yield return healDuration;
SetHealth(currentHealth + healAmount)
}
}
This relies on HealingLoop coming to an end when the enabled property is set to false, and the OnEnable event function starting it running again when the enabled property is set back to enabled.
UPDATE: You can set the state of the enabled property based on whether or not enemies are currently in range of the player by creating another component that invokes a UnityEvent whenever enemies come within the range or leave the range.
using UnityEngine;
using UnityEngine.Events;
public class EnemyInRangeChangedEventTrigger : MonoBehaviour
{
[SerializeField]
private bool invertReactionArgument;
[SerializeField]
private UnityEvent<bool> reaction;
private bool enemyInRangeLastFrame;
private void OnEnable()
{
bool enemyInRangeNow = IsEnemyInRange();
InvokeReaction(enemyInRangeNow);
enemyInRangeLastFrame = enemyInRangeNow;
}
private void Update()
{
bool enemyInRangeNow = IsEnemyInRange();
if(enemyInRangeNow != enemyInRangeLastFrame)
{
InvokeReaction(enemyInRangeNow);
enemyInRangeLastFrame = enemyInRangeNow;
}
}
private bool IsEnemyInRange() => enemyMovement.chase;
private void InvokeReaction(bool enemyInRangeNow) => reaction.Invoke(invertReactionArgument ? !enemyInRangeNow : enemyInRangeNow);
}
Then you can connect this event to the enabled property using the Inspector.
Upvotes: 0
Reputation: 326
You don't need a coroutine if you are using Update() method. It really depends on the architecture and what you exactly need, but the easiest way for me will be to create the method Heal() and check in Update() if it should be invoked. That can be done using bool isHealing which value can be set whatever you want.
If you want to heal exact value of HP or time then calculate everything in update like (timeHealing - Time.deltaTime) etc
Upvotes: 0