C# 如何使 function/Method 等待而不阻塞程序 (Unity)

C# how to Make function/Method Wait without blocking program (Unity)

我想在函数 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 中创建子进程并使其等待?

是否有 C 语言中 Fork(); 的等效项?

此外,当玩家最初受到伤害时会调用此函数。

解决方法:

注意:我将 Health 更改为 Armour

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

你可以创建一个定时器,假设你在更新方法中运行这个

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 点生命值,但该值将始终上升,因此在一秒钟内玩家的生命值将每 100 毫秒增加 1 点生命值

基本协程概念

在 Unity 中,您使用协程来实现这种异步 "threaded" 行为

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 秒。