Enemies getting stuck/not reversing only for SpawnUntilFull

Hi,

My code is pretty much exactly the same as in the video, besides a few changes in variable names.

What I’m observing is this:
Before I prepared and implemented the SpawnUntilFull function, everything was working as shown in the video.

However, once I replaced EnemySpawner with SpawnUntilFull in Start and AllMembersDead, the enemy ground would either get stuck or start jittering at a certain point in the play space.

I changed my camera size, and I can move the player controller from end to end, but the EnemyFormation only moves to X = Around 4, and Y = 1.37 from origin point.

While testing different things, I found that if I changed the direction of the movingRight, they would simply continue moving left and not rebound and move back and forth. The enemies properly moved back and forth ONLY if I make them move right FIRST.

Here’s my code:

<using UnityEngine;
using System.Collections;

public class FormationController : MonoBehaviour {

public GameObject enemyPrefab;
public float width;
public float height;
float spawnerxMin;
float spawnerxMax;
public float spawnerSpeed;
public float spawnDelay = 0.5f;

private bool movingRight = true;

// Use this for initialization
void Start () {
	SpawnUntilFull();
}

public void EnemySpawner() {
	foreach( Transform child in transform) {
		//here the just 'transform' is our transform, which is the enemy formation
		//so now the enemy has the same transform as the parent - the enemy instance is now childed
		//instead of the putting the parent of the enemy to be myself(spawner), make the parent my child(position)
		GameObject enemy = Instantiate(enemyPrefab, child.transform.position, Quaternion.identity) as GameObject;
		enemy.transform.parent = child;
		//initialization for the boundaries by camera view for the Spawner
		float distance = transform.position.z - Camera.main.transform.position.z;
		Vector3 leftmost = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, distance));
		Vector3 rightmost = Camera.main.ViewportToWorldPoint(new Vector3(1, 0, distance));	
		spawnerxMin = leftmost.x;
		spawnerxMax = rightmost.x;	
	}
}

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);
	}
}

public void OnDrawGizmos() {
	Gizmos.DrawWireCube(transform.position, new Vector3(width, height));
}

// Update is called once per frame
void Update () {
	//Moving the spawner left and right
	if (movingRight){
		transform.position += Vector3.right * spawnerSpeed * Time.deltaTime;
	} else {
		transform.position += Vector3.left * spawnerSpeed * Time.deltaTime;
	}
	
	//Constrain to playfield
	float rightEdgeofFormation = transform.position.x + (0.5f*width);
	float leftEdgeofFormation = transform.position.x - (0.5f*width);
	if (leftEdgeofFormation < spawnerxMin) { 
		movingRight = true;
	} else if (rightEdgeofFormation > spawnerxMax) {
		movingRight = false;
	}
	
	if (AllMembersDead()){
		Debug.Log("Empty Formation");
		SpawnUntilFull();
		Debug.Log("New Formation spawned");
	}
}

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

}

Right now, I’m able to make it work by not putting SpawnUntilFull in Start and instead have EnemySpawner as usual in start. Then when I kill the enemies they spawn as expected one by one. Really getting confused now :frowning:

In you r EnemySpawner as well as spawning your enemies you also “//initialization for the boundaries by camera view for the Spawner” this sets the correct values for “spawnerxMin” and “spawnerxMax” which are required in you Update function. As they are not been explicitly set they will default I think to zero.

I think the solution is to just move the “//initialization for the boundaries by camera view for the Spawner” code into a separate function and call that first in the Start function before you call SpawnUntilFull

if you use the spawnUntilFull method you won’t need enemySpawner (all at once). You can grab the boundaries by camera code from the enemySpawner method and put it into your spawnUntilFull();. Once you have done this you can probably comment out or delete the EnemySpawner method?

***Code to move from EnemySpawner to SpawnUntilFull.
//initialization for the boundaries by camera view for the Spawner
float distance = transform.position.z - Camera.main.transform.position.z;
Vector3 leftmost = Camera.main.ViewportToWorldPoint(new Vector3(0, 0, distance));
Vector3 rightmost = Camera.main.ViewportToWorldPoint(new Vector3(1, 0, distance));
spawnerxMin = leftmost.x;
spawnerxMax = rightmost.x;

One problem that seems to come up from this is if you kill enemies while they are in the process of “SpawnUntilFull” they never get full and you keep killing the same one over and over. Probably not too hard to work around that one, though. :slight_smile:

Privacy & Terms