how to get a reference of instantiated objects that have been spawned?


I’m working on a project where I have objects (for example, customers) spawning into the scene, and other objects (a Cash Register) that I can spawn into the scene at will. I basically want the customers (there are seven in total) to be notified when the cash register is spawned by the player.


I can’t seem to figure out a way for this to happen. My idea was to create a boolean in the update function of the customer that reacts when a cash register is spawned, but I cant find a way to get a reference of the cash register object, so it knows it has been spawned.


This is how the objects are being instantiated.


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

public class InstantiateCustomers : MonoBehaviour
{
    [SerializeField] public GameObject objectToSpawn;
    public Tilemap map;
    public float timeRemaining = 0;
    private bool incomingCustomers = true;
    private int amountOfCustomers = 0;
    private int indexQueue = 0;
    void Update()
    {
        timeRemaining = timeRemaining + 1;
        if (timeRemaining >= 500)
        {
            timeRemaining = 0;
            if (incomingCustomers == true)
            {
                amountOfCustomers = amountOfCustomers + 1;
                SpawnCustomers();
            }
            else
            {
                return;
            }
            if (amountOfCustomers >= 7)
            {
                incomingCustomers = false;
            }
        }
    }
    void SpawnCustomers()
    {
        indexQueue = indexQueue + 1;
        GameObject prefabTransform = Instantiate(objectToSpawn, transform.position, Quaternion.identity);
        prefabTransform.GetComponent<CustomerBehaviour>().map = map;
        prefabTransform.GetComponent<CustomerBehaviour>().vec = map.GetCellCenterWorld(new Vector3Int(-1 - indexQueue, -1, 0));
    }
}

public class InstantiateItems : MonoBehaviour
{
    // Start is called before the first frame update
    [SerializeField] public GameObject objectToSpawn;
    [SerializeField] public GameObject cashRegisterToSpawn;

    Vector3 lastPos = Vector3.zero;
    public GameObject prefabTransform;
    public GameObject helperTransform;
    Tilemap map;
    GameObject marker;

    void Start()
    {
        map = GameObject.Find("Grid/Ground").GetComponent<Tilemap>();
        marker = GameObject.Find("Marker");
    }

    public void InstantiateDesk()
    {
        prefabTransform = Instantiate(objectToSpawn, transform.position, Quaternion.identity);
        prefabTransform.GetComponent<DeskBehaviour>().prefabTransform = prefabTransform;
        prefabTransform.GetComponent<DeskBehaviour>().map = map;
        prefabTransform.GetComponent<DeskBehaviour>().HasSpawned = true;
        prefabTransform.GetComponent<DeskBehaviour>().HasBeenPlaced = false;
    }

    public void InstantiateCashRegister()
    {
        prefabTransform = Instantiate(cashRegisterToSpawn, transform.position, Quaternion.identity);
        prefabTransform.GetComponent<CashRegisterBehaviour>().prefabTransform = prefabTransform;
        prefabTransform.GetComponent<CashRegisterBehaviour>().map = map;
        prefabTransform.GetComponent<CashRegisterBehaviour>().HasSpawned = true;
        prefabTransform.GetComponent<CashRegisterBehaviour>().HasBeenPlaced = false;
        marker.GetComponent<MarkerBehaviour>().selectedObject = prefabTransform;
    }
}

I also dont know how to get a reference from a group of instantiated objects. I’ve assumed you could loop through a group of objects, and make them all call a method at the same time, or call a method based on the index of the customer.
Here is what the script attached to the customer looks like:

public class CustomerBehaviour : MonoBehaviour
{
    // Start is called before the first frame update
    private Vector3 target;
    public NavMeshAgent agent;
    public Vector3Int location;
    public Vector3Int worldLocation;
    public Tilemap map;
    public Vector3 vec;
    public GameObject customer;
    public GameObject cashRegisterObj;

    void Awake()
    {
        agent = GetComponent<NavMeshAgent>();
        agent.updateRotation = false;
        agent.updateUpAxis = false;

        target = GameObject.Find("CustomerSpawner").transform.position;
    }
    void Update()
    {
        setTarget(vec);
        SetAgentPosition();

        // if cashregisterObj is spawned, then do something
    }
    void setTarget(Vector3 vec)
    {
        target = vec;
    }
    void SetAgentPosition()
    {
        agent.SetDestination(new Vector3(target.x, target.y, transform.position.z));
    }    
}

Excuse me if I’m using the wrong terms for things, I used the term reference, I’m actually not sure if its the right term to use. Any help or hints in the right direction will be much appreciated. Thanks.

Sounds like you want C# Events. The idea is that, when you spawn a Cash Register, a message is sent out saying that one has been spawned. Any GameObjects that are interested can listen out for this event (they subscribe to it) and can react accordingly. I put some basic details in an earlier reply of mine. Check out the answer to this question (look for the green section).

While that was specific to the original question, you should be able to adapt it for your use case. There are also plenty of video tutorials on C# events that may help.

It goes something like this:

Define the event at the top of your Cash Register code:

public static event Action<GameObject> onNewRegister;

Trigger the event when spawning a new Cash Register:

onNewRegister?.Invoke(newRegister);

Subscribe to the event in the Customer class:

private OnEnable()
{
     WhatYourRegisterClassIsCalled.onNewRegister += CustomerReactMethod;
}

private OnDisable()
{
     WhatYourRegisterClassIsCalled.onNewRegister -= CustomerReactMethod;
}

Finally, add the code to make your customer react to the new register:

void CustomerReactMethod(GameObject newRegister)
{
   // Your code here to react to new register appearing
}

Come back if you have any further questions…