在重构具有多个yield的IEnumerator方法时遇到麻烦
本文关键字:方法 IEnumerator 遇到 麻烦 yield 重构 | 更新日期: 2023-09-27 18:03:23
我的代码要点如下:
// Play the first beat
audio.PlayOneShot(beat);
// Show 1st heartbeat border flash
TweenAlpha.Begin(heartbeatPanel.gameObject, 0.1f, currentStress);
yield return new WaitForSeconds(0.1f);
TweenAlpha.Begin(heartbeatPanel.gameObject, 0.5f, 0);
yield return new WaitForSeconds(interval);
// Play the second beat
audio.PlayOneShot(beat);
// Show 2nd heartbeat border flash
TweenAlpha.Begin(heartbeatPanel.gameObject, 0.1f, currentStress);
yield return new WaitForSeconds(0.1f);
TweenAlpha.Begin(heartbeatPanel.gameObject, 0.5f, 0);
yield return new WaitForSeconds(interval * 2);
现在我想把上面的代码分成一个IEnumerator方法,有两个调用。
这是我想到的:
StartCoroutine(PlayBeat(currentStress, interval));
StartCoroutine(PlayBeat(currentStress, interval * 2));
// ...
IEnumerator PlayBeat(float currentStress, float interval)
{
audio.PlayOneShot(beat);
TweenAlpha.Begin(heartbeatPanel.gameObject, 0.1f, currentStress);
yield return new WaitForSeconds(0.1f);
TweenAlpha.Begin(heartbeatPanel.gameObject, 0.5f, 0);
yield return new WaitForSeconds(interval);
}
这样做的问题是,这两个节拍并没有以正确的间隔发出声音,而是同时发出声音,因为我在无限循环中调用这些声音,Unity崩溃了,因为没有考虑到间隔。
将上面两个重复的代码块提取到单个IEnumerator方法中的最佳方法是什么?
Unity3d的协程可以嵌套。要等待嵌套协程,您需要生成它。所以函数PlayBeat
没问题;你只需要以一种unity3d理解为"等待完成"的方式开始它。您的示例将如下所示:
yield return StartCoroutine(PlayBeat(currentStress, interval));
yield return StartCoroutine(PlayBeat(currentStress, interval * 2));
这看起来和c# 5的async/await非常相似。在某种程度上,这并不奇怪,因为它们都是编译器转换的"协程"状态机,但看到它们的相似性仍然很简洁。