C# 我想这样做,以便在波浪完成后加载下一个场景,但出于某种原因,我可以';I don’我想不出如何防止这种情况早日发生

C# 我想这样做,以便在波浪完成后加载下一个场景,但出于某种原因,我可以';I don’我想不出如何防止这种情况早日发生,c#,unity3d,C#,Unity3d,在游戏的第二关,我用3种不同类型的僵尸制作了一个波浪系统。这个波浪系统产生三种不同的波浪。我的问题是,我想不出一种方法来开始下一个场景,因为无论我尝试什么,它都会在1波之内开始下一个场景。我曾尝试使用bools来检查波是否已经运行,但问题是我必须有一个真的,否则第二个和第三个波一起生成。我试着把它放在第三波的产卵器里,但没有成功。我尝试添加zklef.Length==0,但没有成功。你知道有什么可能的方法可以防止下一个场景提前开始而不提前开始一个波浪吗?谢谢 对不起,如果代码不正确,我是一名学生

在游戏的第二关,我用3种不同类型的僵尸制作了一个波浪系统。这个波浪系统产生三种不同的波浪。我的问题是,我想不出一种方法来开始下一个场景,因为无论我尝试什么,它都会在1波之内开始下一个场景。我曾尝试使用bools来检查波是否已经运行,但问题是我必须有一个真的,否则第二个和第三个波一起生成。我试着把它放在第三波的产卵器里,但没有成功。我尝试添加
zklef.Length==0
,但没有成功。你知道有什么可能的方法可以防止下一个场景提前开始而不提前开始一个波浪吗?谢谢

对不起,如果代码不正确,我是一名学生

using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEngine;


public class Waves : Zombie
{    
    public GameObject behemoth;    
    public GameObject runner;    
    public GameObject zombie;    

    private bool HasSecondWaveRan = false;
    private bool HasThirdWaveRan = true;

    private int xPos;

    public GameObject[] ZKleft;

    // Start is called before the first frame update
    private void Start()
    {
        ZKleft = GameObject.FindGameObjectsWithTag("Zombie");

        for (int i = 0; i < 10; i++)
        {
            xPos = Random.Range(31, -14);            
            Instantiate(zombie, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            
        }

        for (int i = 0; i < 3; i++)
        {
            xPos = Random.Range(31, -14);            
            Instantiate(runner, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            
        }
        
    }

    // Update is called once per frame
    private void Update()
    {
        ZKleft = GameObject.FindGameObjectsWithTag("Zombie");        

        if (ZKleft.Length == 0)
        {
            StartCoroutine(SecondWave());
            HasSecondWaveRan = true;
        }

        if (ZKleft.Length == 0)
        {
            StartCoroutine(ThirdWave());
            HasThirdWaveRan = true;
        }

        if (HasThirdWaveRan == true && HasSecondWaveRan == true)
        {
            SceneManager.LoadScene("Level_2_Completed"); 
        }
    }

    IEnumerator SecondWave()
    {
        if (HasSecondWaveRan == false)
        {
            
            yield return new WaitForSeconds(5.0f);

            for (int i = 0; i < 5; i++)
            {
                xPos = Random.Range(31, -14);
                Instantiate(runner, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            }

            for (int i = 0; i < 20; i++)
            {
                xPos = Random.Range(31, -14);
                Instantiate(zombie, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            }

            HasThirdWaveRan = false;
            HasSecondWaveRan = true;            
        }
    }

    IEnumerator ThirdWave()
    {
        if (HasThirdWaveRan == false)
        {
            yield return new WaitForSeconds(5.0f);

            for (int i = 0; i < 5; i++)
            {
                xPos = Random.Range(31, -14);
                Instantiate(runner, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            }

            for (int i = 0; i < 20; i++)
            {
                xPos = Random.Range(31, -14);
                Instantiate(zombie, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            }

            for (int i = 0; i < 3; i++)
            {
                xPos = Random.Range(31, -14);
                Instantiate(behemoth, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
            }

            HasThirdWaveRan = true;
            
        }
    }
    
}

使用系统集合;
使用System.Collections.Generic;
使用UnityEngine.SceneManagement;
使用UnityEngine;
公共类浪潮:僵尸
{    
公共游戏对象庞然大物;
公共游戏机;
公共游戏对象僵尸;
private bool hassencodwaveran=false;
private bool HasThirdWaveRan=true;
私人int XPO;
公共游戏对象[]左;
//在第一帧更新之前调用Start
私有void Start()
{
zkleet=GameObject.FindGameObjectsWithTag(“僵尸”);
对于(int i=0;i<10;i++)
{
xPos=随机范围(31,-14);
实例化(僵尸,新矢量3(xPos,0.4f,6),四元数.identity);
}
对于(int i=0;i<3;i++)
{
xPos=随机范围(31,-14);
实例化(runner,新向量3(xPos,0.4f,6),四元数.identity);
}
}
//每帧调用一次更新
私有void更新()
{
zkleet=GameObject.FindGameObjectsWithTag(“僵尸”);
如果(zkleet.Length==0)
{
start例程(SecondWave());
HassencondAveran=真;
}
如果(zkleet.Length==0)
{
start例程(ThirdWave());
HasThirdWaveRan=true;
}
if(hassthirdwaveran==true&&HasSecondWaveRan==true)
{
SceneManager.LoadScene(“已完成2级”);
}
}
IEnumerator第二波()
{
if(hassencodwaveran==false)
{
收益率返回新的WaitForSeconds(5.0f);
对于(int i=0;i<5;i++)
{
xPos=随机范围(31,-14);
实例化(runner,新向量3(xPos,0.4f,6),四元数.identity);
}
对于(int i=0;i<20;i++)
{
xPos=随机范围(31,-14);
实例化(僵尸,新矢量3(xPos,0.4f,6),四元数.identity);
}
HasThirdWaveRan=false;
HassencondAveran=真;
}
}
IEnumerator ThirdWave()
{
if(HasThirdWaveRan==false)
{
收益率返回新的WaitForSeconds(5.0f);
对于(int i=0;i<5;i++)
{
xPos=随机范围(31,-14);
实例化(runner,新向量3(xPos,0.4f,6),四元数.identity);
}
对于(int i=0;i<20;i++)
{
xPos=随机范围(31,-14);
实例化(僵尸,新矢量3(xPos,0.4f,6),四元数.identity);
}
对于(int i=0;i<3;i++)
{
xPos=随机范围(31,-14);
实例化(庞然大物,新向量3(xPos,0.4f,6),四元数.identity);
}
HasThirdWaveRan=true;
}
}
}

更新仅在一个帧中完成所有if语句。因此,当您将布尔值设置为true时,将执行下一个if语句,从而将所有这些语句都更改为true。您可以尝试以下方法:

private bool HasSecondWaveRan=false;
private bool HasThirdWaveRan=false;
...
私有void更新()
{
zkleet=GameObject.FindGameObjectsWithTag(“僵尸”);
如果(zkleet.Length==0)
{
如果(!hassencodwaveran&&!hassencodwaveran)
{
StopCorroutine(FirstWave());
//你没有“第一波”,但我想我
//可能包括它。如果不想,请删除它
//第一波。
start例程(SecondWave());
HassencondAveran=真;
返回;
}
else if(hassencodwaveran&!hassthirdwaveran)
{
StopCorroutine(SecondWave());
start例程(ThirdWave());
HasThirdWaveRan=true;
返回;
}
else if(hassencodwaveran&&HasThirdWaveRan)
{
StopCorroutine(ThirdWave());
SceneManager.LoadScene(“已完成2级”);
}
}
}
您可以从比较
Has\u WaveRan
false
的协同程序中删除if语句。如果if语句运行,我使用“return”取消更新函数。如果用update函数替换此代码,它应该可以工作。如果没有和/或您收到错误,请注释并描述该行、发生的错误以及错误代码。将协程更改为:


IEnumerator第二波()
{
对于(int i=0;i<5;i++)
{
xPos=随机范围(31,-14);
实例化(runner,新向量3(xPos,0.4f,6),四元数.identity);
}
对于(int i=0;i<20;i++)
{
xPos=随机范围(31,-14);
实例化(僵尸,新矢量3(xPos,0.4f,6),四元数.identity);
}
收益率返回新的WaitForSeconds(5.0f);
// For now does nothing than keeping track of all existing instances of this script
public class Enemy : MonoBehaviour
{
    // stores all instances of this component => all existing enemies in the scene
    private static readonly HashSet<Enemy> instances = new HashSet<Enemy>();

    // Readonly access property
    // returns a new HashSet so nobody on the outside can alternate the content
    public static HashSet<Enemy> Instances => new HashSet<Enemy>(instances);

    // For our script we only need the count which is cheaper then going through the "Instances" property
    public static int Count => instances.Count;

    private void Awake()
    {
        // Register yourself as soon as you come alive
        instances.Add(this);
    }

    private void OnDestroy ()
    {
        // Unregister yourself as soon as you were destryoed
        instances.Remove(this);
    }
}
// See https://docs.unity3d.com/ScriptReference/CreateAssetMenuAttribute.html
[CreateAssetMenu]
public class WaveProfile : ScriptableObject
{
    // Here you put any information a wave needs e.g.
    // an array of informations of which prefabs and how many of them to spawn
    public PrefabInfo[] PrefabInfos;

    // Depending on your needs you could have additional re-usable profiles
    // to determine when exactly this wave is allowed to BEGIN
    public ScriptableDelay Delay;
}

[Serializable]
public class PrefabInfo
{
    // which prefab to spawn
    public Enemy Prefab;
    // how many
    [Min(1)]public int Amount = 1;
}

// Inherit from this to create as many custom waiters as you need
public abstract class ScriptableDelay : ScriptableObject
{
    // every inheritor will implement its own wait condition(s)
    public abstract IEnumerator Wait();
}
[CreateAssetMenu]
public class TimeDelay : ScriptableDelay
{
    // As the name suggest this one just uses a fixed time delay
    // before starting this wave

    // time in seconds
    public float time = 1f;

    public override IEnumerator Wait()
    {
        yield return new WaitForSeconds(time);
    }
}
[CreateAssetMenu]
public class AllEnemiesDeadDelay : ScriptableDelay
{
    // This one waits until all enemy instances are destroyed before
    // starting this wave

    public override IEnumerator Wait()
    {
        yield return new WaitWhile(() => Enemy.Count > 0);
    }
}
// Not sure why this inherits from Zombie?
public class Waves : Zombie
{    
    // Here you drag in all desired wave profiles for this scene
    public WaveProfile[] waveProfiles;

    // as before in the wave profile add a conditional for when to go to the next
    // scene after the last wave has spawned
    // most probbaly you would want to go for the "AllEnemiesDeadDelay"
    public ScriptableDelay afterLastWaveBeforeNextSceneDelay;

    // name of the scene to load after all waves have run and the "afterLastWaveBeforeNextSceneDelay"
    // has passed
    public string nextScene = "Level_2_Completed";

    // Yes! If you make "Start" return "IEnumerator" then Unity
    // automatically starts it as a Coroutine!
    private IEnumerator Start()
    {
        // iterate over all waves EXCEPT the last one
        // because for the last one we wait in a different way
        foreach(var profile in waveProfiles)
        {
            // Wait for the condition of this wave
            if(profile.Delay)
            {
                yield return profile.Delay.Wait();
            }

            // Spawn all the different enemiy prefabs of the current wave
            foreach(var prefabInfo in profile.PrefabInfos)
            {
                for(var i = 0; i < prefabInfo.Amount; i++)
                {
                    var xPos = Random.Range(31, -14);            
                    Instantiate(prefabInfo.Prefab, new Vector3(xPos, 0.4f, 6), Quaternion.identity);
                }
            }
        }
 
        // After the last have has spawned wait until all enemies are killed
        if(afterLastWaveBeforeNextSceneDelay)
        {
            afterLastWaveBeforeNextSceneDelay.Wait();
        }

        SceneManager.LoadScene(nextScene); 
    }
}