【发布时间】:2021-07-13 04:12:33
【问题描述】:
我认为协程有一些基本的东西我不理解,因为我无法理解为什么会发生这种情况。
我有这个协程,第一次按预期完美运行,但第二次尝试使用它时完全失败。
public IEnumerator CharacterDialogue()
{
inDialogue = true;
playerController.enabled = false;
mouselook.enabled = false;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
dialogueMenu.SetActive(true);
yield return new WaitForEndOfFrame();
for (int i = 0; i < dialogueStrings.Length; i++)
{
while (!Input.GetKeyDown("e"))
{
yield return null;
}
yield return new WaitForEndOfFrame();
dialogueText.text = dialogueStrings[i];
}
yield return new WaitForEndOfFrame();
while (!Input.GetKeyDown("e"))
{
yield return null;
}
yield return new WaitForEndOfFrame();
QuestManager.Instance.SpawnDouxland();
inDialogue = false;
playerController.enabled = true;
mouselook.enabled = true;
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
dialogueMenu.SetActive(false);
}
这很简单:我禁用播放器的控件并弹出对话窗口。然后我等待玩家在每个文本字符串之间输入,以便他可以按照自己的节奏阅读。他读完后,我重新激活控件并关闭对话窗口。
此代码的工作方式与我第一次完全一样,但第二次它只是通过 for 循环而不等待输入。
我在这里做错了什么,为什么它第一次起作用?
编辑:
评论指出问题一定出在我调用协程的方式上。现在这对我来说很有意义,因为我使用相同的键 (e) 来调用协程。所以也许它会在按下时读取键并运行 for 循环。但是为什么它只会第二次这样做呢?
这是我调用协程的代码的 sn-p:
if (hit.collider.CompareTag("Character"))
{
raycastedObj = hit.collider.gameObject;
CrosshairActive();
interactionManager.InteractiveFeedbackTextCall("CharacterQuest");
if (Input.GetKeyDown("e"))
{
Debug.Log("I have interacted with: " + hit.collider.gameObject.name + ".");
StartCoroutine(canvasAnimManager.CharacterDialogue());
}
}
【问题讨论】:
-
协程不会无限循环。代码本身看起来不错,它可能与您第二次调用它的方式或位置有关。我不得不说将输入检测放在非更新函数中虽然会变得很不稳定。相反,我会将 Input 放入 Update 中,然后在按下键时有一个 bool 会发生变化。然后在 IEnumerator 内部,一旦你设置了 bool,而不是 while(!Input) 执行 while(!keyNotHeldDown)。
-
@TEEBQNE 实际上我认为检查协程中的输入没有问题。在我看来,这比必须将值存储在类字段中并从那里轮询检查要干净得多……但是,是的,请向我们展示您如何准确地调用此例程
-
@derHugo 感谢您的回答并指出问题可能不在协程本身!我用调用协程的代码 sn-p 更新了问题。
标签: c# for-loop unity3d coroutine