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

Unity中yield return new WaitForSeconds不等待问题求助

问题:WaitForSeconds在对话流程中部分步骤失效

问题概述

使用WaitForSeconds创建延迟事件切换对话步骤推进剧情,部分场景正常,部分场景失效。首次执行符合预期,但后续连续4个步骤会直接跳过延迟进入下一步,之后延迟功能才恢复正常并结束流程。

代码片段

float waitTime = currentStep.isSpoken ? currentStep.dialogueClip.length + 1.0f : 2.0f;

selectedText = null;

if(currentStep.speaker.ToString() != "Gui"){
    StartCoroutine( ProgessStep(waitTime) );
}

IEnumerator ProgessStep(float waitTime) {
    if(currentStep.stepName.Equals("S1-P1-1")) {
        yield break;
    }
    else if(currentStep.stepName.Equals("S2-P1-5-8")) {
        if(levelManager.fireAlarmTested) {
            SetStep("S2-P1-5-10"); 
            yield break;
        }
        else {
            levelManager.fireAlarmTested = true;
        }
    }

    if(currentStep.nextStep.Equals("")) 
        yield break;
    
    Debug.Log($"Waiting for {waitTime}s before moving to {currentStep.nextStep}");
    yield return new WaitForSeconds(waitTime);
    Debug.Log($"Moving to {currentStep.nextStep}");
    
    if(!currentStep.canRespond) 
        SetStep(currentStep.nextStep);
}

预期结果

执行完前置检查后,等待音频片段(若存在)播放完毕再进入下一个对话步骤。

实际结果

首次执行延迟正常,后续连续4个步骤直接跳过WaitForSeconds进入下一步,之后延迟功能恢复正常并结束流程。

已尝试方案

  • 使用Invoke和WaitForSecondsRealtime测试:Invoke问题更严重,WaitForSecondsRealtime无改善
  • 为waitTime设置固定默认值
  • 添加try/catch块,未捕获到异常
  • 使用Mathf.Ceil或CeilToInt处理waitTime的小数位

排查与解决建议

  1. 阻止协程重复启动
    大概率是切换步骤时重复启动了协程,多个协程并行执行导致后续步骤的延迟被覆盖。给协程加个全局引用,启动前先停止之前的:

    private Coroutine _currentProgressCoroutine;
    
    // 替换原启动协程的代码
    if(currentStep.speaker.ToString() != "Gui"){
        if(_currentProgressCoroutine != null) StopCoroutine(_currentProgressCoroutine);
        _currentProgressCoroutine = StartCoroutine(ProgessStep(waitTime));
    }
    
  2. 缓存步骤参数避免被修改
    协程挂起期间,currentStep可能被其他逻辑提前修改,导致后续操作指向了新步骤。在协程开头就缓存关键参数:

    IEnumerator ProgessStep(float waitTime) {
        // 缓存当前步骤的目标下一步和自动推进标记
        string targetNextStep = currentStep.nextStep;
        bool shouldAutoProceed = !currentStep.canRespond;
    
        // 原有检查逻辑保留...
    
        if(targetNextStep.Equals("")) 
            yield break;
        
        Debug.Log($"Waiting for {waitTime}s before moving to {targetNextStep}");
        yield return new WaitForSeconds(waitTime);
        Debug.Log($"Moving to {targetNextStep}");
        
        if(shouldAutoProceed) 
            SetStep(targetNextStep);
    }
    
  3. 检查时间缩放异常
    虽然试过WaitForSecondsRealtime,但还是要确认是否有逻辑修改了Time.timeScale。在日志里加上时间缩放的输出,确认数值是否正常:

    Debug.Log($"Waiting for {waitTime}s (timeScale: {Time.timeScale}) before moving to {targetNextStep}");
    
  4. 追踪步骤切换时机
    在SetStep方法里添加日志,输出当前切换的步骤名称和调用栈,看看是否有逻辑在延迟结束前就强制切换了步骤。


内容的提问来源于stack exchange,提问作者Aidan H M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:02:54