C#如何使函数/方法在不阻塞程序的情况下等待(Unity)

C#如何使函数/方法在不阻塞程序的情况下等待(Unity),c#,unity3d,fork,wait,C#,Unity3d,Fork,Wait,我想在unity的游戏中,在函数RestoreHealth()中模拟生命再生 我是不是想创建一个子进程而想得太多了,所以当我调用wait时,它不会影响任何当前正在运行的进程或线程,并且当函数完成时,子进程将死亡 public void RestoreHealth() { if (health >= MaxHealth) return; // health and MaxHealth are Class variables if (health % 10 != 0) {

我想在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);
    }
}
然后用它来启动协同程序

 void Start(){

    StartCoroutine(player.RestoreArmour());
}

您可以创建一个计时器,假设您在update方法中运行它

private float timer=1;
专用浮动时间设置=1;
私有void更新(){
恢复健康();
}
公共卫生(恢复健康){
if(health>=MaxHealth)return;//health和MaxHealth是类变量
如果(运行状况%10!=0){//如果运行状况不能除以10
int temp=health%10;//然后我们将其四舍五入到最接近的十分之一
温度=10-温度;
健康+=温度;
}
int i=健康;
对于(;i0){
计时器-=1*time.deltaTime;
}否则{
健康+=10;
Debug.Log(“运行状况:+Health”);
定时器=定时器设置;
}
}
}
或者你可以简单地给你的玩家每秒1点生命值,或者任何数量的生命值

public void RestoreHealth(){
if(health>=MaxHealth)return;//health和MaxHealth是类变量
如果(运行状况%10!=0){//如果运行状况不能除以10
int temp=health%10;//然后我们将其四舍五入到最接近的十分之一
温度=10-温度;
健康+=温度;
}
int i=健康;
对于(;i
因此,在这种情况下,玩家每秒获得10点生命值,但值始终会上升,因此在一秒钟内,玩家的生命值将每100ms增加1点生命值 在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秒。

fork()
不会创建进程。它创建了一个线程。是的,您可以在C#中创建线程。在unity中,您不能创建线程,因为unity仅在多线程的主线程上运行,您必须使用服务器并查询服务器以执行操作。这不是一个无限循环,因为计时器总是重置为1吗?另外,当玩家最初受到伤害时,这个函数被调用。只有当计时器一直倒计时到零时,它才会被重置。是的,我可以工作,但我想要一个更明显的缓慢增量。谢谢,虽然我替换了“WaitForEndOfFrame();“返回新的等待秒(ArmourRegenRate);”相反,太棒了!无论什么对你有用,我只是想在这里展示这个概念。记住,这些东西是异步的,这意味着你应该确保一次只启动其中一个,当然,除非你需要多个异步运行;这个实现看起来很棒!嗯,所以每次玩家受到伤害时都会调用这个RestoreArmour()函数,如果玩家在盔甲再生时再次被击中,那就不好了,我需要停止当前运行的函数并重新启动itAh,是的。常见用例;去抖功能。我将更新我的代码,向您展示我通常如何实现这一点。1秒
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;
}