1

I am having a bit of a problem figuring out how to randomly get an object out of a list that wasn't picked on the last update of a script. When this randomly instantiated object is spawned and reaches a certain y value, it will set itself to inactive. So when this object is not active, it will go through an array and pick another object at random. However, I do not want to include the previous active object.

example: blue ball was first active. Moves on the Y axis. Becomes inactive. Next object spawn should have no chance of being a blue ball. Any ideas and help will be greatly appreciated.

My code is below

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

public class ballGeneratorShooter : MonoBehaviour
{

    private int ballSelector;
    private TagNumber theTagNumber;
    public ObjectPooler[] theObjectballPools;//In my inspector, I have 5 prefab gameObjects attached
    List<ObjectPooler> changingBalls;

    public bool changeBalls;

    public GameObject currentBall;
    public GameObject newBall;

    // Use this for initialization
    void Start()
    {

        changingBalls = new List<ObjectPooler>();
        currentBall = newBall;
    }

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

        if (newBall == null)
        {

            ballSelector = Random.Range(0, theObjectballPools.Length);

            newBall = theObjectballPools[ballSelector].GetPooledObject();

            newBall.transform.position = transform.position;
            newBall.transform.rotation = transform.rotation;
            newBall.SetActive(true);
        }

        if (newBall.activeInHierarchy == false)
        {
            if (changeBalls)
            {
                for (int i = 0; i < theObjectballPools.Length; i++)
                {
                    if (theObjectballPools[i].GetPooledObject().GetComponent<TagNumber>().tag != currentBall.GetComponent<TagNumber>().tag)
                    {
                        changingBalls.Add(theObjectballPools[i]);
                    }
                    //changingballs.Add(theObjectballPools[i]);
                }

                ballSelector = Random.Range(0, changingBalls.Count);
                newBall = theObjectballPools[ballSelector].GetPooledObject();
                Debug.Log(changingBalls.Count);
                newBall.transform.position = transform.position;
                newBall.transform.rotation = transform.rotation;
                newBall.SetActive(true);
                currentBall = newBall;
                changeBalls = false;
                changingBalls.Clear();
            }

        }

    }

}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291

2 Answers2

2

You need to store the random number to variable (lastRandomNum) each time you generate a random number. Now, use the function below that can generate a random number with exclusion.

int RandomWithExclusion(int min, int max, int exclusion)
{
    var result = UnityEngine.Random.Range(min, max - 1);
    return (result < exclusion) ? result : result + 1;
}

You pass in 0 to min, then theObjectballPools.Length or changingBalls.Count to the max, then finally, lastRandomNum value to the exclusion parameter.

You also need a boolean variable to determine if this is the first run. If this is the first run, use the Unity's Random.Range function then set the firstRun to false. If it is not the firstRun, use the RandomWithExclusion function from this answer and pass in the lastRandomNum value to exclude it. Also, store the generated random number to the lastRandomNum variable to be used next frame.

Below is a simplified version of what I said above. You have to incorporate that to your code.

GameObject[] yourItem = null;
bool firstRun = true;
int lastRandomNum = 0;

void Update()
{
    if (firstRun)
    {
        firstRun = false;
        //First run, use Random.Range
        lastRandomNum = UnityEngine.Random.Range(0, yourItem.Length);
    }
    else
    {
        //Not First run, use RandomWithExclusion
        lastRandomNum = RandomWithExclusion(0, yourItem.Length, lastRandomNum);
    }

    //Do something with the lastRandomNum value below

    newBall = theObjectballPools[lastRandomNum].GetPooledObject();
}

int RandomWithExclusion(int min, int max, int exclusion)
{
    var result = UnityEngine.Random.Range(min, max - 1);
    return (result < exclusion) ? result : result + 1;
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
1

Try linq :

    public class Ball
    {
        public static List<Ball> balls = new List<Ball>();
        public int value { get; set; }
        public Boolean active { get; set; }

        public Ball() {}
        public Ball(int size)
        {
            // initial class
            Random rand = new Random();
            for (int i = 0; i < size; i++)
            {
                balls.Add(new Ball(){ value = rand.Next(), active = false}); 
            }
        }

        public Ball GetRandom()
        {
            Random rand = new Random();
            Ball randomBall = balls.Where(x => x.active == false).Select((x) => new { value = x, randX = rand.Next() }).OrderBy(x => x.randX).FirstOrDefault().value;
            randomBall.active = true;
            return randomBall;
        }
    }
jdweng
  • 33,250
  • 2
  • 15
  • 20