Iâve implemented this very functionality in my asset Make It Random.
To avoid just arrogantly plugging my asset, hereâs the core bit of the algorithm, so that you can get going yourself. 
public int GetRandomWeightedIndex(int[] weights)
{
// Get the total sum of all the weights.
int weightSum = 0f;
for (int i = 0; i < weights; ++i)
{
weightSum += weights[i];
}
// Step through all the possibilities, one by one, checking to see if each one is selected.
int index = 0;
int lastIndex = elementCount - 1;
while (index < lastIndex)
{
// Do a probability check with a likelihood of weights[index] / weightSum.
if (Random.Range(0, weightSum) < weights[index])
{
return index;
}
// Remove the last item from the sum of total untested weights and try again.
weightSum -= weights[index++];
}
// No other item was selected, so return very last index.
return index;
}
To use the function, you just need an array of weights that is equal in size to the number of items you want to select from. It will return an index that you can use to access the selected item.
To summarize/explain the algorithm, you first figure out the weight of all the possibilities summed together. Then you start with the first index and ask, âOut of all the possibilities, how probable is this first index?â That probability is the weight of the first index, divided by the weights of all untested possibilities (including the one currently being checked).
To check that probability, just generate a value greater than or equal to 0, and strictly less than the total untested weights, and if the result is strictly less than the weight of the item being tested, then the check passes and that item should be selected.
If not, then you consider that item to be tested, subtract its weight from the sum of total untested weights, and move on to the next item.
If you manage to make it to the very last item, then the total untested weights will be equal to the weight of that last item. The probability is then of course 100% that the last item will be checked. I wrote my loop above so that it avoids this last useless check, and always returns the last item if it gets that far.
Note that I used integer weights in the above example. The overall concept will work with any other numeric type, but because Unityâs Random class selects from float ranges that include the upper bound, it wonât be exactly accurate unless you write your own method of getting a random float that excludes the upper bound.
(Side note: I just did a search and quickly discovered an alternate method which is even better if you can guarantee that your array of weights is sorted, as it only requires generating a single random number. Time for me to add a to-do for updating my randomization library with that option!)