简体   繁体   中英

GameObject can't be found once per frame, even though it exists

at the moment I am creating a wave based game but I have a problem when it comes to checking whether all the enemies were killed. I have three different Enemies with the Tags "Enemy1", "Enemy2" and "Enemy3". Every second, I am using GameObject.FindGameObjectWithTag("Enemy1") == null to check if all enemies were killed.

Below you can find my code for better understanding:

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

public class Level1WaveSpawner : MonoBehaviour
{
   public enum SpawnState { SPAWNING, WAITING, COUNTING }

   public Waves[] Waves;
   private int nextWave = 0;

   public Transform SpawnPointE1;
   public Transform SpawnPointE2;
   public Transform SpawnPointE3;

   public float timeBetweenWaves = 2f;
   private float waveCountdown;

   private float searchCountdown = 1f;

   private SpawnState state = SpawnState.COUNTING;

   void Start()
   {
       waveCountdown = timeBetweenWaves;
   }

   void Update()
   {

       Debug.Log(EnemyIsAlive());
       if (state == SpawnState.WAITING)
       {
           if (!EnemyIsAlive())
           {
               WaveCompleted();
           }
           else
           {
               return;
           }
       }

       if(waveCountdown <= 0)
       {
           if(state != SpawnState.SPAWNING)
           {
               StartCoroutine(SpawnWave(Waves[nextWave]));
           }
       }
       else
       {
           waveCountdown -= Time.deltaTime;
       }
   }

   void WaveCompleted()
   {
       Debug.Log("Wave Completed");
       state = SpawnState.COUNTING;
       waveCountdown = timeBetweenWaves;

       if (nextWave + 1 > Waves.Length - 1)
       {
           nextWave = 0;
           Debug.Log("Completed all Waves");
       }
       else
       {
           nextWave++;
       }


   }

   bool EnemyIsAlive()
   {

       searchCountdown -= Time.deltaTime;
       if(searchCountdown <= 0f)
       {
           searchCountdown = 1f;
           if (GameObject.FindGameObjectWithTag("Enemy1") == null && GameObject.FindGameObjectWithTag("Enemy2") == null && GameObject.FindGameObjectWithTag("Enemy3") == null) ;
           {
               Debug.Log("All Enemies Killed");
               return false;
           }
       }
       return true;
   }

   IEnumerator SpawnWave(Waves _wave)
   {
       Debug.Log("Spawning Wave: " + _wave.name);
       state = SpawnState.SPAWNING;

       for(int i = 0; i < _wave.count; i++)
       {
           SpawnEnemy(_wave.enemy);
           yield return new WaitForSeconds(1f / _wave.rate);
       }

       state = SpawnState.WAITING;

       yield break;
   }

   void SpawnEnemy(Transform _enemy)
   {
       Transform _sp = null;

       Debug.Log("Spawning Enemies: " + _enemy.name);

       if(_enemy.transform.tag == "Enemy1")
       {
            _sp = SpawnPointE1;
       }
       else if (_enemy.transform.tag == "Enemy2")
       {
           _sp = SpawnPointE2;
       }
       else if (_enemy.transform.tag == "Enemy3")
       {
           _sp = SpawnPointE3;
       }

       Instantiate(_enemy, _sp.position, _sp.rotation);
       
   }
}

The problem that I have is that every single second, the Method returns false (only for one frame) and then switches back to true, even though the Enemies exist the whole time. There is no other code blocking or changing the state of the enemies, and the enemies are tagged. Do you have any idea why this is happening?

Another strange thing I found while experimenting is the following:

Debug.Log("Enemy1 Exists: " + GameObject.FindGameObjectWithTag("Enemy1");

if (GameObject.FindGameObjectWithTag("Enemy1") == null) ;
            {
                Debug.Log("Entered If Loop");
                Debug.Log("Enemy1 Exists: " + GameObject.FindGameObjectWithTag("Enemy1");
            }

The results were the following:

Enemy1 Exists: Enemy1 (Clone)
Entered If Loop
Enemy1 Exists: Enemy1 (Clone)

It seems like the logic on your code is correct, the only problem I could find in the code you provided was here

if (GameObject.FindGameObjectWithTag("Enemy1") == null && GameObject.FindGameObjectWithTag("Enemy2") == null && GameObject.FindGameObjectWithTag("Enemy3") == null) ;

More specifically in the last character, where there is a semicolon, which means that in the case that the if condition is true, nothing will be done, since the code "attached" to it is an empty line followed by a semicolon. The curly brackets that you put after the if aren't actually connected to the if clause in this case, which means that the code inside them will be executed everytime, independently of the enemies being dead or not. If you simply remove this semicolon at the end everything should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM