Spawning AI Objects in Unity

Richard Morgan
3 min readFeb 11, 2023

We want to spawn a bunch of AI objects in Unity. Here’s what it will look like:

In this example, every time the X key is pressed, a new AI object is created and spawned, complete with Nav Mesh Agent instructions.

We’ve already got our Navigation system and our waypoints set up as prefab objects, and our Sphere prefab object, complete with a Nav Mesh Agent component, and AI_Nav script to control them which looks like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class AI_Nav : MonoBehaviour
{
// move the AI to a Waypoint
public List<Transform> waypoints;
private NavMeshAgent agent;
private int currentWaypoint = 0;

// Start is called before the first frame update
void Start()
{
// Assign the NavMeshAgent component to the agent variable
agent = GetComponent<NavMeshAgent>();
// Enable auto braking and the NavMeshAgent component
agent.autoBraking = true;
agent.enabled = true;
// Set the initial destination to the first waypoint in the list
agent.destination = waypoints[currentWaypoint].position;
}

// Update is called once per frame
void Update()
{
// Check if the distance to the current waypoint is within a certain range
if (agent.remainingDistance < 0.5f)
{
// If so, set the next waypoint as the destination

// if currentWaypoint = last waypoint then destroy the object
if (currentWaypoint == waypoints.Count - 1)
{
Destroy(gameObject);
}
else
{
currentWaypoint = (currentWaypoint + 1) % waypoints.Count;
agent.SetDestination(waypoints[currentWaypoint].position);
}

}

// Check if the NavMeshAgent is on the nav mesh, not stopped or stained, has a path, and is not pending
if (agent.isOnNavMesh && !agent.isStopped && !agent.isPathStale && agent.hasPath && !agent.pathPending &&
agent.remainingDistance < 0.5f)
{
// If so, set the next waypoint as the destination
currentWaypoint = (int)Mathf.Repeat(currentWaypoint + 1, waypoints.Count);
agent.destination = waypoints[currentWaypoint].position;
// Alternatively, select the next waypoint randomly:
// agent.destination = waypoints[Random.Range(0, waypoints.Count)].position;
}
agent.destination = waypoints[currentWaypoint].position;
}
}

We’ll need 3 scripts to spawn our AI objects:
1) Robot custom class script
2) SpawnManager singleton script (attached to empty GameObject)
3) GameManager MonoBehavior script (attached to empty GameObject)

First the Robot class:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


// Serialize to make it visible in the inspector
[System.Serializable]

// Create a class for the Robot
public class Robot
{
//define traits
public GameObject robotPrefab;

// Create a constructor
public Robot(GameObject robotPrefab)
{
this.robotPrefab = robotPrefab;
}
}

Pretty basic… Our robots only have one trait and that’s the prefab. The prefab will already have the Nav Mesh Agent, AI_Nav script (including our waypoints as prefabs), and Collider components:

Next, our SpawnManager will be a singleton for easy referencing:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnManager : MonoBehaviour
{
// make this a singleton
public static SpawnManager instance;

// define our variables
private Vector3 pos1 = new Vector3(42, 1, 3);
public GameObject robotPrefab;

// make this singleton static
public static SpawnManager Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<SpawnManager>();
}
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
}
else
{
Destroy(gameObject);
}
}

// instantiate passed in game object at passed in position
public Robot spawnRobot(GameObject robotPrefab)
{
// create a new robot
Robot robot = new Robot(robotPrefab);
// instantiate the robot
Instantiate(robotPrefab, pos1, Quaternion.identity);
// return the robot
return robot;
}
}

And finally, our GameManager:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameManager : MonoBehaviour
{
// make this a singleton
public static GameManager instance;

//[SerializeField] public GameObject robotPrefab;
[SerializeField] public GameObject robotPrefab;


// make this singleton static
public static GameManager Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<GameManager>();
}
return instance;
}
}
private void Awake()
{
if (instance == null)
{
instance = this;
}
else
{
Destroy(gameObject);
}
}

// Start is called before the first frame update
void Start()
{

}

// Update is called once per frame
void Update()
{
// if S is pressed, call SpawnManager's Spawn method
if (Input.GetKeyDown(KeyCode.X))
{
SpawnManager.Instance.spawnRobot(robotPrefab);
}
}
}

When X is pressed, GameManager calls SpawnManager.SpawnRobot and SpawnRobot instantiates an instance of Robot.

Next, we’ll implement object pooling instead of instantiating/destroying objects one by one.

--

--