当我在 Unity 游戏中的对话之间切换得太快时,会出现奇怪的角色

When I change too fast between dialogues in my Unity game, weird characters appear

我对编码相当陌生(过去 4 个月一直在学习),我一直在 Unity 中使用类似 RPG 的对话系统制作 2D 点和点击游戏,对话适用于大部分除了一件事:每当我从一个对象的对话转到另一个对象的对话时,如果我在它们之间切换得太快,就会开始出现奇怪的字符并且文本被屠杀。

这是我的意思的一个例子:https://media.giphy.com/media/4QsoxLSInXN0vKciaW/giphy.gif。 .文本是西班牙文的,但我认为任何人都可以看到文本在哪里表现得不像它应该的那样(随机出现符号和字母的奇怪组合)。我第一次打开两个对话(第一个对话在抽屉对象中,第二个对话在 lamp 对象中)它们都很好,但是第二次,我在 lamp 对象中打开了对话太快了,让文字看起来很奇怪。

我的代码的对话系统基于 YouTube 频道 Brackeys 中显示的对话系统:https://www.youtube.com/watch?v=_nRzoTzeyxU。我修改了这个脚本,以便它可以适应我的游戏,但主要是为了我可以用 UI 按钮触发对话并添加一个关闭按钮(这就是为什么某些 public 变量看起来不需要,但我在其他 UI 按钮中使用了它们。

主要代码如下:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;
 
 public class DialogueManager : MonoBehaviour
 {
 
     public Text nameText;
     public Text dialogueText;
     public GameObject gameObject;
     public float delay = 0.5f;
     public PlayerController playerController;
     public Toggle myToggle;
     public GameObject endObject;
 
     private Queue<string> sentences;
 
     // Start is called before the first frame update
     void Start()
     {
         sentences = new Queue<string>();
         
     }
 
     public void StartDialogue(Dialogue dialogue){
 
         playerController.enabled = false;
         nameText.text = dialogue.name;
 
         sentences.Clear();
 
         foreach(string sentence in dialogue.sentences){
             sentences.Enqueue(sentence);
         }
 
         DisplayNextSentence();
     }
 
     public void DisplayNextSentence(){
         if(sentences.Count == 0){
             EndDialogue();
             return;
         }
 
         string sentence = sentences.Dequeue();
         StopAllCoroutines();
         StartCoroutine(TypeSentence(sentence));
     }
 
     IEnumerator TypeSentence(string sentence){
         dialogueText.text = "";
         foreach(char letter in sentence.ToCharArray()){
             dialogueText.text += letter;
             yield return new WaitForSeconds(delay);
         }
     }
 
     void EndDialogue(){
         myToggle.isOn = false;
         endObject.SetActive(false);
         playerController.enabled = true;
         gameObject.SetActive(false);
     }
 
 }

它使用 public class,其中包含名为“对话”的对话:

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 using UnityEngine.UI;
 
 [System.Serializable]
 public class Dialogue
 {
     public string name;
     
     [TextArea(3, 10)]
     public string[] sentences;
 }

它还使用了一个通过按钮调用的触发器函数。

 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class DialogueTrigger : MonoBehaviour
 {
     public Dialogue dialogue;
     public DialogueManager dialogueManager;
 
     public void TriggerDialogue(){
         dialogueManager.StartDialogue(dialogue);
     }
 }

如果我没有很好地解释自己,我真的很抱歉,就像我说的,我是新手并且还在学习,所以如果你不明白我在问什么或者你想要我澄清一些事情就问我,这样我们就可以更好地理解彼此。在此先感谢任何愿意提供帮助的人! :)

StopCoroutine 相当不可靠,你可以做一个布尔检查,看看对话是否是 运行 例如 private bool DialogueRunning 并在

中将其设置为 true
IEnumerator TypeSentence(string sentence){
     dialogueText.text = "";
      DialogueRunning = true;
     foreach(char letter in sentence.ToCharArray()){
         dialogueText.text += letter;
         yield return new WaitForSeconds(delay);
     }
      DialogueRunning = false;
 }

然后,当您尝试 EndDialogue() 时,首先检查对话是否完成,如果没有,return。否则,您可以将 delay 设置为 0 以立即输入文本,然后结束对话。这将确保协程不会被多次调用。

void EndDialogue(){
if (DialogueRunning) return;

     myToggle.isOn = false;
     endObject.SetActive(false);
     playerController.enabled = true;
     gameObject.SetActive(false);
 }

问题是您有多个对象访问您的 text box,但只有一个文本框用于传递值。当一个协程启动而另一个未完成时,[=15] =] 将值传递给文本框,你会得到这些乱七八糟的乱码而不是句子。

否则你也可以使用 async 来等待任务完成,这使得它比协程更干净