2
votes

i have a problem with my unity code and i can't get it why it doesn't work. I am kinda new to unity, just starting to learn it. I have 4 prefabs with different name in the project tree, and i want a prefab to spawn every second, but i want it to be randomized without using "if"'s, so i tried to save the prefabs names in an array and then Instantiate the GameObject that has the same name with the value of the array. When i run my script in Unity it says that the object i want to instantiate is null, i tried to find an answer on the web, but i found nothing. Can you help me?

This is my code:

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

public class Spawnnoif : MonoBehaviour
{
    public GameObject cub;
    public GameObject capsula;
    public GameObject cilindru;
    public GameObject sfera;
    public int x;
    public GameObject paleta;
    public float delta;
    public string[] a = { "cub", "capsula", "cilindru", "sfera" };

    void Start()
    {
        Vector3 position = new Vector3(UnityEngine.Random.Range(-1.88f, 2.1f), 1, UnityEngine.Random.Range(-7.81f, -3.1f));
        x = UnityEngine.Random.Range(0, 3);
        Instantiate(GameObject.Find(a[x]), position, Quaternion.identity);
    }

    IEnumerator Spawn()
    {
        while (true)
        {
            Vector3 position = new Vector3(UnityEngine.Random.Range(-1.88f, 2.1f), 1, UnityEngine.Random.Range(-7.81f, -3.1f));
            x = UnityEngine.Random.Range(0, 3);
            Instantiate(GameObject.Find(a[x]), position, Quaternion.identity);
            yield return new WaitForSeconds(1.0f);
        }
    }
}
2
Are you sure GameObject.Find(a[x]) returns something? - krobelusmeetsyndra
I moved now the GameObjects into the scene, looks like this was a problem, but still, it only generates cubes, no other object is generated - Morar Mihai
Are all the objects with the correct tag name? - krobelusmeetsyndra
@krobelusmeetsyndra Find has nothing to do with tags but only with the object names - derHugo

2 Answers

1
votes

Please don't use Find for this! It is extremely expensive! And unreliable!

This function only returns active GameObjects. If no GameObject with name can be found, null is returned.

Especially since it looks like you want to use this for prefabs that only exist in the Assets and not in the Scene this will always return null as it only finds objects from the Scene.


Rather use an array like

public GameObject[] Prefabs;

reference your objects here and simply do

Vector3 position = new Vector3(Random.Range(-1.88f, 2.1f), Random.Range(-7.81f, -3.1f));
Instantiate(Prefabs[Random.Range(0, Prefabs.Length)], position, Quaternion.identity);

To your IEnuemrator ... well, you never start this as a Coroutine so it is simply never running.

You can do it directly in Start using StartCoroutine

private void Start()
{
    StartCoroutine(Spawn());
}

private IEnumerator Spawn()
{
    while (true)
    {
        Vector3 position = new Vector3(Random.Range(-1.88f, 2.1f), Random.Range(-7.81f, -3.1f));
        Instantiate(Prefabs[Random.Range(0, Prefabs.Length)], position, Quaternion.identity);

        yield return new WaitForSeconds(1.0f);
    }
}

actually you could even directly use

private IEnumerator Start()
{
    while (true)
    {
        Vector3 position = new Vector3(Random.Range(-1.88f, 2.1f), Random.Range(-7.81f, -3.1f));
        Instantiate(Prefabs[Random.Range(0, Prefabs.Length)], position, Quaternion.identity);

        yield return new WaitForSeconds(1.0f);
    }
}

If Start is declared as IEnumerator Unity automatically runs it as a Coroutine.


Or in such a simple case you could even use InvokeRepeating like

private void Start()
{
    // second parameter is the initial delay
    // last parameter the repeat interval
    InvokeRepeating(nameof(Spawn), 0, 1.0f);
}

private void Spawn()
{
    Vector3 position = new Vector3(Random.Range(-1.88f, 2.1f), Random.Range(-7.81f, -3.1f));
    Instantiate(Prefabs[Random.Range(0, Prefabs.Length)], position, Quaternion.identity);
}
0
votes

You could use an array of GameObjects (the prefabs) and assign them in the editor. Then you can assign as many prefabs as you want in the Inspector and spawn them randomly:

public class Spawnnoif : MonoBehaviour
{
    public GameObject[] prefabs;

    public int x;
    public GameObject paleta;
    public float delta;

    void Start()
    {
        Vector3 position = new Vector3(UnityEngine.Random.Range(-1.88f, 2.1f), 1, UnityEngine.Random.Range(-7.81f, -3.1f));
        x = UnityEngine.Random.Range(0, prefabs.Length);
        Instantiate(prefabs[x], position, Quaternion.identity);
    }
    ...
}