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

Unity C#循环一次性执行全部数组成员代码而非逐次迭代问题排查

问题解决方法

根因分析

你遇到的问题是同步函数无法实现跨帧延迟逻辑:
Unity的普通C#方法会在单帧内执行完全部代码逻辑,你在循环中累加Time.deltaTime的写法没有预期效果:

  • 同一帧内Time.deltaTime为固定值,内层do while循环会在单帧内反复执行,快速把计时器累加到阈值,瞬间生成3次三角攻击
  • 外层for循环也会在同一帧遍历完所有pattern数组元素,导致所有批次的攻击同时触发,没有间隔

解决方案

将attackOverdrive改为Unity协程(Coroutine),通过yield return实现等待延迟,自动跨帧执行逻辑,不需要自己维护计时器。
修改后的完整代码如下:

using UnityEngine;
using System.Collections;
using System.Text.RegularExpressions;

public class overdrivePiano : MonoBehaviour
{
    private GameObject enemyBoxer;
    private pianoRoll theRoll;
    private string theCoordMod;
    private string[] thePatterns;
    private int howMany;
    private float thePunchDelay, thePatternDelay, theCoordModAmount, patternDelayTimer;
    private Vector2[] theCoords;

    void Start()
    {
        enemyBoxer= GameObject.Find("enemyBoxer");
        theRoll = gameObject.GetComponent<pianoRoll>();
    }

    private void readRoll()
    {
        thePatterns = theRoll.patterns;
        thePunchDelay = theRoll.punchDelay;
        thePatternDelay = theRoll.patternDelay;
        theCoords = theRoll.coords;
        theCoordMod = theRoll.coordMod;
        theCoordModAmount = theRoll.modAmount;
    }

    public void onSwitch()
    {
        theRoll.SendMessage("firstVerse");
        readRoll();
        // 启动协程
        StartCoroutine(attackOverdrive(thePatterns, thePunchDelay, thePatternDelay, theCoords));
    }

    // 改为返回IEnumerator的协程方法
    public IEnumerator attackOverdrive(string[] patterns, float punchDelay, float patternDelay, Vector2[] coords, string coordMod = "none", float modAmount = 0)
    {
        for(int i = 0; i < patterns.Length; i++)
        {
            if (patterns[i] == "triangle")
            {
                Vector2[] triangleVectors = new Vector2[] {new Vector2(coords[i].x, coords[i].y + 0.75f), new Vector2(coords[i].x - 0.75f, coords[i].y - 0.75f), new Vector2(coords[i].x + 0.75f, coords[i].y - 0.75f)};
                for(int j = 0; j < 3; j++)
                {
                    // 等待punchDelay时间后再执行后续逻辑
                    yield return new WaitForSeconds(punchDelay);
                    enemyBoxer.SendMessage("createAttack", triangleVectors[j]);
                }
            }
            else if (patterns[i] == "square")
            {
                // 后续pattern逻辑同理,用yield return实现延迟
            }
            else if (patterns[i] == "circle")
            {
                
            }
            else if (patterns[i].StartsWith("verticalLine"))
            {
                var result = Regex.Match(patterns[i], @"\d+$", RegexOptions.RightToLeft);
                if (result.Success) 
                { 
                    //Debug.Log(result.Value);
                } 
            }
            // 不同pattern之间等待patternDelay
            yield return new WaitForSeconds(patternDelay);
        }
    }
}

// pianoRoll类中的firstVerse方法不需要修改
private void firstVerse()
{
    patterns = new string[] {"triangle", "triangle", "triangle", "singleRandom", "singleRandom", "verticalLine5"};
    coords = new Vector2[] {new Vector2(-1.3f, 2.5f), new Vector2(0f, -2.5f), new Vector2(1.3f, 2.5f), new Vector2(0,0), new Vector2(0,0), new Vector2(0, 4f)};
    punchDelay = 0.5f;
    patternDelay = 0.5f;
}

补充说明

  • 协程遇到yield return时会自动挂起,等等待时间结束后从挂起位置继续执行,完美匹配你按顺序延迟触发攻击的需求
  • 不需要再手动维护punchDelayTimer变量,WaitForSeconds会自动处理计时逻辑
  • 如果需要中途终止攻击序列,可以调用StopCoroutine()方法停止运行中的协程

内容的提问来源于stack exchange,提问作者Feudimonster

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 18:09:03