【问题标题】:My script won't work as expected, it also crashes the unity editor [duplicate]我的脚本无法按预期工作,它还会使统一编辑器崩溃 [重复]
【发布时间】:2019-04-18 15:06:59
【问题描述】:

我已经在这个项目上工作了几天,我遇到了一个似乎无法解决的错误,因为不仅没有错误消息出现,而且它还“跳过”了我的调试消息并使编辑器本身崩溃。

以下脚本是一个对话框显示器,这显然是导致问题的原因(请原谅混乱的代码,我在尝试解决问题时弄乱了它):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class DialogDisplayer : MonoBehaviour
{
    [SerializeField] Dialog[] dialogFiles;
    TextMeshPro outputTxt;

    bool next, finished;
    char comma = (char)44;
    char period = (char)46;

    // Use this for initialization
    void Start()
    {
        outputTxt = GetComponent<TextMeshPro>();
        StartCoroutine(type());
    }

    IEnumerator type()
    {
        int dialogIndex = 0;

        do
        {
            foreach (char c in dialogFiles[dialogIndex].dialogText)
            {
                if (Input.GetKeyDown(KeyCode.Z))
                {
                    outputTxt.text = dialogFiles[dialogIndex].dialogText;
                    Debug.Log("z pressed in the foreach");
                    break;
                }

                outputTxt.text += c;
                if (c == ' ')
                    continue;

                if (dialogFiles[dialogIndex].delayforPunctuations)
                {
                    if (c == comma)
                        yield return new WaitForSeconds(dialogFiles[dialogIndex].delayBetweenLetters + 0.1f);
                    else if (c == period)
                        yield return new WaitForSeconds(dialogFiles[dialogIndex].delayBetweenLetters + 0.2f);
                    else
                        yield return new WaitForSeconds(dialogFiles[dialogIndex].delayBetweenLetters);
                }
                else
                    yield return new WaitForSeconds(dialogFiles[dialogIndex].delayBetweenLetters);
            }
            Debug.Log("Either finished or broken out of the loop");

            while (!finished)
            {
                Debug.LogWarning("Entering while loop");
                if (Input.GetKeyDown(KeyCode.Z))
                {
                    Debug.Log("entered if");
                    finished = true;
                    dialogIndex++;
                }
                Debug.Log("got out");
            }

        } while (dialogIndex != dialogFiles.Length - 1);
    }
}

【问题讨论】:

  • 我不是 Unity 专家,但我认为您不想在启动协程时调用 type()(顺便说一句,方法的好名字)。我认为您将方法信息传递给它:StartCoroutine(type);

标签: c# unity3d


【解决方案1】:

您不要在Coroutine 的任何地方使用yield return。这将cause your coroutine to run all iterations in the same frame

来自Scripting documentation

// every 2 seconds perform the print()
private IEnumerator WaitAndPrint(float waitTime)
{
    while (true)
    {
        yield return new WaitForSeconds(waitTime);
        print("WaitAndPrint " + Time.time);
    }
}

或者您可以使用yield return null 将协程传递到下一帧:

private IEnumerator YourDialogCoroutine()
{
    bool finished = false;

    while (!finished)
    {
        If(Input.GetKeyDown("Z"))
        {
            Debug.Log("Ending loop!");
            finished = true;
        }

        yield return null;
    }
}

【讨论】:

  • 抱歉,我不太明白。你能说得更具体点吗?
  • 在 Coroutines 的文档中,您必须使用声明 yield returnnull 或类似 WaitForSeconds(float seconds) 的东西。在这种情况下,我会查看文档,因为您缺少此声明
  • 其实有几个yield returns...
  • 协程将处理单个帧内的所有信息 (stackoverflow.com/a/32469037/1299146)。一旦你的代码通过你的 foreach 循环,在你的 do-while 结束时就没有yield return null
  • 那么,我必须在 do while 的末尾添加一个 yield return null 吗?
【解决方案2】:

据我所见....

英文:只要 dialogIndex 不等于 dialogFiles.length 减一,您的脚本就会崩溃。

一旦这样:

while (dialogIndex != dialogFiles.Length - 1);

是真的,它进入了一个无限循环。一旦 dialogFiles.Length -1 不再等于 dialogIndex,就没有指示该做什么了。

不确定你想用那里的最后一行代码来完成什么,但计算机也不是,一旦满足这些条件,它只会等待指令......永远。

应该是

while (dialogIndex != dialogFiles.Length - 1); {
  Do Something;
  provide Action To Eventually escape this loop (make dialogIndex = dialogFiles.Length - 1)
}

至于评论的话,你可以StartCoroutine(type());或者StartCoroutine("type");就可以了。

【讨论】:

  • 最后一行代码 (while(dialogIndex != dialogFiles.Lenght - 1)) 实际上是 do while 循环的一部分。而且,在等待答案时,我还发现导致问题的代码行实际上是 while(!finished) 循环,但我仍然不知道为什么。
  • 为了清楚起见,这个脚本的目标是输入 dialogFiles[dialogIndex].dialogText 具有打字机效果,同时还可以通过按“z”来加快打字过程在键盘上,一旦输入了所有文本,再次按“z”会导致 dialogIndex 增加 1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
  • 2023-03-20
  • 2015-06-26
  • 2020-04-23
  • 2013-07-27
相关资源
最近更新 更多