Well, it’s connected to using Random.Range(). I’ll try to explain…
I wanted to add a bit of interest to my extended text game by having the player get into a fight with the guards here and there. I thought I would use Random.Range() to generate a value and use it to decide the outcome of the fight.
Here’s an example, you’ve just come down the steps and run into a guard.
void steps_1()
{
MainText.text = "The guard in the hallway looks up and sees you, \"Oi! You!\" he shouts "+
"as he draws his tazer.\n\n"+
"Press T to draw your Tazer against the guard.\n";
if( Input.GetKeyDown (KeyCode.T) ) myState = States.steps_2;
}
}
void steps_2( )
{
int myFightResult = Random.Range( 0, 10 );
print( "myFightResult: " +myFightResult);
//odds are stacked slightly in your favour
if( myFightResult <= 6 ) myState = States.steps_3;
else if( myFightResult >= 7 ) myState = States.steps_4;
}
void steps_3() //you won the tazer fight
{
MainText.text = "You zap the guard with your tazer. He falls to the "+
"ground and lies there twitching and grunting. "+
"You drag him into a corner and leave him.\n\n"+
"Press H to return to the Hallway";
if( Input.GetKeyDown (KeyCode.H) ) myState = States.hallway_0;
}
void steps_4() //you lost the tazer fight
{
MainText.text = "The guard is a quicker draw than you and shoots you with his tazer. "+
"As you fall to the floor, twitching and dribbling, you see the other "+
"guards arriving.\n\n"+
"Press C to Continue";
if( Input.GetKeyDown (KeyCode.C) ) myState = States.cell_6;
}
Sometimes it works as intended and sometimes not. It seems to me that the steps_2() method is run several times before moving on to the next method.
In the screenshot you can see that steps_2() has run four times. On the first three times, it generates a value less than 6 indicating that you win the fight, but on the fourth it generates 7, meaning that you lost. In the last two lines of the console it looks like steps_3() AND steps_4() are both executing.
If you press C to continue, you go back to the cell as expected, but the console shows that steps_3() is still being called over and over. Sooner or later this trips the game up because you press a key (in this case the H key) expecting something to happen, but it’s a race between steps_3 and whichever other method you think you’ve called, to respond the keypress.
At the time of writing, I’ve been banging my head on the desk about this, between other things, for nearly two weeks.
I’ve tried rewriting my code in as many ways as I can think of, including:
-
setting up a global variable for fightResult so that I can generate its value before leaving the steps_1() method, so that all steps_2() has to do is examine the result and decide which method to call and call it. But before long I come up against the same problem.
-
moving the three methods I have shown above into one longer method, I get a problem where Random.Range is being called with every update and it causes the text messages to change faster than you can read them as Random.Range generates different results.
I thought about making each option in the game have a different letter to try to remove the race condition, but that doesn’t sit well with me because it’s just trying to cover up the problem instead of fixing it and sooner or later the menu choices are going to look pretty silly, for example: “Press X to Open such and such.”
I’ve also looked at the man pages for Execution Order of Events, Time, the Time Manager and Time and Framerate Management because I thought one of the settings there might solve my problem, but so far I cannot find it.
I thought that update() was run once per frame, so I don’t understand why steps_2 seems to be executed multiple times.
Has anyone else come across this, know a better way to do it or have any suggestions as to what I might try next?