You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

问题根源分析

  1. TaskDone方法逻辑混乱:只要任意任务处于完成状态(值为2),就强制将tasks[0]设为3,且固定跳转到对话块3,完全混淆了不同任务的状态,导致tasks[0]被错误覆盖。
  2. OnTriggerEnter强制重置对话位置:每次触发碰撞都把dialogueBlockPlace设为0,完全忽略当前任务状态,即使tasks[0]已经是3,也会回到初始对话,无法进入对应分支。
  3. ChangeText条件无优先级:三个if并列执行,若多个任务状态满足条件,后面的赋值会覆盖前面的,导致对话文本不符合预期。
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 20:57:02