Ange
Ange

Reputation: 319

How to randomly generate GameObjects programmatically?

I'd like some help with the following issue. I'm making a simple game where you have a character running and he has to jump over obstacles coming at him.

And I'm currently stuck when it comes to creating GameObjects and randomly generating them within the game scene at run time.

I've written a class to help accomplish this:

using UnityEngine;
using System.Collections;

public class randomObstacles : MonoBehaviour {

    public GameObject myCube;
    public Vector3 spawnLocation = new Vector3(0,2,0);

    // Use this for initialization
    void Start () {
        GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);
    }

    // Update is called once per frame
    void Update () {

    }
}

The above code is what I wrote to simply create Objects, one after the other. But when I run the game, it comes up empty -_- !

Can anyone please tell me where am going wrong, and from the look of it my code doesn't seem to do what I am hoping to achieve :(

I've attached the above script into an empty GameObject as I saw in a tutorial from the Unity Community forum, but that did not help either. (I've looked around and it seems like no one has come across such an issue - I could bee wrong)

Upvotes: 1

Views: 25014

Answers (3)

Dan Puzey
Dan Puzey

Reputation: 34218

It may be worth pointing out that you're creating your object in the Start method, which means your code will only run once: from the name of your class, I'd assume you want to create more than one object using this code.

If you move the code into Update you'll create one object per frame, which is most likely too many. My guess would be that you want something like a coroutine that will run on a random interval, and then spawn cubes repeatedly over time, something like this:

void Start () {
    StartCoroutine("SpawnObjects");
}

IEnumerator SpawnObjects()
{
    while (keepAddingObjects) // a boolean - could just be "true" or could be controlled elsewhere
    {
        GameObject SpawnLocation = (GameObject)Instantiate(myCube, spawnLocation, Quaternion.identity);
        float delay = Random.Range(1f, 5f); // adjust this to set frequency of obstacles
        yield return new WaitForSeconds(delay);
    }
}

Upvotes: 7

daniel-cheng
daniel-cheng

Reputation: 152

It would seem that your myCube variable is the root of your problems, having tested it in a scene of my own. By subsituting

(GameObject)Instantiate(myCube, ... 

with

(GameObject)Instantiate(GameObject.CreatePrimitive(PrimitiveType.Cube), ...

I was able to produce a cube at (0,2,0) with no qualms. Perhaps your myCube GameObject is missing a Mesh Renderer, in which case it would appear in the Hierarchy during runtime even though it would not appear visible in Game View. Perhaps you are not assigning it in the Inspector before you run the game, in which case the myCube variable would refer to null and thus not be created. Additionally, though you may be assigning the GameObject you instantiate to SpawnLocation, it is an unused local variable (something MonoDevelop or your code editor should notify you of). Make sure you either provide a reference to a myCube GameObject in the Inspector before runtime or through script referencing to a loaded prefab/GameObject during runtime. It would also be helpful to provide a fallback (say, to PrimitiveType.Cube perhaps?), which will make your code more robust and able to handle errors in referencing should they arise.

Regardless, in order to achieve the functionality you have described, first make sure yo have properly prepared whatever you would desire myCube to be. Also, for future posterity, you may want to initialize your spawnLocation in the Start routine, and assign the variable coordinates by substituting Random.value * yourValueCeiling in for each random coordinate you would like myCube to spawn on. You could even go as far to make a helper method externalized and thus independent from the start routine, such that you will not have to have a hundred instances of a single script to create a hundred instances of what you need; rather, you can call the method through a single script, and save yourself trouble in this way. If you would so appreciate it, here is my implementation of your objective, hope this helps!

using UnityEngine;
using System.Collections;

public class randomObstacles : MonoBehaviour {

    public Vector3 spawnLocation;
    public GameObject myCube;

    // Use this for initialization
    void Start () {
        if (myCube != true) {
            Debug.Log("myCube not set");
            myCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }
        if (myCube.renderer.enabled == false) {
            Debug.Log("myCube not rendered");
            myCube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        }
        CreateCube();
    }

    // Update is called once per frame
    void Update () {  
    }

    void CreateCube() {
        spawnLocation = new Vector3(0, Random.value * 10, 0);
        Instantiate(myCube, spawnLocation, Quaternion.identity);
    }
}

Upvotes: 7

LightStriker
LightStriker

Reputation: 21034

Taken from my own code in a game that auto generate mazes:

public class Cell
{
    private GameObject instance;

    public void CreateVisual()
    {
        // Load a GameObject that exist inside the "Resources" folder.
        GameObject prefab = (GameObject)Resources.Load("Models/Walls/3W1"); 

        // Create an instance of the prefab
        instance = (GameObject)GameObject.Instantiate(prefab);
        instance.transform.position = myPosition;
    }
}

I think the part you are missing is the Resources.Load() method.

Upvotes: 2

Related Questions