问题:
假设我有10种敌人,一共20关,每关3-5个敌人就可以满足我的关卡难度,那么怎么随机生成每关的敌人,使每一关的敌人尽量都不一样同时难度递增呢?
1.生成敌人个数曲线:
如果3-5个敌人就可以满足关卡难度那么每多一个敌人,难度就是成倍增加的,所以随着关卡数上升,敌人个数不能线性增长,可以对数增长,即
敌人数基数 =log 关卡数
但是这样第一关不就生成0个敌人?所以应该还要加上一个初始基数
敌人数基数y =log 关卡数x +初始基数
敌人的实际数量在这个基数上随机波动,范围要根据实际情况自定,同时应该定一个上限,即最高可以生成多少敌人。最好到达19或者20关时刚好基数到达上限
假设同时打8个敌人就是最高上限
a=x的y分之一次方,a==2.11
int MaxSpownNumber=8;
int BaseSpownNubmer=4;
int SpownNubmerDownFloat=1;//向下波动1
int SpownNubmerUpFloat=1; //向上波动1
float a = Mathf.Pow((float)MaxSpownNumber, 1f / Level);
int mBaseSpownCount = Mathf.Min(Mathf.FloorToInt(Mathf.Log(a, CurrentLevel)) + BaseSpownNumber, MaxSpownNumber);
int SpownNumber = Random.Range(mBaseSpownCount - SpownNumberDownFloat, mBaseSpownCount + SpownNumberUpFloat);
2.敌人难度分级
将所有的敌人依照难度分级,敌人拥有难度因子变量d
初始容易关卡不应该有难度因子高的敌人。可以有一个可生成种类设置Count,可以试试与关卡数成线性
Count=a*TotalLevel,若总共有10种,开始关可以生成四种,20关,
Count=0.3*TotalLevel;
int BaseSpownCount=4;
int Level=20;
int CurrentLevel
//返回当前这一关可以生成的种类数
private int GetSpownTypeCountWithLine()
{
int count = 0;
count =Mathf.CeilToInt ((float)(enemys.Count - BaseSpownCount) / Level * CurrentLevel);
if (count > enemys.Count)
{
count = enemys.Count;
}
return count;
}
随机生成一个敌人,根据其难度因子d,难度因子越高,生成的机率就越小。
每个敌人的生成机率不同,但所有敌人的生成机率相加为1,使用0-1的随机数就可以确定生成的敌人
如下图所示
也可以不为1,只要保证在算法的处理上可以按难度因子的比率生成对应敌人即可
在生成一个敌人之后,为了尽量不生成第二个,可以将这个敌人生成的机率降为0,同时提高其它的敌人的生成机率
使用数组probability[] 保存所有敌人的生成机率
使用enemys[]保存敌人的prefab,
使用diff[]设置敌人的难度困子,也是初始的生成机率
GetSpownIndex方法根据当前的生成机率随机生成Index,通过index对应生成敌人
public float[] EnemyDiffs; //设置
private float[] probabilitys;
private int Count=GetSpownTypeCountWithLine();
private void Start()
{
for(int i=0;i<enmeys.Count;i++)
{
probabilitys[i] = EnemyDiffs[i];
}
}
private int GetSpownIndex()
{
int index = 0;
float total = 0; //将机率相加
for (int i = 0; i < Count; i++)
{
total += probabilitys[i];
}
float value = Random.Range(0,total);
while (value>=0)
{
value -= probabilitys[index];
index++;
if (index == mSpownTypeCount)
{
break;
}
}
return index-1;
}
获得当前要生成的敌人,生成之,然后改变probabilitys
private void ResetProbabilitys(int index)
{
for (int i = 0; i < Count; i++)
{
if (i != index)
probabilitys[i] += probabilitys[index] / (Count - 1);
}
probabilitys[index] = 0;
}
这样每次生成敌人调用如下代码
int spownIndex = GetSpownIndex();
ResetProbabilitys(spownIndex);
GameObject enemyGo = Instantiate(EnemyPrefabs[spownIndex]);