如何从 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);
}
}
我对编程还很陌生,所以很乐意提供帮助。
这在 理论 中应该有效,但由于某种原因,当我 运行 在 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);
}
}