【问题标题】:Coroutine only works the first time协程只在第一次工作
【发布时间】: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


【解决方案1】:

感谢一些 cmets,我弄清楚了问题所在。

if (Input.GetKeyDown("e"))
        {
            Debug.Log("I have interacted with: " + hit.collider.gameObject.name + ".");
            StartCoroutine(canvasAnimManager.CharacterDialogue());
        }

我认为 GetKeyDown 的想法是它只被触发一次......一定有一些我没有得到的东西。无论如何,问题是这被多次调用,即使在我完成对话后,它也会让协程通过循环。

我刚刚添加了一个小布尔检查来解决这个问题:

            if (Input.GetKeyDown("e") && !canvasAnimManager.inDialogue)
            {
                Debug.Log("I have interacted with: " + hit.collider.gameObject.name + ".");
                StartCoroutine(canvasAnimManager.FoukiDialogue());
            }

干杯并感谢您的帮助!

【讨论】:

    猜你喜欢
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-08
    • 2021-04-21
    相关资源
    最近更新 更多