Easiest way to create a random chance in a tick?

Started by mipen, November 06, 2014, 06:36:11 AM

Previous topic - Next topic

mipen

If I had an object with a normal ticker type, what would be the easiest way to make a random chance of something happening? Say for example I want there to be a 5% chance of the object exploding every day. What would be the best way to achieve this? Is there a UnityEngine method that does a "dice roll", so to speak?

Timber

#1
Quote from: mipen on November 06, 2014, 06:36:11 AM
If I had an object with a normal ticker type, what would be the easiest way to make a random chance of something happening? Say for example I want there to be a 5% chance of the object exploding every day. What would be the best way to achieve this? Is there a UnityEngine method that does a "dice roll", so to speak?
Make a separate ticker that lasts a day per tick.

Randomize between 0 and 100 with this method:

public double GetRandomNumber(double minimum, double maximum)
{
    Random random = new Random();
    return random.NextDouble() * (maximum - minimum) + minimum;
}


Then check if what you got is less or equals to five. "Five" can and probably should be a variable itself, call it "occurChance" or something like that.

More on StackOverflow:
http://stackoverflow.com/questions/1064901/random-number-between-2-double-numbers
I ask not for a lighter burden but for broader shoulders. -Atlas

Rikiki

Use the Rand class:
int value = Rand.Range(minValue, maxValue);


class XXX
{
        const int explodeCheckPeriod = 20000; // 1 day duration.
        int tickCounter = 0;

        public override void Tick()
        {
             tickCounter++;
             if (tickCounter >= explodeCheckPeriod )
             {
                    if (Rand.Value < 0.05)
                    {
                        // Explode! :-D
                    }
                    tickCounter = 0;
              }
         }
}

skullywag

Skullywag modded to death.
I'd never met an iterator I liked....until Zhentar saved me.
Why Unity5, WHY do you forsake me?

mipen

Thanks for the replies guys! That's just what I was looking for! :) on a side note, a better way of having something happen every x number of ticks is to use a modulus of the world tick count. For example:

if((Find.TickManager.curTickCount%x) == 0)
{
DoSomething()
}

Where x is the number of ticks that you want to trigger it, in this case 20000. This is just a big faster and takes removes the need for another variable.
The Rand class looks really useful! How have I not seen it before? :P thanks guys

Rikiki

I believe most of us know the modulus function ;)

However, I think incrementing a local variable is better than relying on a very global one (especially for test and debug).
Plus, in term of computation time, after an hour of game, the ticker will be equal to 3600 * 60 = 216000 and I am quite sure that comparing (x >= 20000) takes less time than computing ((216000 % 20000) == 0)...
Please dear CPU time experts, correct me if I'm wrong. ::)

Tynan

Quote from: Rikiki on November 06, 2014, 04:30:05 PM
I believe most of us know the modulus function ;)

However, I think incrementing a local variable is better than relying on a very global one (especially for test and debug).
Plus, in term of computation time, after an hour of game, the ticker will be equal to 3600 * 60 = 216000 and I am quite sure that comparing (x >= 20000) takes less time than computing ((216000 % 20000) == 0)...
Please dear CPU time experts, correct me if I'm wrong. ::)

You're wrong :p The computer doesn't care how big the numbers are; math operations take the same time for the same operation.

It's also pointless to micro-optimize math like this anyway. Unless you're writing an OS kernel or a low-level renderer, this level of computation is essentially free.

Anyway, for your solution, if you want something to happen on average once per day, but at random times, I'd do two specific things:

1. Only check every 100 ticks.
2. Roll a random die with a 1/200 chance of firing.

So the code would be:


const int CheckFrequency = 100f;

if( Find.TickManager.curTickCount % CheckFrequency == 0 && Rand.Value < CheckFrequency /GenDate.TicksPerDay )
{
//fire event
}


The reason you'd only fire every 100 ticks is because you may become vulnerable to float precision issues if you have to make the chance so small that 20,000 checks produce one hit on average. Actually, you probably wouldn't, but it's nice to be safe in case the code is modified.
Tynan Sylvester - @TynanSylvester - Tynan's Blog

mipen

Thanks Tynan! That's very helpful to know! I'm always wary of using extra variables because I'm learning microcontrollers at Uni and the chip I'm using only has a couple of Kb's of program memory :L