如何让Bool触发的对话系统仅执行一次?解决每帧重复问题
解决对话系统每帧重复执行的问题
问题根源:
FixedUpdate会按固定时间间隔重复执行,只要stopPlayer.frozen为true,就会不断调用DisplayDialogue,每次调用都会启动新的协程,导致对话重复播放。解决方案:添加一个布尔变量标记对话是否正在进行,只有当对话未在进行时才启动协程,避免重复触发。
修改后的完整代码:
[SerializeField] public TMP_Text dialogueText; [SerializeField] public GameObject dialogueBox; public stopPlayer stopPlayer; public GameObject player; public DialogueObject currentDialogue; // 标记对话是否正在进行 private bool isDialogueActive; void Start() { stopPlayer = player.GetComponent<stopPlayer>(); dialogueBox.SetActive(false); isDialogueActive = false; } void FixedUpdate() { // 仅当玩家被冻结且对话未激活时,启动对话 if(stopPlayer.frozen && !isDialogueActive) { dialogueBox.SetActive(true); DisplayDialogue(currentDialogue); } // 当冻结状态解除时,关闭对话框并重置对话状态 else if(!stopPlayer.frozen && isDialogueActive) { dialogueBox.SetActive(false); isDialogueActive = false; StopAllCoroutines(); } } private IEnumerator MoveThroughDialogue(DialogueObject dialogueObject) { isDialogueActive = true; for(int i = 0; i < dialogueObject.dialogueLines.Length; i++) { dialogueText.text = dialogueObject.dialogueLines[i].dialogue; // 等待用户点击左键切换对话 yield return new WaitUntil(()=>Input.GetMouseButtonDown(0)); // 等待一帧避免跳过下一次点击检测 yield return null; } // 对话结束后关闭对话框,重置状态 dialogueBox.SetActive(false); isDialogueActive = false; // 可选:解除玩家冻结状态,恢复控制 // stopPlayer.frozen = false; } public void DisplayDialogue(DialogueObject dialogueObject) { // 仅当对话未进行时启动协程 if(!isDialogueActive) { StartCoroutine(MoveThroughDialogue(dialogueObject)); } }
- 关键调整说明:
isDialogueActive变量确保同一时间只有一个对话协程运行,彻底避免重复调用。FixedUpdate中增加双重判断,仅在符合条件时触发对话,同时处理冻结状态解除后的清理逻辑。- 协程结束后自动重置状态并关闭对话框,修正了原代码中对话结束后仍保持对话框激活的问题。
内容的提问来源于stack exchange,提问作者Fish_Fish013
相关产品推荐
相关产品推荐

