- Home /
Having problem with instantiating and destroying prefabs
Hello! I've been working on a simple project for quite a while and I have been facing some issues. Basically, my game has some spawn points where some button will spawn and the player has to hit the buttons for points. There are two types of buttons that I have used in an array. One button will kill you and the other will increase your points. I looked for solutions online but I am unable to understand the issue.
Here's my button spawner script: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class ButtonSpawner : MonoBehaviour
{
public GameObject[] Buttons;
//private List<GameObject> Instantiated;
void Start()
{
StartSpawning();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha2))
{
Invoke("StartSpawning", 2f); //Spawn testing
}
}
public void DestroyButtons()
{
GameObject[] gameObjects = GameObject.FindGameObjectsWithTag("Button");
foreach(GameObject target in gameObjects)
{
GameObject.Destroy(target);
}
}
public void StartSpawning()
{
int random = Random.Range(0, Buttons.Length);
Instantiate(Buttons[random], transform.position, Quaternion.identity, transform);
}
}
And here's my Button Manager script that will manage when the buttons will spawn
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ButtonManager : MonoBehaviour
{
ButtonSpawner ButtonSpawner;
void Start()
{
ButtonSpawner = GameObject.Find("ButtonSpawner").GetComponent<ButtonSpawner>();
}
public void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "Player")
{
ButtonSpawner.StartSpawning();
ButtonSpawner.DestroyButtons();
}
}
}
I accessed the spawning and destroying functions of the button spawner script and used it in the button manager script. But when I run the game, it says, "Object reference not set to an instance of an object". Any hint on what am I doing wrong here? Also, I used the button manager script in the buttons prefab and the button spawner script on an empty game object.
Any help is greatly appreciated. Thanks in advance!
Answer by endasil_unity · Jun 23, 2021 at 09:39 PM
Fixing the error message
"Object reference not set to an instance of an object". also tells you what script and what line the error occurs. That information is rather critical to efficiently.
But if it fails directly on start the only rows that I can see that would cause that error after a quick glance is is either:
Instantiate(Buttons[random], transform.position, Quaternion.identity, transform);
meaning your Buttons array is empty or
ButtonSpawner = GameObject.Find("ButtonSpawner").GetComponent();
Where GameObject.Find("ButtonSpawner");
does not find any game object with the exact name "ButtonSpawner". Make sure you spelled it exactly the same, did not add any space in the hierarchy and the Capitalization is exactly the same.
So that solves the issue with the error. Then when it comes to button spawning.
Buttons not spawning as expected
You experience is that this is working when you do the same thing by pressing a button, but you do not do the same thing when pressing a button. You have the button press in the update loop in the ButtonSpawner class and you have 10 of those. All 10 of those spawners will each receive your button press. The frame after all 10 of them will in turn invoke the DestroyButtons script and flag all buttons for destruction. once all spawners have called destruction, each one of those 10 spawners will now invoke the spawner function.
In your ButtonManager, you find 1 button spawner and Invoke DestroyButtons on that one. DestroyButton destroys all 10 buttons in the scene. Then the ButtonManager will invoke StartSpawning on that one spawner, making it respawn its own button. What you want is to call all spawners and tell each one of them to respawn their button.
Here is an example on how to solve that with comments.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class ButtonManager : MonoBehaviour
{
// Use a list so we can have multiple spawners
List<ButtonSpawner> ButtonSpawners;
void Start()
{
// FindObjectsOfType will be used to find all ButtonSpawner scripts in the scene.
// As default this will return an array but lists are easier to iterate over, so
// we have a ToList to get it as that instead.
ButtonSpawners = GameObject.FindObjectsOfType<ButtonSpawner>().ToList();
}
public void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "Player")
{
// As long as each spawner destroy all other buttons, we only need
// to call one of them. If you change so that each spawner destroy
// its own button with this call, you can invoke it in the for loop
// loke with StartSpawning
ButtonSpawners.First().Invoke("DestroyButtons", 1f);
// Loop trough the list of each spawner in the scene and have the
// variable button store a reference to the current one.
foreach (ButtonSpawner button in ButtonSpawners)
{
// Invoke the StartSpawning method of this spawner,
// telling it to spawn a new button in about 1.001f seconds.
button.Invoke("StartSpawning", 1.001f);
}
}
}
}
Hello! Thank you very much for your help. I feel dumb because there was a spelling mistake. Thankfully, the error is not showing anymore. However, I am still facing the issue of instantiating and destroying the object properly.
Whenever I hit the green buttons, it doesn't change the button sets, but only keeps one button out of all of them.
So I tried to use a key to test if the sets change. I added this in the button-spawner script and it's working great.
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha2))
{
Invoke("DestroyButtons", 0f);
Invoke("StartSpawning", 0.001f);
}
}
I used a similar process in the button-manager script but used it on the OnCollisionEnter2D function.
public void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "Player")
{
ButtonSpawner.Invoke("DestroyButtons", 1f);
ButtonSpawner.Invoke("StartSpawning", 1.001f);
}
}
But it's not working the way I intended. It doesn't even show any error either. I use my button-manager script in my button prefabs.
I don't know what's happening now. What can I do to solve it?
Updated the answer, see if this additional information helps you solve the problem, otherwise provide info from the debug logs and we can narrow it down future.
Ok, I added debug log and the results were as expected. The green dots on both sides are spawners and I gave each of them the button-spawner script. So the debug shows that the button was spawned 10 times (as there are 5 on each side). But after hitting the green button, it shows one time (as only one of them is being spawned). I have noticed that my script chooses only the first spawner, even though I have given the same script to all of them. The rest of the debug is working fine. So the problem is either on my instantiate script, or how my script handles the spawn points.