In my previous post, I talked about the dropping of materials from asteroids. I was using Unity’s Random.value to determine the type to drop and needed to add probability per material value. As with any computer programming problem, there are many solutions. An example of my solution is below. I will walk you through this algorithm here and explain how I use it in material choosing.
First, we create an array with our probabilities in it. My goal when creating these is to make them equal 100 or a multiple thereof. Keeping these multiples of 100 makes it easy for me to calculate the percentage I am attempting to portray. In the example code below I do this 10,000 times to show the probability function returns the proper amount of each item given a large sample size. In the game, I have a dictionary with the type as the key and the count of the item as the value. I do this six times to determine the types to return, then add a random value from 1 to 100 to the value of that key. In this fashion, you could get six of the highest value items, only one that would become an object representing the full value of all six. You may remember from a few weeks ago that having fewer actual material objects floating in the scene reduces the overall load on the physics engine.
Random.Next(0, 100) with probabilities at 40, 25, 15, 10, 8, 2
private static void ProbabilityFunction()
{
//To store the count of each item
int[] randomNumbers = new int[6];
//The percentage of each item array
int[] percentages = new int[]{40, 25, 15, 10, 8, 2};
//Used to determine how close we were to the projected percentage
int[] difference = new int[6];
//Get the sum of percentages used, I try to use 100 to make it easy on my brain
int maxNumber = percentages.Sum();
//Holder for the current random number
int currentNumber;
//Do this 10000 times to show the probability is working
for(int i = 0; i < 10000; i ++)
{
//Get a number between 0 and the sum of probabilities
currentNumber = rand.Next(0, maxNumber);
//Look at each percentage and determine if the number falls into that bucket. If not subtract that bucket from the current number and check the next number.
for(int x = 0; x < percentages.Length; x ++)
{
if(currentNumber < percentages[x])
{
randomNumbers[x] ++;
break;
}
else
{
currentNumber -= percentages[x];
}
}
}
for(int i = 0; i < randomNumbers.Length; i ++)
{
difference[i] = Math.Abs(percentages[i] - randomNumbers[i]);
}
Console.Write("Probability : 0: {0} 1: {1} 2: {2} 3: {3} 4: {4} 5: {5}", randomNumbers[0], randomNumbers[1], randomNumbers[2], randomNumbers[3], randomNumbers[4], randomNumbers[5]);
Console.WriteLine(" Diff : {0}", difference.Sum());
}
Percentage 0: 4000 1: 2500 2: 1500 3: 1000 4: 800 5: 200
Probability : 0: 3929 1: 2514 2: 1551 3: 980 4: 841 5: 185 Diff : 210
Probability : 0: 3980 1: 2525 2: 1461 3: 1023 4: 827 5: 184 Diff : 148
Probability : 0: 4008 1: 2517 2: 1477 3: 1028 4: 765 5: 205 Diff : 115
Probability : 0: 3936 1: 2477 2: 1573 3: 957 4: 833 5: 224 Diff : 258