Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Dynamic spawn areas for enemies to spawn

Discussion in 'Scripting' started by Polarfist1, Jan 29, 2022.

  1. Polarfist1

    Polarfist1

    Joined:
    Aug 16, 2021
    Posts:
    15
    I have a game in which there is a map where enemies spawn. Currently, enemies spawn in a randomspawnpos in a random range across the map's x and z coordinates. What I want instead is a randomspawnpos that is dynamic.
    What this means is that enemies can spawn in different areas, only if that area has been unlocked by the player (buying a gate for access, or if its the standard one), else enemies cannot spawn in that area if it hasnt been unlocked.
    For the areas that have been unlocked, I want enemies to spawn in them randomly (ie if 3 enemies spawned next wave, 2 might spawn in Area 1 and 1 might spawn in area 2, 0 in area 3, 0 in area 4 as they have not been unlocked yet).
    Here is my code, note that any code in comments is my attempt at dynamic spawn position (basically pseudocode), the other code is there for the wave spawning or the static randomspawnpos. Also note that the spawnareas array has 2 elements in it currently, those being 2 empty objects with different coordinates. The array's list is controlled and changed in the script's component in the inspector (the script's parent is called SpawnPoint1 if that information is necessary):

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.AI;
    5. public class GameController : MonoBehaviour
    6. {
    7.     public int waveNumber = 0;
    8.     public int enemySpawnAmount = 0;
    9.     public int enemiesKilled = 0;
    10.     //public GameObject[] spawnareas;
    11.     public GameObject enemy;
    12.     public float maxX;
    13.     public float maxZ;
    14.     private Enemy enemyScript;
    15.     private NavMeshAgent enemyNavMesh;
    16.     //public int spawnareasx = Random.Range(spawnareas[0, 1].transform.position.x);
    17.     //public int spawnareasz = Random.Range(spawnareas[0, 1].transform.position.z);
    18.     void Start()
    19.     {
    20.         enemyScript = enemy.GetComponent<Enemy>();
    21.         enemyNavMesh = enemy.GetComponent<NavMeshAgent>();
    22.         //InvokeRepeating("spawnEnemy", 1f, 10f);
    23.         //spawnareas[1].SetActive(false); this is not unlocked yet by the pkayer, spawnareas[0] however is not SetActive(false) as that is the standard spawn area)
    24.         StartWave();
    25.     }
    26.     void Update()
    27.     {
    28.         if(Input.GetKeyDown(KeyCode.P))
    29.         {
    30.             spawnEnemy();
    31.         }
    32.         if (enemiesKilled >= enemySpawnAmount)
    33.         {
    34.             NextWave();
    35.         }
    36.     }
    37.     void spawnEnemy()
    38.     {
    39.         float RandomX = Random.Range(-maxX, maxX);
    40.         float RandomZ = Random.Range(-maxZ, maxZ);
    41.         Vector3 randomSpawnPos = new Vector3(RandomX, 10f, RandomZ);
    42.         //Vector3 randomSpawnPos2 = new Vector3(spawnareasx, 10f, spawnareasz);
    43.         Instantiate(enemy, randomSpawnPos, Quaternion.identity);
    44.     }
    45.     void StartWave()
    46.     {
    47.         waveNumber = 1;
    48.         enemySpawnAmount = 2;
    49.         enemiesKilled = 0;
    50.         for(int i = 0; i < enemySpawnAmount; i++)
    51.         {
    52.             Invoke("spawnEnemy", 2);
    53.        
    54.         }
    55.     }
    56.     public void NextWave()
    57.     {
    58.         waveNumber++;
    59.         enemySpawnAmount += 2;
    60.         enemiesKilled = 0;
    61.         enemyScript.health += 2f;
    62.    
    63.         if(enemyNavMesh.speed < 15f)
    64.         {
    65.             enemyNavMesh.speed += 0.1f;
    66.         }
    67.    
    68.         if(waveNumber % 5 == 0)
    69.         {
    70.             enemyScript.enemyScore += 10f;
    71.         }
    72.    
    73.         for (int i = 0; i < enemySpawnAmount; i++)
    74.         {
    75.             Invoke("spawnEnemy", 2);
    76.         }
    77.     }
    78. }
    Also, does setactive(false) actually remove the gameobject in the array from the pool of choosable spawn locations?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    Tons of ways to do dynamic spawns. Here's a few:

    - put blank gameobjects into the scene for each spawn location, grouping them into "Regions"

    - put a single blank gameobject in and choose a position within a random distance of it

    - put min and max blank gameobjects in and choose points randomly between them

    - put colliders in your scene and use their bounds to generate random locations. Use layers to keep the colliders from interfering with other physics functions

    - hard-code the coordinates in your scene (oldskool, hard to maintain)

    - many many many other ways.
     
  3. Polarfist1

    Polarfist1

    Joined:
    Aug 16, 2021
    Posts:
    15
    This is good, but it doesn't really help with the 'dynamic' part of the spawns instead only helps with implementing spawners.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,970
    I'm sorry, I thought it was obvious.

    This applies to ALL of the ways above I listed.

    Put groups of the whatever spawn-indicator objects above that you choose either a) into an array in your spawn script, or b) under a single GameObject so you can find them

    When you go spawn, based on the state of your game, choose from a list appropriately.

    I'll say it even more explicitly:

    Code (csharp):
    1. // fill these out in your spawner manager thingy:
    2. public Transform[] SpawnsForArea1;
    3. public Transform[] SpawnsForArea2;
    4. public Transform[] SpawnsForArea3;
    When you go to choose, choose randomly from above.

    If you haven't unlocked area 2... don't use that list!
     
  5. Polarfist1

    Polarfist1

    Joined:
    Aug 16, 2021
    Posts:
    15
    I can't do much with this still, sorry if I am being a nuisance; I want enemies to be able to spawn not from ONE randomly chosen SpawnsForArea, but all of the ones unlocked (for example if player has 2 areas unlocked, it will randomly choose between those two SpawnsForArea to spawn enemies in; for example if there were 10 enemies spawning next round, 5 could spawn in spawn locations in SpawnsForArea1, and 5 could spawn in spawn locations in SpawnsForAreas2 etc)

    I am not that experienced in coding, but I hope you can help.