当我在 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 来等待任务完成,这使得它比协程更干净
我对编码相当陌生(过去 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
并在
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 来等待任务完成,这使得它比协程更干净