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

Posted

技术标签:

【中文标题】如何从 OnTriggerStay 协程中启动和停止其他协程【英文标题】:How to start and stop other coroutines from a OnTriggerStay coroutine 【发布时间】:2021-10-24 00:42:50 【问题描述】:

我对编程很陌生,所以我很喜欢任何帮助。

这在 theory 中应该可以工作,但由于某种原因,当我在 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);
        
    

【问题讨论】:

为什么要重新启动例程每个 FixedUpdate 调用? 最后的yield return new WaitForEndOfFrame();也没什么用;) @derHugo lel good one...如果我不知道更好的话,我的电脑会崩溃 那么 .. 随心所欲 ... 我只能告诉你的是,它在你拥有它的地方绝对不会做任何事情 ... 没有无限循环可能会冻结你的应用程序,并且可以肯定它不会“让你的电脑崩溃”^^ 如果你这么信任这个页面上的人,那么为什么还要在这里问呢? ^^ @derHugo 啊等等,我明白你的意思了,对不起,我以为你在谈论不同的东西 【参考方案1】:

你已经接近了,但这里有几件事要看看。

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

中连接 Stop

第二 - 当您使用我相信您必须参考的方法启动一个 couroutine 时,您必须停止它。如果您改用字符串,它会更容易停止。 example of ref to couroutine and string calls

这里有一个示例,可以满足您的需要。代替 OnTriggerStay,我只使用了一个可以在检查器中切换的公共 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);
    
`

【讨论】:

非常感谢!我最终使用了我不喜欢的字符串方法。但是,它有效,现在我只关心 lel。【参考方案2】:

好的 所以我得到的答案确实使用 string 方法启动协程 不喜欢它确实有效

感谢@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);
        
    

【讨论】:

以上是关于如何从 OnTriggerStay 协程中启动和停止其他协程的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Kotlin 协程中使用 Sqldelight

如何在协程中发出 GET 请求?

Kotlin 协程协程中的多路复用技术 ① ( 多路复用技术 | await 协程多路复用 | Channel 通道多路复用 )

如何在协程中发出GET请求?

协程中的流

协程中的流