Unity开发中,随机数经常会用到,有时对于随机数会有一些比较特殊的需求。比如,播放一段视频或音频,要求每次播放不同并且所有资源都要能播放到,那么仅适用Random.Range就不够了,需要加入概率的概念,如此,想到了游戏中的掉装备,要每种品质的装备都能掉落,但是品质越好的装备掉落率越低。那么我们的需求中,不同的是我们的概率要简单的多,每个值取到的可能性是相同的。
首先,我们需要定义一个集合,用来存放要选的资源,并做初始化概率,因需求中要求每一个值取到的概率相同,故每个值得概率即为元素数量分之一。这里简化使用字符串做示意,可以根据需要自行修改。
public List<string> listMovies;
private float[] probability;
private void ProbabilityInit()
{
probability = new float[listMovies.Count];
for (int i = 0; i < listMovies.Count; i++)
{
probability[i] = 1.0f / listMovies.Count;
}
}
接下来要开始算概率取值了,原理上,要保证每个元素取到的概率相同,那么简单操作为,取到值得概率降低,同时未取到值的概率升高。这里同样简化为升高、降低都为1%,可自行修改。
private void GetMovie()
{
int probIndex = MakeRandomValue(probability);
foreach (string i in listMovies)
{
if (i == listMovies[probIndex])
{
Debug.Log("播放视频:" + i);
}
}
for (int i = 0; i < probability.Length; i++)
{
if (i == probIndex && probability[probIndex] >= 0)
{
probability[probIndex] -= (listMovies.Count - 1) / 100.0f;
}
else
{
if (probability[probIndex] <= 1)
{
probability[probIndex] += 1.0f / 100.0f;
}
}
}
}
private int MakeRandomValue(float[] arg_ProbabilityTable)
{
float movieProbability = Random.Range(0.0f, 1.0f);
for (int j = 0; j < probability.Length; j++)
{
if (movieProbability <= arg_ProbabilityTable[j])
{
return j;
}
movieProbability -= arg_ProbabilityTable[j];
}
return arg_ProbabilityTable.Length;
}
如此将得到结果:
可以看到,每个值都取到,并且取得次数相差不大,如此当运行一定时间后:
时间问题不做过长时间的测试,目前看来,最多与最少次数的差值稍大,但是整体看还是可以满足我们的需求的。
有更好的方法,欢迎讨论。