tags dev

Generating Better Random Numbers

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.

Back to index