【发布时间】:2020-11-01 15:56:09
【问题描述】:
我正在创建一个经常使用加权生成的 RPG。许多类,如怪物、战利品或地牢生成都有一个名为 spawnChance 的变量,它是一个 0-100 的值,用于确定生成率。
我以前一直使用这种选择方式从数组中获取随机加权成员
var weights = enemy.Select(e => e.spawnChance);
var index = weights.GetRandomWeightedIndex();
return enemy[index];
这是扩展名
public static int GetRandomWeightedIndex(this IEnumerable<float> weights)
{
int count = weights.Count();
if (weights == null || count == 0)
{
Debug.LogWarning($"Weights are invalid");
return -1;
}
else if (count == 1)
return 0;
float w;
float t = 0;
int i;
for (i = 0; i < count; i++)
{
w = weights.ElementAt(i);
if (float.IsPositiveInfinity(w))
{
return i;
}
else if (w >= 0f && !float.IsNaN(w))
{
t += weights.ElementAt(i); ;
}
}
float r = UnityEngine.Random.value;
float s = 0f;
for (i = 0; i < count; i++)
{
w = weights.ElementAt(i); ;
if (float.IsNaN(w) || w <= 0f) continue;
s += w / t;
if (s >= r) return i;
}
return -1;
}
但是,我想减少这段代码,因为通过 linq 选择所有浮点数然后将其传递到扩展程序然后返回的方法相当繁琐并且使用了数十次。
我曾想过使用反射在泛型类中找到一个名为“spawnChance”的变量,但由于所有内容都是在运行时生成的,所以速度会很慢。
我是否可以将 spawnChance 从一个简单的浮点数转换为一个类,然后以某种方式编写一个 linq 方法,该方法能够高效地提取该类的值?由于项目设置,这些类不能从 spawnChance 类继承。 想法?感谢您的宝贵时间!
【问题讨论】:
-
如果我是你,我不会将生成机会实现为浮点数,而是整数百分比。请记住,C# 中的
floats 不是小数,而是 base-2 数字(特别是 binary32 数字,例如二进制中的 0.010101)。像小数一样处理二进制数有时会导致令人惊讶的结果。 -
也可以使用C#的
System.Decimal(decimal),它是十进制数格式。 -
如果您正确处理浮点数就可以了,即将它用作“距离”的总和而不是离散的度量。