如何防止连续两次从数组中选取相同的对象
How to prevent same object from being picked from array twice in a row
我在弄清楚如何从上次更新脚本时未选择的列表中随机获取对象时遇到一些问题。当这个随机实例化的对象被生成并达到某个 y 值时,它会将自己设置为非活动状态。所以当这个对象不活动时,它会通过一个数组并随机选择另一个对象。但是,我不想包括以前的活动对象。
示例:蓝球最先激活。在 Y 轴上移动。变得不活跃。下一个生成的对象应该没有机会成为蓝球。任何想法和帮助将不胜感激。
我的代码如下
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();
}
}
}
}
试试 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;
}
}
每次生成随机数都需要将随机数保存到变量(lastRandomNum
)中。现在,使用下面的函数可以生成 exclusion
.
的随机数
int RandomWithExclusion(int min, int max, int exclusion)
{
var result = UnityEngine.Random.Range(min, max - 1);
return (result < exclusion) ? result : result + 1;
}
您将 0
传递给 min
,然后将 theObjectballPools.Length
或 changingBalls.Count
传递给 max
,最后,将 lastRandomNum
值传递给排除参数。
您还需要一个 boolean
变量来确定这是否是第一个 运行。如果这是第一个 运行,请使用 Unity 的 Random.Range
函数,然后将 firstRun
设置为 false
。如果不是 firstRun
,请使用此答案中的 RandomWithExclusion
函数并传入 lastRandomNum
值以将其排除。此外,将生成的随机数存储到 lastRandomNum
变量以供下一帧使用。
下面是我上面所说的简化版本。您必须将其合并到您的代码中。
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;
}
我在弄清楚如何从上次更新脚本时未选择的列表中随机获取对象时遇到一些问题。当这个随机实例化的对象被生成并达到某个 y 值时,它会将自己设置为非活动状态。所以当这个对象不活动时,它会通过一个数组并随机选择另一个对象。但是,我不想包括以前的活动对象。
示例:蓝球最先激活。在 Y 轴上移动。变得不活跃。下一个生成的对象应该没有机会成为蓝球。任何想法和帮助将不胜感激。
我的代码如下
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();
}
}
}
}
试试 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;
}
}
每次生成随机数都需要将随机数保存到变量(lastRandomNum
)中。现在,使用下面的函数可以生成 exclusion
.
int RandomWithExclusion(int min, int max, int exclusion)
{
var result = UnityEngine.Random.Range(min, max - 1);
return (result < exclusion) ? result : result + 1;
}
您将 0
传递给 min
,然后将 theObjectballPools.Length
或 changingBalls.Count
传递给 max
,最后,将 lastRandomNum
值传递给排除参数。
您还需要一个 boolean
变量来确定这是否是第一个 运行。如果这是第一个 运行,请使用 Unity 的 Random.Range
函数,然后将 firstRun
设置为 false
。如果不是 firstRun
,请使用此答案中的 RandomWithExclusion
函数并传入 lastRandomNum
值以将其排除。此外,将生成的随机数存储到 lastRandomNum
变量以供下一帧使用。
下面是我上面所说的简化版本。您必须将其合并到您的代码中。
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;
}