Spawning Objects in Unity without the Clutter
The current operation of the Enemy SpawnManager creates and creates red cubes.
The next step is to instantiate the Enemy GameObject clones in a container to shorten the list of clones appearing in the Hierarchy list.
Steps to spawn Enemy(Clone)s inside the Spawn_Manager parent gameObject. The Spawn_Manager was created as an empty GameObject to act as a container.
- Instantiate the object
- Retrieve a reference to the object
- Assign the parent of the reference to Spawn_Manager, the container
<right-click> on Spawn_Manager to create another empty object to act as another container.
In this example the new name is Enemy Container, put into the Inspector.
open SpawnManager.cs to add the new object. Note the lowercase fieldname.
public class SpawnManager : MonoBehaviour
{
[SerializeField]
private GameObject _enemyContainer;
...
- One — <click> to highlight parent Spawn_Manager
- Two, Three — <click> and <drag> child Enemy Container from Hierarchy to Inspector
Compare the two different lines of code:
Instantiate(_enemyPrefab,positionToSpawn, Quaternion.identity);
GameObject newEnemy = Instantiate(_enemyPrefab, positionToSpawn, Quaternion.identity);
2;
int newInt = 2;
The first two lines both create a new Enemy, the second line creates a variable (of type GameObject) to reference the Enemy later if needed.
The same difference is shown in lines 3 and 4.
Both newEnemy and _enemyContainer are type GameObject. The parameter “get” takes a type transform, so the “.transform” is added on.
The difference now is the organization in the Hierarchy view under the Enemy Container object.
To finish the manager to stop spawning with the Player cube is destroyed, the file and its class SpawnManager needs to communicate with the file and class Player.
Inside the Player class:
public class Player : MonoBehaviour
{
[SerializeField]
private int _lives = 4;
public void Damage()
{
_lives-- ;
if( _lives < 1 )
{
// notify SpawnManager when Player dies
// stop spawning new Enemy objects
Destroy(this.gameObject);
}
}
}
The SpawnManager class looks like this:
public class SpawnManager : MonoBehaviour
{
private bool _stopSpawning = false;
...
IEnumerator SpawnRoutine()
{
while(_stopSpawning == false )
{
Vector3 positionToSpawn = new Vector3(Random.Range(-8f, 8f), 7, 0);
GameObject newEnemy = Instantiate(_enemyPrefab, positionToSpawn, Quaternion.identity);
newEnemy.transform.parent = _enemyContainer.transform;
yield return new WaitForSeconds(5.0f);
}
}
public void OnPlayerDeath()
{
_stopSpawning=true;
}
}
GetComponent() is used to communicate among classes.
Here is the search result of “unity scripting api getcomponent”
Unity — Scripting API: GameObject.GetComponent (unity3d.com)
Two steps: Create a local variable equal to the other component. Check if null.
// in the SpawnManager.cs file
public class SpawnManager : MonoBehaviour
//in the Player.cs file
public class Player : MonoBehaviour
{
private SpawnManager _spawnManager; // global to Player class
}
- Verify the Component and spelling in the Inspector for Spawn_Manager.
- Find and check if valid.
// in the Player.cs file
void Start()
{
_spawnManager = GameObject.Find("Spawn_Manager").GetComponent<SpawnManager>();
if (_spawnManager == null )
{
Debug.LogError("_spawnManager is null at Player.Start()");
}
}
Putting the connection to use.
// from the SpawnManager.cs file
public class SpawnManager : MonoBehaviour
{
private bool _stopSpawning = false;
public void OnPlayerDeath()
{
_stopSpawning=true;
}
}
Call the external method.
// from SpawnManager.cs file
public class Player : MonoBehaviour
{
[SerializeField]
private int _lives = 4;
private SpawnManager _spawnManager; // global to Player class
public void Damage()
{
_lives-- ;
if( _lives < 1 )
{
_spawnManager.OnPlayerDeath();
Destroy(this.gameObject);
}
}
}
Now after the Player cube is destroyed, only the existing Enemy objects remain without spawning new ones.