My current game – Riflestorm – has lots of procedurally generated levels, enemies, events and so on. Even a lot of the gameplay is random as well. This week I just wanted to share some tricks for generating more effective random numbers.
Basic Chance
// accuracy 0% - 100%
if (UnityEngine.Random.Range(0, 100) < accuracy) return true;
Common condition for basic attacks. Accuracy is the chance to land a successful hit.
Randomized Stores
local quantity = randInt(2, 3) -- 2 or 3
local price = randItem({400, 500}) -- 400 or 500
echo.store.sellSupplies(quantity, price)
randItem
returns a random item from the given table (array). This is useful for limiting the randomness to a few options. In this case I don’t want random numbers between 400 - 500.
Critical Hits
public static int[] criticalBuckets = new int[]{115, 125, 135, 150};
public float BucketBonus(int[] bucket) {
float bonus = 100.0f;
if (bucket.Length > 0) {
bonus = bucket[UnityEngine.Random.Range(0, bucket.Length)];
}
return (bonus / 100.0f);
}
// usage
float criticalBonus = BucketBonus(criticalBuckets); // 1.15f, 1.25f, 1.35f or 1.5f
weapDmg = (int)(weapDmg * criticalBonus);
A better way to handle critical hits is to create buckets with big stepped values for more varried results. This is used in many RPGs.
Random Damage
int splitDamage = (int)Mathf.Ceil(weapDmg * weapon.DamageSpray); // DamageSpray ~0.1-0.2
int damage = weapDmg - UnityEngine.Random.Range(0, splitDamage);
Slightly randomize damage output, for bigger numbers like the shotgun a bucket is used instead because it will give more varried random numbers.
Randomize List
local classes = randShuffle({"Class1", "Class2", "Class3", "Class4", "Class5", "Class6"})
Sometimes you want to randomize a list of something and loop through the results. For this case I created a randShuffle
method to randomize the lists order.
Random Amount of Items From List
local rareItems = randAmount({"AK47", "M4Carbine", "L96A1", "SCARL", "Glock", "M9"}, randInt(2, 3)) -- {"AK47", "M9", maybe 3rd item}
I use randAmount
to choose a number of items from an array and return it. Useful for choosing a smaller subset from a bigger pool, like in this case choosing which rare items to give.
Lastly Random Money
When a player wins a mission or gets money from an event. Instead of hard coding an amount. A simple 0 - 3 value is sent. The game will then calculate the correct amount to give.
eventUtil.randCash(randInt(2, 3)) -- give mid or highest amount of cash
Source
public int RandCash(CashLevels cashLevel) {
int min = 0;
switch (cashLevel) {
case CashLevels.None:
return 0;
case CashLevels.Low:
min = 1000;
break;
case CashLevels.Medium:
min = 2000;
break;
case CashLevels.High:
min = 2500;
break;
}
min = (int)(min * diff.cashMod);
int max = (int)(min * 1.25f);
return Random.Range((int)(min / 10.0f), (int)(max / 10.0f)) * 10;
}
To keep money looking nice, all values below 10 is cutoff. All money is also multiplied by diff.cashMod
to give more money in easy mode and less in hard mode.
Conclusion
I write a new blog post every week, subscribe to my newsletter for updates.