Pergunta

I basically have a script that populates an area in a game, You can add multiple objects to populate the area and they all have a spawn Chance value from 0.00 - 1.00 attached.

I'm trying to convert those spawn chances to fit into 100%, so that 3 objects with with 1.00 will convert to 0.33% or 3 objects with 50% will also convert to 0.33%. Or lastly, 3 objects with: 0.4, 0.4, 0.2 - Will convert to: 40, 40, 20 (I hope thats right).

I'm trying, probably in the wrong direction, this at the moment:

void GetRanges()
{
    for (int i = 0; i < clutterObjects.Length; i++)
    {
        temp += clutterObjects[i].spawnChance;
    }

    if (temp > 1.0)
    {
        temp = temp - 1.0f;

        for (int i = 0; i < clutterObjects.Length; i++)
        {
            clutterObjects[i].spawnChance -= 
                clutterObjects[i].spawnChance * temp;
        }
    }
    else
    {
        temp = Mathf.Abs(temp - 1.0f);
        for (int i = 0; i < clutterObjects.Length; i++)
        {
            clutterObjects[i].spawnChance += 
                clutterObjects[i].spawnChance * temp;
        }
    }

    Spawn();
}

Anyone know how to go about this, Or what a better solution may be.

Foi útil?

Solução

You just need to divide by the overall sum -- that will normalize the values to a total of 1. Start with the sum of all 3, and then divide each one by the sum to get the normalized probability.

double[] probabilities = { 1, 1, 1 }
double sum = probabilities.Sum();
double[] normalized = probabilities.Select(prob => prob/sum).ToArray();

Or, working with your example:

void GetRanges()
{
    double sum = clutteredObjects.Sum(obj => obj.spawnChance);

    for (int i = 0; i < clutterObjects.Length; i++)
    {
        clutterObjects[i].spawnChance /= sum;
    }

    Spawn();
}

Outras dicas

It sounds like you want a weighted average of your parts that totals to 100.

Add them all together to get the total amount, then multiply them all by 100 and divide by your total.

float temp = 0f;
for (int i = 0; i < clutterObjects.Length; i++)
    temp += clutterObject[i].spawnChance;
for (int i = 0; i < clutterObjects.Length; i++)
    clutterObjects[i].spawnChance *= 100f / temp;

You should follow this approach:

  1. Sum the weights (chances)
  2. Divide 1 by the sum
  3. Multiply each weight by the value obtained in 2

That will give you normalized weights, where the sum of the normalized weights will be 1.

Here is a LINQPad program that demonstrates:

void Main()
{
    double[] weights = { 0.5, 0.5, 0.25 };
    double sum = weights.Sum();
    double factor = 1.0 / sum;
    double[] normalizedWeights = weights.Select(w => w * factor).ToArray();
    double[] percentages = normalizedWeights.Select(w => 100.0 * w).ToArray();
    percentages.Dump();
    percentages.Sum().Dump();
}

Output:

40
40
20

100
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top