Physics.Overlapsphere не обнаруживает коллайдеры - PullRequest
0 голосов
/ 08 апреля 2020

Я работаю над своей второй игрой в fps.

Я знаю, что этот вопрос может быть повторен, но я не смог найти решение своей проблемы. Потому что в моем скрипте все нормально.

Итак,

У меня есть сцена, в которой у меня пустой игровой объект (spawnPoints). он содержит все точки появления для появления врага. ЦЕЛЬ и ПРОБЛЕМА Я не хочу перекрывать врагов. Всего 6 очков появления. Если я поставлю 5 как размер точки возрождения. Все работает хорошо ... то есть враги не пересекаются. Но если я поставлю 7, 8 или 9 в качестве размера массива spawnpoint. враги перекрываются. Я использую Physics.overlapsphere для обнаружения коллайдеров.

Я не хочу порождать врагов, если нет места для появления. Если нет места для появления, тогда я хочу, чтобы враги подождали ... пока не очистится любая точка появления.

CODE

using UnityEngine;
using System.Collections; 
public class EnemySpawns : 
MonoBehaviour {

 public GameObject Enemy;
 public Transform[] spawnPoints;
 public float spawnTime;
 public int maxEnemy = 5;
 private int currentEnemy = 0;
 bool isSpawn;

 public float EnemyRadius = 16f;
 void Start(){
     isSpawn = false;
     InvokeRepeating ("spawnEnemy", spawnTime, 5.4f);
     isSpawn = true;
 }


 public void spawnEnemy(){

     for (int i = 0; i < spawnPoints.Length; i++) {

         Collider[] cols = Physics.OverlapSphere (spawnPoints [i].transform.position, EnemyRadius);

         foreach (Collider hit in cols) {
             if (hit.tag == "AI Controller")
             {
                 isSpawn = false;
                 return;
             } 
             else
             {
                 isSpawn = true;
             }

         }
     }
     if (isSpawn == true) {
         if (currentEnemy <= maxEnemy) {

             Transform currentSpawnPoint = spawnPoints [Random.Range (0, spawnPoints.Length)].transform;  //pickrandom
             Instantiate (Enemy, currentSpawnPoint.position, currentSpawnPoint.rotation);
             currentEnemy++;


         }
     }
     if (currentEnemy == maxEnemy) {  //stop spawning enemies
         CancelInvoke ();
     }}} 

1 Ответ

0 голосов
/ 08 апреля 2020

у вас было несколько ошибок в вашей логике c, я реорганизовал ваш код в качестве сопрограммы, так как я думаю, что он более уместен в вашем случае.

            StartCoroutine(SpawnEnemies());
        }

        public IEnumerator SpawnEnemies()
        {
            while (_spawnedEnemies < _enemiesToSpawn.OrderBy(o => Random.value))
            {
                // You should really store these "magic numbers" in variables (5.4f)
                yield return new WaitForSeconds(5.4f);

                foreach (var spawnPoint in _spawnPoints)
                {
                    var cols = Physics.OverlapSphere(spawnPoint.transform.position, EnemyRadius);

                    // I would recommend not using tags in general, instead maybe GetComponent<AIController>() or even better, use an enemy layer and use a mask when overlapping the sphere
                    if (cols.Any(c => c.tag == "AI Controller")) 
                    {
                        continue;
                    }

                    Instantiate(_enemyPrefab, spawnPoint.position, spawnPoint.rotation);
                    currentEnemy++;
                    break;
                }
            }
        } 

По сути, функция управляет своим жизненным циклом по сравнению с ... используя invoke, он выполняет итерацию по всем точкам вызова, проверяет, есть ли там какие-либо контроллеры ИИ, и, если нет, порождает там врага.

Если все точки вызова заняты, функция будет ожидать заданную задержку ( 5.4s), а затем повторите попытку.

_enemiesToSpawn.OrderBy(o => Random.value) - это быстрое перемешивание в точках низкой производительности (в вашем случае это будет вызываться N раз каждые 5,4 секунды, что незначительно)

Вы Вы также можете перемещать урожай после за l oop, таким образом, вы сначала будете вызывать врага без задержки и только потом ждать следующего появления.

...