Spawning Objects in Unity without the Clutter

Lance Gold
4 min readApr 1, 2024

--

The current operation of the Enemy SpawnManager creates and creates red cubes.

Game Run wth increaseing number of Enemy red cube objects

The next step is to instantiate the Enemy GameObject clones in a container to shorten the list of clones appearing in the Hierarchy list.

Hierarchy full of Enemy(Clone)s

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.

<right-click> to Create Empty object

In this example the new name is Enemy Container, put into the Inspector.

Name choice “Enemy Container” for empty object

open SpawnManager.cs to add the new object. Note the lowercase fieldname.

add empty container name into .cs file, SpawnManager class
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
Drag child object from Hierarchy to Inspector component

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.

Moving _enemyPrefab to parent _enemyContainer

Both newEnemy and _enemyContainer are type GameObject. The parameter “get” takes a type transform, so the “.transform” is added on.

Game run with multiple Enemy(Clone)s

The difference now is the organization in the Hierarchy view under the Enemy Container object.

Enemy(Clone)s inside Enemy Container inside Spawn_Manager

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”

Search result of 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.
Verify gameObject name spelling
  • 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.

--

--

No responses yet