【问题标题】:C# - Loop executes code on all members of array at once instead of iterating through one at a timeC# - 循环一次在数组的所有成员上执行代码,而不是一次迭代一个
【发布时间】:2021-11-22 22:06:30
【问题描述】:

我正在 Unity 中制作一个小型拳击游戏。我设计了一个函数(attackOverdrive)来接受一大堆参数,然后让敌方拳击手根据输入函数的数据进行攻击。我有另一个类,它设置了一堆变量,然后我读取这些值,将它们分配给局部变量,然后运行我的函数。问题是我循环中的代码是在数组的所有成员上执行的,而不是一次迭代一个,导致敌人一次抛出许多本应按顺序抛出的攻击。 pushDelayTimer 应该计数到一个限制,然后发送消息以实例化攻击,然后循环返回并再次执行。

我快疯了,尝试了所有不同类型的迭代器,但一无所获。我是 C# 新手,不知道我在这里做错了什么。在其他脚本中设置变量的函数位于代码块的底部。

using UnityEngine;
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, punchDelayTimer, patternDelayTimer;
    private Vector2[] theCoords;

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

    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();
        attackOverdrive(thePatterns, thePunchDelay, thePatternDelay, theCoords);
    }

    public void 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")
            {
                int j = 0;
                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)};
                do
                {
                    if (punchDelayTimer <= punchDelay)
                    {
                        punchDelayTimer += Time.deltaTime; //Debug statement here for i and j both print 0
                    }
                    else
                    {
                        enemyBoxer.SendMessage("createAttack", triangleVectors[j]);
                        punchDelayTimer = 0;  //Debug statement here outputs 9 statements for the value of i: 0,0,0,1,1,1,2,2,2
                        j += 1; //Debug statement here outputs 9 statements for the value of j: 0,1,2,0,1,2,0,1,2
                    }
                } while (j < 3);
            }
            else if (patterns[i] == "square")
            {
                
            }
            else if (patterns[i] == "circle")
            {
                
            }
            else if ("verticalLine".CompareTo(patterns[i]) == -1)
            {
               
                var result = Regex.Match(patterns[i], @"\d+$", RegexOptions.RightToLeft);
                if (result.Success) 
                { 
                    //Debug.Log(result.Value);
                } 
            }
        }
    }
}


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

【问题讨论】:

  • 您是否尝试过添加一些日志记录?在每个循环中,punchDelayTimer、punhcDelay 和 Time.deltaTime 的值是多少?
  • punchDelay 设置为 0.5,计时器正确计数。一旦超过 0.5,else 子句中的所有代码都会在数组的所有成员上执行,而不仅仅是在 patterns[i] 上执行。
  • 此外,我放在 else 子句中的任何日志语句都将执行 9 次(3 个三角形中的每一个执行 3 次)——所有时间都同时加上时间戳。
  • 您在循环中的哪个位置执行“延迟”。 IE。你怎么等?我唯一能看到的是 punchDelayTimer 的值正在增加。
  • if 子句-punchDelayTimer += Time.deltaTime; - 随着时间的推移增加计时器。一旦它达到了punchDelay设置的限制,它应该运行else子句,然后将punchDelayTimer重置为0,以便它可以再次运行。它可以完成所有这些事情,但一次执行 9 次,而不是一次执行一次。

标签: c# loops iteration


【解决方案1】:

原来浮动计时器是问题所在。它正确地遍历了数组,但是这一切都发生在同一帧上。我能够通过将attackOverdrive 的返回类型更改为IEnumerator 并从OnSwitch 将其作为协程调用来解决该问题。我删除了循环三角形部分内的 if 语句,并用 Unity 的 WaitForSeconds 类替换了浮点计时器。以下是更改的功能以防万一有人感兴趣:

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

    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")
            {
                int j = 0;
                Vector2[] triangleVectors = new Vector2[] {new Vector2(coords[i].x, coords[i].y + 0.5f), new Vector2(coords[i].x - 0.5f, coords[i].y - 0.5f), new Vector2(coords[i].x + 0.5f, coords[i].y - 0.5f)};
                do
                {
                    enemyBoxer.SendMessage("createAttack", triangleVectors[j]);
                    yield return new WaitForSeconds(punchDelay);
                    punchDelayTimer = 0f;
                    j += 1;
                } while (j < 3);
            }
            else if (patterns[i] == "square")
            {
                
            }
            else if (patterns[i] == "circle")
            {
                
            }
            else if ("verticalLine".CompareTo(patterns[i]) == -1)
            {
               
                var result = Regex.Match(patterns[i], @"\d+$", RegexOptions.RightToLeft);
                if (result.Success) 
                { 
                    Debug.Log(result.Value);
                } 
            }
            else if ("single".CompareTo(patterns[i]) == -1)
            {
               
                var result = Regex.Match(patterns[i], @"\d+$", RegexOptions.RightToLeft);
                if (result.Success) 
                { 
                    Debug.Log(result.Value);
                } 
            }
        }
    }

感谢 Unity 论坛上的 rage_co,他们向我展示了此修复程序 =]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 2020-07-02
    • 2019-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多