Spawn enemies one at a time at the start of the game

At the moment they come into the game space all at once in their formation in the start. After I destroy all the enemies and the formation, then they come in one by one. I would like them to come in one by one as soon as I start the game. If anyone knows how to make this happen then please let me know what I can do to achieve this. Thanks :).

Maybe you could share your enemy spawning code so we can take a look?

From what you are describing it sounds like you may have the enemies already sitting on the enemy spawner/position objects and may need to delete them so that the spawner can spawn new enemies at the start of the level. If you look at the hierarchy (usually on the left side of unity yours may be different) and at your enemy spawner and positions underneath that, are enemies already under your position objects when the game is not running? If so this would cause the enemies to start the level already there and would require you to destroy those before the spawner could make more one by one.

Hi.

Thank you for the response to my question. There are no enemies in my hierarchy. Only the position gizmos as to where they spawn. The enemies spawn in when the game starts but they come flying in, in there formation already, instead of flying in one by one to form the formation. After I destroy all the enemies, then they come flying in one by one to form the formation. I was hoping to get the enemies to fly in one by one instead of all together and forming the formation as the game starts. I think it might have something to do with the script spawning the enemies at the same time at the start and once they respawn, there is a slight delay so they spawn in one by one.

Good morning bools_eye,

Ok so that removes the possibility that the enemy ships are already in the formation. With that in mind it sounds like there is some quirk or something in the enemy spawner script that we would need to comb through to figure out why the ships are flying in all at once versus coming in one by one like they do for the second wave of enemies. I would need to see your code for that script to know for sure whats causing it to behave that way. I have a hunch the issue lies somewhere in the spawnUntillFull or nextFreePosition methods and or how they are called.

@bools_eye,

How does your SpawnUntilFull method compare with the following;

    /// <summary>
    /// Spawns enemies until each enemy position in the formation is filled
    /// </summary>
    private void SpawnUntilFull()
    {
        Transform freePosition = NextFreePosition();

        if (freePosition)
        {
            GameObject enemy = Instantiate(enemyPrefab, freePosition.position, Quaternion.identity) as GameObject;
            enemy.transform.parent = freePosition;
        }
        if (NextFreePosition())
        {
            Invoke("SpawnUntilFull", spawnDelay);
        }
    }

The line which adds the delay is this one;

Invoke("SpawnUntilFull", spawnDelay);

It is calling the same method but with the delay specified by spawnDelay, in the course, this is a public member variable which set initially as follows;

public float spawnDelay = 0.25f;

Note: The above code is a direct copy of that from the course, thus it includes some inefficiency.

using UnityEngine;
using System.Collections;

public class FormationController : MonoBehaviour {
	public GameObject enemyPrefab;
	public float width = 0f;
	public float height = 0f;
	public float speed = 0f;
	public float spawnDelay = 0.5f;
	
	private bool move = true;
	private float xmin;
	private float xmax;

	// Use this for initialization
	void Start () {
		//Restricts enemy to gamespace
		float distance = transform.position.z - Camera.main.transform.position.z;
		Vector3 leftEdge = Camera.main.ViewportToWorldPoint (new Vector3(0, 0, distance));
		Vector3 rightEdge = Camera.main.ViewportToWorldPoint (new Vector3(1, 0, distance));
		xmin = leftEdge.x;
		xmax = rightEdge.x;
		SpawnEnemies ();
	}
		
	//Spawn enemy on Position
	void SpawnEnemies () {
		foreach (Transform child in transform) {
		GameObject enemy = Instantiate (enemyPrefab, child.transform.position, Quaternion.identity) as GameObject;
		enemy.transform.parent = child;
		}
	}
	//Spawns 1 enemy after all is destroyed
	void SpawnUntilFull () {
		Transform freePosition = NextFreePosition ();
		if (freePosition) {
		GameObject enemy = Instantiate (enemyPrefab, freePosition.position, Quaternion.identity) as GameObject;
		enemy.transform.parent = freePosition;
		}
		if (NextFreePosition ()) {
			Invoke ("SpawnUntilFull", spawnDelay);
		}
	}
	
	//Gizmo cube
	public void OnDrawGizmos () {
		Gizmos.DrawWireCube (transform.position, new Vector3 (width,height));
	}
	
	// Update is called once per frame
	void Update () {
		//Moves enemy left and right
		if (move) {
			transform.position += new Vector3(speed * Time.deltaTime, 0);
	}	else {
			transform.position += new Vector3(-speed * Time.deltaTime, 0);
	}
		//Keeps formation from going out of gamespace
		float rightEdgeOfFormation = transform.position.x + (0.5f * width);
		float leftEdgeOfFormation = transform.position.x - (0.5f * width);
		if (leftEdgeOfFormation < xmin) {
			move = true;
		}else if (rightEdgeOfFormation > xmax) {
			move = false;
		}
		//Respawn enemies after all is dead
		if (AllMembersDead()) {
			Debug.Log ("Empty Formation");
			SpawnUntilFull ();
		}
		}

		bool AllMembersDead () {
		foreach (Transform childPositionGameObject in transform) {
		if (childPositionGameObject.childCount > 0) {
			return false;
			}
		}
			return true;
	}
		Transform NextFreePosition () {
		foreach (Transform childPositionGameObject in transform) {
		if (childPositionGameObject.childCount == 0) {
			return childPositionGameObject;
			}
		}
			return null;
	}
}

PS. I edit my float values in the inspector so you’ll see in my code that most of them are at “0”

Hi Rob,

Thanks for your response. As far as I can see, my code looks the same “SpawnUntilFull” as the code from the course. My float value is 0.5f instaed of 0.25f but i changed it to 0.25f and it seems to have the same effect as the 0.5f.

here is my code, if you would like to have a look at it and maybe see if you could see what the problem could be.

using UnityEngine;
using System.Collections;

public class FormationController : MonoBehaviour {
	public GameObject enemyPrefab;
	public float width = 0f;
	public float height = 0f;
	public float speed = 0f;
	public float spawnDelay = 0.5f;
	
	private bool move = true;
	private float xmin;
	private float xmax;

	// Use this for initialization
	void Start () {
		//Restricts enemy to gamespace
		float distance = transform.position.z - Camera.main.transform.position.z;
		Vector3 leftEdge = Camera.main.ViewportToWorldPoint (new Vector3(0, 0, distance));
		Vector3 rightEdge = Camera.main.ViewportToWorldPoint (new Vector3(1, 0, distance));
		xmin = leftEdge.x;
		xmax = rightEdge.x;
		SpawnEnemies ();
	}
		
	//Spawn enemy on Position
	void SpawnEnemies () {
		foreach (Transform child in transform) {
		GameObject enemy = Instantiate (enemyPrefab, child.transform.position, Quaternion.identity) as GameObject;
		enemy.transform.parent = child;
		}
	}
	//Spawns 1 enemy after all is destroyed
	void SpawnUntilFull () {
		Transform freePosition = NextFreePosition ();
		if (freePosition) {
		GameObject enemy = Instantiate (enemyPrefab, freePosition.position, Quaternion.identity) as GameObject;
		enemy.transform.parent = freePosition;
		}
		if (NextFreePosition ()) {
			Invoke ("SpawnUntilFull", spawnDelay);
		}
	}
	
	//Gizmo cube
	public void OnDrawGizmos () {
		Gizmos.DrawWireCube (transform.position, new Vector3 (width,height));
	}
	
	// Update is called once per frame
	void Update () {
		//Moves enemy left and right
		if (move) {
			transform.position += new Vector3(speed * Time.deltaTime, 0);
	}	else {
			transform.position += new Vector3(-speed * Time.deltaTime, 0);
	}
		//Keeps formation from going out of gamespace
		float rightEdgeOfFormation = transform.position.x + (0.5f * width);
		float leftEdgeOfFormation = transform.position.x - (0.5f * width);
		if (leftEdgeOfFormation < xmin) {
			move = true;
		}else if (rightEdgeOfFormation > xmax) {
			move = false;
		}
		//Respawn enemies after all is dead
		if (AllMembersDead()) {
			Debug.Log ("Empty Formation");
			SpawnUntilFull ();
		}
		}

		bool AllMembersDead () {
		foreach (Transform childPositionGameObject in transform) {
		if (childPositionGameObject.childCount > 0) {
			return false;
			}
		}
			return true;
	}
		Transform NextFreePosition () {
		foreach (Transform childPositionGameObject in transform) {
		if (childPositionGameObject.childCount == 0) {
			return childPositionGameObject;
			}
		}
			return null;
	}
}

Thanks again :slight_smile:

1 Like

Hi,

If you look at the FormationController.cs script you’ll note that within it’s Start method it calls SpawnEnemies, not SpawnUntillFull.

SpawnEnemies just iterates through each position and instantiates an enemy prefab instantly.

As a test, within the Start method, comment out SpawnEnemies and add a call to SpawnUntilFull, that would at least take into account the spawnDelay variable.

p.s. when copy/pasting code, if you add the code formatting characters before and after the code it will appear correctly :slight_smile:


See also;

Thank you so much :slight_smile:.
I changed the “SpawnEnemies” to “SpawnUntilFull” at the start method and it fixed the issue, and now the enemies come in one by one.
Thanks again for all the help and the link to guide about apply code formatting to post.
:slight_smile:

1 Like

You’re more than welcome :slight_smile:

One thing you might want to consider…

The code which spawns them all in at once could be useful in the future, depends on it’s usage. For example, you might want to have a level where some enemies fade in / materialise, having a swarrm of them all materialise in at once could be quite a nice effect. So the code in that method SpawnEnemies could still be handy, perhaps a method name change SpawnEnemiesAtOnce for example. Just a thought :slight_smile:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms