Unity对话任务脚本tasks[0]==3逻辑失效,对话循环问题求助
问题:任务状态
tasks[0] == 3逻辑失效导致对话循环 我正在为Unity游戏编写对话与任务控制脚本,核心逻辑如下:
- 任务列表
tasks的变量值控制对话内容:0=未接受,1=已接受,2=已完成,3=已向NPC汇报完成 - 玩家触发NPC碰撞体时显示对话界面,提供两个按钮:关闭对话/推进流程
- 当前问题:
tasks[0] == 3的逻辑完全不生效,对话陷入循环,尝试调整逻辑位置无果
相关C#代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class Dialogue : MonoBehaviour { [SerializeField] GameObject dialogue; [SerializeField] Text npcText; [SerializeField] List<Text> buttonText = new List<Text>(); public DialogueBlock[] dialogueBlock; [SerializeField] public PlayerController playerController; int dialogueBlockPlace = 0; public List<int> tasks = new List<int>(); [SerializeField] List<string> taskString = new List<string>(); public void OnTriggerEnter(Collider other) { if(other.tag == "Player") { dialogue.SetActive(true); dialogueBlockPlace = 0; Answer(0); } } public void OnTriggerExit(Collider other) { if(other.tag == "Player") { dialogue.SetActive(false); } } private void Answer(int num) { npcText.text = dialogueBlock[num].npcText; buttonText[0].text = dialogueBlock[num].playerAnswer[0].Text; buttonText[1].text = dialogueBlock[num].playerAnswer[1].Text; } public void AnswerButtonClicked(int buttonNum)//u=mesti ant mygtuko { if(dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].speakEnd) { dialogue.SetActive(false); } dialogueBlockPlace = dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].toBlock; TaskStarted(); if (dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].questInt == 1) { if (tasks[0] == 0) { tasks[0] = 1; } else if (tasks[0] > 2) { tasks[1] = 1; } else if (tasks[1] > 2 ) { tasks[2] = 1; } } DialogueControl(); } public void DialogueControl() { TaskDone(); ChangeText(); print(dialogueBlockPlace); Answer(dialogueBlockPlace); } private void TaskStarted() { if (tasks[0] == 1 || tasks[1] == 1 || tasks[2] == 1) { dialogueBlockPlace = 4; } } private void TaskDone() { if (tasks[0] == 2 || tasks[1] == 2 || tasks[2] == 2) { dialogueBlockPlace = 3; tasks[0] = 3;//dont work } } public void ChangeText() { if (tasks[0]==0) { dialogueBlock[2].npcText = taskString[0]; } if (tasks[0] == 3) { dialogueBlock[2].npcText = taskString[1]; } if (tasks[1] == 3) { dialogueBlock[2].npcText = taskString[2]; } } } [System.Serializable] public class DialogueBlock { public string npcText; public PlayerAnswer[] playerAnswer; } [System.Serializable] public class PlayerAnswer { public string Text; public int toBlock; public bool speakEnd; public int questInt; }
问题根源分析
- TaskDone方法逻辑混乱:只要任意任务处于完成状态(值为2),就强制将
tasks[0]设为3,且固定跳转到对话块3,完全混淆了不同任务的状态,导致tasks[0]被错误覆盖。 - OnTriggerEnter强制重置对话位置:每次触发碰撞都把
dialogueBlockPlace设为0,完全忽略当前任务状态,即使tasks[0]已经是3,也会回到初始对话,无法进入对应分支。 - ChangeText条件无优先级:三个if并列执行,若多个任务状态满足条件,后面的赋值会覆盖前面的,导致对话文本不符合预期。
- AnswerButtonClicked流程顺序错误:先修改对话块位置再调用
TaskStarted,会强制跳转到对话块4,打断原本的对话流程。
修复方案
1. 修正TaskDone方法,区分不同任务的完成状态
private void TaskDone() { // 任务0完成后标记为已汇报 if (tasks[0] == 2) { dialogueBlockPlace = 3; tasks[0] = 3; } // 任务1完成后标记为已汇报(对话块编号根据你的配置调整) else if (tasks[1] == 2) { dialogueBlockPlace = 5; tasks[1] = 3; } // 任务2完成后标记为已汇报 else if (tasks[2] == 2) { dialogueBlockPlace = 6; tasks[2] = 3; } }
2. 修改OnTriggerEnter,根据任务状态初始化对话位置
public void OnTriggerEnter(Collider other) { if(other.tag == "Player") { dialogue.SetActive(true); // 根据任务状态动态设置初始对话块 if (tasks[0] == 3) { dialogueBlockPlace = 2; // 对应任务0已汇报的对话块 } else if (tasks[0] == 2) { dialogueBlockPlace = 3; // 对应任务0完成后汇报的对话块 } else if (tasks[0] == 1) { dialogueBlockPlace = 4; // 对应任务0已接受的对话块 } else { dialogueBlockPlace = 0; // 初始对话 } Answer(dialogueBlockPlace); } }
3. 调整ChangeText的条件为else if,保证优先级
public void ChangeText() { if (tasks[0] == 0) { dialogueBlock[2].npcText = taskString[0]; } else if (tasks[0] == 3) { dialogueBlock[2].npcText = taskString[1]; } else if (tasks[1] == 3) { dialogueBlock[2].npcText = taskString[2]; } }
4. 调整AnswerButtonClicked的流程顺序
public void AnswerButtonClicked(int buttonNum) { int targetBlock = dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].toBlock; // 先处理任务接受逻辑 if (dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].questInt == 1) { if (tasks[0] == 0) { tasks[0] = 1; } else if (tasks[0] > 2) { tasks[1] = 1; } else if (tasks[1] > 2 ) { tasks[2] = 1; } } // 处理任务状态相关的对话跳转 DialogueControl(); // 若任务逻辑未修改对话块位置,则使用原本的目标块 if (dialogueBlockPlace == dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].toBlock) { dialogueBlockPlace = targetBlock; } // 处理关闭对话 if(dialogueBlock[dialogueBlockPlace].playerAnswer[buttonNum].speakEnd) { dialogue.SetActive(false); } Answer(dialogueBlockPlace); }
5. 优化TaskStarted方法,避免打断正常流程
private void TaskStarted() { // 仅在当前对话块不是任务汇报相关时,跳转到任务进行中的对话 if ((tasks[0] == 1 || tasks[1] == 1 || tasks[2] == 1) && dialogueBlockPlace != 3 && dialogueBlockPlace != 5 && dialogueBlockPlace != 6) { dialogueBlockPlace = 4; } }
内容的提问来源于stack exchange,提问作者user21495296
相关产品推荐
相关产品推荐

