如何从 OnTriggerStay 协程启动和停止其他协程

How to start and stop other coroutines from a OnTriggerStay coroutine

我对编程还很陌生,所以很乐意提供帮助。

这在 理论 中应该有效,但由于某种原因,当我 运行 在 unity 中它只是不起作用并且我不知道为什么

我希望这个伤害系统可以工作,但我希望SFX伤害率 不同 但是我不确定如何做到这一点,这是我能想到的最好的。

问题: 尽管它确实会造成伤害,但它会反复叠加伤害。当我不应该受到伤害时,它不会因为某种原因停止。

    IEnumerator OnTriggerStay2D(Collider2D collision)
    {
        if (collision.CompareTag("Damage"))
        {
            //The StopCoroutine here is supposed to stop it from stacking however I am getting 
            //mixed results
                 
            StopCoroutine(Damager());
            StopCoroutine(DamageSFX());

            StartCoroutine(Damager());
            StartCoroutine(DamageSFX());
        }
         
        //I feel like it should be an "else if" method but I'm not sure why or how

        else
        {
            StopCoroutine(Damager());
            StopCoroutine(DamageSFX());
        }

        yield return new WaitForEndOfFrame();
    }

    IEnumerator Damager()
    {
        while (true)
        {
            curruntHealth--;

            yield return new WaitForSeconds(Delay);
        }
    }

    IEnumerator DamageSFX()
    {
        while (true)
        {
            //This part works perfectly fine on its own but not in this context
            FindObjectOfType<AudioManager>().Play("Damage SFX");

            yield return new WaitForSeconds(SoundDelay);
        }
    }

你很接近,但这里有几件事要看。

首先 - 您可能需要一个简单的 bool 标志 来检查您是否启动了破坏性协程,这将阻止它们被重复创建。在您发布的示例中,您希望在 OnTriggerExit2D(Collider2D other)

中连接 Stop

其次 - 当您使用方法启动协程时,我相信您必须获得的参考是停止它。如果您改用字符串,它会更容易停止。 example of ref to couroutine and string calls

这是一个可以满足您需要的示例。代替 OnTriggerStay 我只是使用 public bool 我可以在检查器中切换。

public bool iscolliding;

float delay = 1f;
float sounddelay = 3f;

bool takingDamage = false;

// ref to started coroutine for start/stop if you didn't want to use strings
// private IEnumerator damageCoroutine;

private void Update()
{
    // we have a collision
    // this would be OnTriggerStay2D
    if (iscolliding)
    {
        // and we haven't stared our couroutines up
        if (!takingDamage)
        {
            StartCoroutine("Damager");
            StartCoroutine("DamageSFX");
            takingDamage = true; // flag on
        }
    }
    // else no collision
    // so check on OnTriggerExit2D
    else
    {
        // we're still taking damage, so stop the coroutines
        if (takingDamage)
        {
            StopCoroutine("Damager");
            StopCoroutine("DamageSFX");
            takingDamage = false; // flag off
        }
    }
}

IEnumerator Damager()
{
    while (true)
    {
        Debug.Log("Taking damage");
        yield return new WaitForSeconds(delay);
    }
}

IEnumerator DamageSFX()
{
    while (true)
    {
        //This part works perfectly fine on its own but not in this context
        Debug.Log("Play damage sound fx");
        yield return new WaitForSeconds(sounddelay);
    }
}`

好的 所以我得到的答案确实使用 字符串方法 启动协程 不喜欢 但是确实有效

感谢@RichardSoluis

    [SerializeField] float Delay;
    [SerializeField] float SoundDelay;
    private bool IsTakingDamage = false;

void OnTriggerStay2D(Collider2D collision)
    {
        if (collision.CompareTag("Damage") && !IsTakingDamage)
        {
            StartCoroutine("Damager");
            StartCoroutine("DamageSFX");

            IsTakingDamage = true;
        }
    }

    void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.CompareTag("Damage") && IsTakingDamage == true)
        {
            StopCoroutine("Damager");
            StopCoroutine("DamageSFX");

            IsTakingDamage = false;
        }
    }

    IEnumerator Damager()
    {
        while (true)
        {
            curruntHealth--;

            yield return new WaitForSeconds(Delay);
        }
    }

    IEnumerator DamageSFX()
    {
        while (true)
        {
            FindObjectOfType<AudioManager>().Play("Damage SFX");

            yield return new WaitForSeconds(SoundDelay);
        }
    }