3

I want to simulate health regeneration in my game in unity, in the function RestoreHealth().

Am I overthinking it by wanting to create a child process, so when I call wait, it won't affect any current running process or thread and the child process will die when the function is done.

public void RestoreHealth() {
    if (health >= MaxHealth) return; // health and MaxHealth are Class variables

    if (health % 10 != 0) {     // if health is not dividable by 10
        int temp = health % 10; // then we round it to the closest 
                                //tenth
        temp = 10 - temp;
        health += temp;
    }

    int i = health;

    for (; i < MaxHealth; i += 10) {  // where the health grows till 100
        health += 10;
        // sleep(1000);  // make function wait for '1 second' to iterate again

        Debug.Log("Health: " + health);
    }
}

How do I create a child process in C# or unity in this case and cause it to wait?

Is there an equivalent to Fork(); like in C?

Also, this function is called when the player initially receives damage.

Solution:

note: I changed Health to Armour

public IEnumerator RestoreArmour() {
        while (_Armour < _MaxArmour) {
            _Armour++;
            Debug.Log("Health: " + _Armour);
            yield return new WaitForSeconds(ArmourRegenRate); // ArmourRegenRate is a 
                                                             // float for the seconds
        }
    }

and use this to initiate the coroutine

 void Start(){

    StartCoroutine(player.RestoreArmour());
}
2
  • fork() doesn't create a process. It creates a thread. Yes, you can create threads in C#. Commented May 17, 2019 at 20:51
  • In unity you can't create threads because unity only runs on the main thread for multi-threading you would have to use a server and query the server to perform actions @Amy Commented May 17, 2019 at 20:53

2 Answers 2

5

Basic Coroutine concept

In Unity you work with Coroutines to achieve this asychronous "threaded" behaviour

IEnumerator RestoreHealth() {
   while (health != MaxHealth) {
       health++;
       yield return new WaitForEndOfFrame();
   }
}

and then invoke it with

StartCoroutine(RestoreHealth());

Restarting a Coroutine

In order to stop an existing Coroutine from running and start a new one, this is how you would achieve that:

private Coroutine _myCoroutine = null;

void SomeMethod()
{
    if (_myCoroutine != null)
        StopCoroutine(_myCoroutine);

    _myCoroutine = StartCoroutine(SomeOtherMethod());
}


Pausing armor restoration for X seconds when player has taken damage

A common functionality is to have something restore armor when player hasn't taken damage for X seconds:

private bool _shouldRestoreArmour = true;
private Coroutine _pauseArmorCoroutine = null;

void Update()
{
    if (_shouldRestoreArmour)
        Armor += ArmorRegenerationPerSecond * Time.deltaTime;
}

void PlayerTakeDamage() 
{
    if (_pauseArmorCoroutine != null) 
        StopCoroutine(_pauseArmorCoroutine);

    _pauseArmorCoroutine = StartCoroutine(PauseRestoreArmor());

    // Take damage code
}

IEnumerator PauseRestoreArmor()
{
    _shouldRestoreArmor = false;
    yield return new WaitForSeconds(RESTORE_ARMOR_DELAY_TIME);
    _shouldRestoreArmor = true;
}

Here the player will regenerate armor at all times, except for X seconds after the player has taken damage. If the player takes damage multiple times we will simply abort the previous coroutine and start a new one, so that it will be a fresh X seconds from the last hit.

Sign up to request clarification or add additional context in comments.

6 Comments

I replace 'WaitForEndOfFrame(); with 'yield return new WaitForSeconds(ArmourRegenRate); ' instead
Great! Whatever works for you, I just wanted to show the concept here. Remember that these things are asynchronous, meaning you should make sure to only start ONE of these at the time, unless you need multiple of the running asynchronously, of course.
I see the update in your original post; that implementation looks great!
hmm, so this RestoreArmour() function would be called every time the player is Damaged, if the player gets hit again while the armour is regenerating, then it would be bad, i need to halt the current running function and restart it
Ah, yes. A common use-case; a debouncer functionality. I'll update my code to show you how I usually implement this. 1 sec
|
0

You can create a timer assuming that you run this in the update method

private float timer = 1;
private float timerReset = 1;

private void Update(){
  RestoreHealth();
}

public void RestoreHealth() {
  if (health >= MaxHealth) return; // health and MaxHealth are Class variables

  if (health % 10 != 0) {     // if health is not dividable by 10
    int temp = health % 10; // then we round it to the closest tenth
    temp = 10 - temp;
    health += temp;
  }
  int i = health;
  for (; i < MaxHealth; i += 10) {  // where the health grows till 100
    if(timer > 0){
      timer -= 1 * time.deltaTime;
    }else{
      health += 10;
      Debug.Log("Health: " + health);
      timer = timerReset;
    }
  }

}

or you can simply just give your player 1 health every second or whatever amount for instance

    public void RestoreHealth() {
      if (health >= MaxHealth) return; // health and MaxHealth are Class variables

      if (health % 10 != 0) {     // if health is not dividable by 10
        int temp = health % 10; // then we round it to the closest tenth
        temp = 10 - temp;
        health += temp;
      }
      int i = health;
      for (; i < MaxHealth; i += 10) {  // where the health grows till 100

          health += 10 * 1 * time.deltaTime;
          Debug.Log("Health: " + health);
          timer = timerReset;

      }

    }

So in this scenario your player recieves 10 health every second but the value will always go up so in the matter of a second the player health would go up 1 health every 100ms

3 Comments

won't this be an infinite loop because the timer is always reset to 1? also, this function is called when the player initially receives damage.
It only gets reset once the timer has counted down all the way to zero then it is reset
yeah i works but i want a more noticeable slow increment. thanks though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.