Unity lists

smokereaper98

Member
Joined
Nov 16, 2019
Messages
12
Programming Experience
1-3
I have a empty objects that is a spawner on my scene and i want it to spawn a random prefab every an x amount of time.. i use this code but i cant figure it out.. im sure there is an easyer way to create a random call from an array.


C#:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class obstacleSpawner : MonoBehaviour
{
    //vars
    public Rigidbody rb;
    public float ForwardForce;
    public GameObject Obstacle2;
    public GameObject Obstacle1;
    private Vector3 test;
    //lists
    public List<string> obstacles = new List<string>();



    void Start()
    {
        obstacles.Add("Obstacle1");
        obstacles.Add("Obstacle2");
        InvokeRepeating("spawnObstacle", 3f, 3f);
    }

    void Update()
    {
        rb.velocity = new Vector3(rb.velocity.y, rb.velocity.y, ForwardForce);
    }
    


    void spawnObstacle()
    {
        System.Random r = new System.Random();
        int genRand = r.Next(1, 2);

        test = new Vector3(10.47f, 0.4096543f, transform.position.z);
        Instantiate(obstacles[r], test, transform.rotation);
    }
 
Your problem may be in the UI. The script above will require your spawn object to be hooked up through the component manager.

Select your game spawn object, and then providing you saved your script, drag the script form the folder its in to the component manager. This is how you are meant to hook up scripts through the Unity UI. However, I generally create a hierarchy Scene Manager object and then under the "Scene", I move the scene manager to the top and I add all my scripts for that scene to that game object. Anyway, see screenshot :

Screenshot_47.jpg


Why do you have this :
C#:
Instantiate(obstacles[r], test, transform.rotation);
You should initialise from inside the start void as it even tells you in the docs Unity - Manual: Creating and Using Scripts
That method you created isn't even used : void spawnObstacle()

Topic belongs in Third Party Products
 
Your problem may be in the UI. The script above will require your spawn object to be hooked up through the component manager.

Select your game spawn object, and then providing you saved your script, drag the script form the folder its in to the component manager. This is how you are meant to hook up scripts through the Unity UI. However, I generally create a hierarchy Scene Manager object and then under the "Scene", I move the scene manager to the top and I add all my scripts for that scene to that game object. Anyway, see screenshot :

View attachment 719

Why do you have this :
C#:
Instantiate(obstacles[r], test, transform.rotation);
You should initialise from inside the start void as it even tells you in the docs Unity - Manual: Creating and Using Scripts
That method you created isn't even used : void spawnObstacle()

Topic belongs in Third Party Products
the spawnObstacle void is used in line 23
C#:
 InvokeRepeating("spawnObstacle", 3f, 3f);
the thing i want to do it to use a random generated number to call a random item from the array like that: obstacles[RandomNumber]. is that possible?
 
Look a little closer at what I quoted you. Are you still not seen the problem?

Yes, it is possible. But you shouldn't be leaving the start/update voids unless you are returning something to it.
 
In your code you have a List<string>
C#:
public List<string> obstacles = new List<string>();
And in your method :
void spawnObstacle(), you are trying to get one of these objects using random, and treating the list as though its a string array or something. Random is nor a string or int, its a class :
C#:
Instantiate(obstacles[r]
And if you do want to search a list, you can use List<T>.Find(Predicate<T>) Method (System.Collections.Generic) and Linq to acquire the values.
So even if you had used the random.Next() assigned int named genRand. Then this too would also be wrong, because your list of Obstacles is of type string, and not int.
Try editing this pseudo code to the way you want it. What I think you are missing is some dynamics which you can acquire by using Tuple<T1,T2> Class (System). I use tuples a lot in Unity, as they give you the ability to expand your functionality.
C#:
public class obstacleSpawner : MonoBehaviour
{
    //vars
    public Rigidbody rb;
    public float ForwardForce;
    public GameObject Obstacle2;
    public GameObject Obstacle1;
    private Vector3 test;
    //lists
    public List<Tuple<int, string, GameObject>> MyObstacles = new List<Tuple<int,string, GameObject>>();
    void Start()
    {
        MyObstacles.Add(Tuple.Create(0, "Obstacle1", Obstacle1));
        MyObstacles.Add(Tuple.Create(0, "Obstacle2", Obstacle2));
        InvokeRepeating("spawnObstacle", 3f, 3f);
    }
    void Update()
    {
        rb.velocity = new Vector3(rb.velocity.y, rb.velocity.y, ForwardForce);
    }
    void spawnObstacle()
    {
        System.Random r = new System.Random();
        int getRand = r.Next(0, 10);
        test = new Vector3(10.47f, 0.4096543f, transform.position.z);

        foreach (Tuple<int, string, GameObject> t in MyObstacles)
        {
            //NOTE : Not all if statements are required, just choose the one you want to check with, otherwise it will instantiate 3 times.
            /* Does it match the ID? */
            if (t.Item1 == getRand)
            {
                Instantiate(t.Item3, test, transform.rotation);
            }
            /* Does it match the obstacle name? */
            if (t.Item2 == "Obstacle2")
            {
                Instantiate(t.Item3, test, transform.rotation);
            }
            /* Does it match the game object? */
            if (t.Item3 == Obstacle1)
            {
                Instantiate(t.Item3, test, transform.rotation);
            }
        }
    }
}
 
Apologises, I overlooked the repeating invoke API. You should also know, if the value for the repeating invoke is ever 0 it won't do anything for you. ;)

And remember to hook up your script to your game spawn object in the UI, otherwise It also won't work.
 
i have it hooked up already. thank you very much for your time again you helped me a lot! il use the code you posted :giggle: thanks a lot again, brother ;)
 
Hold on there. this :
C#:
        MyObstacles.Add(Tuple.Create(0, "Obstacle1", Obstacle1));
        MyObstacles.Add(Tuple.Create(0, "Obstacle2", Obstacle2));
Should be :
C#:
        MyObstacles.Add(Tuple.Create(0, "Obstacle1", Obstacle1));
        MyObstacles.Add(Tuple.Create(1, "Obstacle2", Obstacle2));
Notice I never changed the ID. You should make sure the ID is somehow auto-incremented. So the more objects you add, you will need to increment the integer in the Tuple.

Glad you found it suits your needs.
 

Latest posts

Back
Top Bottom