C # как сделать функцию / метод ожидания без блокировки программы (Unity) - PullRequest
3 голосов
/ 17 мая 2019

Я хочу симулировать регенерацию здоровья в моей игре в единстве, в функции RestoreHealth().

Не слишком ли я продуман, желая создать дочерний процесс, поэтому, когда я вызываю wait, он не будетповлияет на любой текущий запущенный процесс или поток, и дочерний процесс умрет, когда функция будет выполнена.

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);
    }
}

Как создать в этом случае дочерний процесс в C # или Unity и заставить его ждать?

Есть ли эквивалент Fork();, как в C?

Также эта функция вызывается, когда игрок изначально получает урон.

Решение :

примечание: я изменил здоровье на Броню

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

и используйте это для запуска сопрограммы

 void Start(){

    StartCoroutine(player.RestoreArmour());
}

Ответы [ 2 ]

5 голосов
/ 18 мая 2019

Базовая концепция сопрограмм

В Unity вы работаете с сопрограммами для достижения этого асинхронного «многопоточного» поведения

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

, а затем вызываете его с помощью

StartCoroutine(RestoreHealth());

Перезапуск сопрограммы

Чтобы остановить запуск подпрограммы и запустить новую подпрограмму, вот как можно этого добиться:

private Coroutine _myCoroutine = null;

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

    _myCoroutine = StartCoroutine(SomeOtherMethod());
}


Приостановка восстановления брони дляX секунд, когда игрок получил урон

Обычная функция - что-то восстановить броню, если игрок не получил урон в течение X секунд:

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;
}

Здесь игрок вообще регенерирует бронюраз, кроме X секунд после того, как игрок получил урон.Если игрок получает урон несколько раз, мы просто прервем предыдущую сопрограмму и запустим новую, так что это будут свежие X секунд от последнего удара.

0 голосов
/ 17 мая 2019

Вы можете создать таймер, предполагая, что вы запустите его в методе обновления

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;
    }
  }

}

или вы можете просто дать своему игроку 1 здоровье каждую секунду или любую другую сумму, например

    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;

      }

    }

Таким образом, в этом сценарии ваш игрок получает 10 единиц здоровья каждую секунду, но значение всегда будет увеличиваться, поэтому в течение секунды здоровье игрока будет увеличиваться на 1 единицу здоровья каждые 100 мсек

...