- Home /
Create a 10 second delay using WaitForSeconds
Hi everybody!
First question here on unityAnswers so be gentle! :D
I'm currently creating an air hockey game. So far, I have the drag and drop working, the collisions working to an extent but not perfectly, the scores, and I am now on creating power ups. I have them creating in random positions and even alternating ends of the table to keep it fair and only 1 on the table at a time, with 1 of 2 possible power ups which works fine. The power up gets used instantly and after 5 seconds, all goes back to normal as hoped. Where I get my problem is trying to delay the creation of power ups. Obviously, if left completely to itself, the random number generator could churn out several power ups within quick succession i.e., as soon as one is collected, another is created. Similarly, it could be ages before a new power up is created. I don't want this, it wouldn't make for a nicely playable game. I want it so that it has to wait for at least 10 seconds before another power up can be created and i am having serious issues. I have a 'RandomNumberGenerator' script which is just attached to a GUIText object and at the moment, I have the 'Update()' function which calls the 'RandomPowerup()' function:
function Update ()
{ RandomPowerup(); }
then in my 'RandomPowerup()' function (edited):
function RandomPowerup()
{ yield WaitForSeconds(5); //This is the only Wait that actually works and only the first time it runs through
var random : int = Random.Range(0, 3);
var xPos : int;
var zPos : int;
if (powerOn == false) //If there isn't already a power up on the table
{
if (random == 1) //Decide which power up it is
{
if (powerPlace == true) //Decide where on the table to put it
{
xPos = Random.Range(5, 145);
zPos = Random.Range(-75, 75);
powerPlace = false;
}
else
{
xPos = Random.Range(-145, -5);
zPos = Random.Range(-75, 75);
powerPlace = true;
}
powerOn = true;
cube = Instantiate(powerUp, Vector3(xPos, 5, zPos), Quaternion.identity); //Create powerup
HandleBehaviour.powerUpType = "PaddleSizeUp"; //For debugging
yield WaitForSeconds(3); //wait after power up is created before doing anything else *****
}
if (random == 2) //All same as above
{
if (powerPlace == true)
{
xPos = Random.Range(130, 145);
zPos = Random.Range(-75, 75);
powerPlace = false;
}
else
{
xPos = Random.Range(-145, -130);
zPos = Random.Range(-75, 75);
powerPlace = true;
}
powerOn = true;
cube = Instantiate(powerUp, Vector3(xPos, 5, zPos), Quaternion.identity);
HandleBehaviour.powerUpType = "PaddleSizeDown";
yield WaitForSeconds(3);
}
}
}
*This is the line that doesn't do what I want it to do. It should wait for 3 seconds, but just seems to not do anything. I have seen another couple of topics (http://unity3d.qatohost.com/questions/47872/can-i-not-use-yield-waitforseconds-in-a-class-func.html) and (http://unity3d.qatohost.com/questions/23424/coroutines-waitforseconds-with-function-update.html#comment-79094) that suggest you can't use coroutines like I'm trying to, but I've tried their alternatives and none of them seem to work.
Can anybody offer any support?
Thanks in advance,
Matt
Answer by Bunny83 · Sep 20, 2011 at 12:49 PM
You don't understand how coroutines works. When calling RandomPowerup in Update the function returns immediately and just starts a new coroutine that runs on its own. Since you start a new one each frame you will have hundreds of them running at the same time.
At a frame-rate of 100fps (assumed that the random goes way 1 or 2 and not 0) you have a total waiting time of 8 sec which will run 800 instances of this function at the same time.
You have to prevent calling the function again when it's still running. The easiest way is to use a boolean.
var RandomPowerup_running = false;
function Update () { RandomPowerup(); }
function RandomPowerup() { if (RandomPowerup_running) yield break; // Not sure if that's the right syntax in UnityScript, i'm a C# user ;) RandomPowerup_running = true; yield WaitForSeconds(5);
//
// ...
//
RandomPowerup_running = false;
}
Thankyou! This wasn't exactly right, I had to change the syntax a bit but it is now working. Although unless I'm still doing something wrong a bit, something weird is happening. I have set the Wait time after each possibility to 10 seconds, but it only seems to wait for around 7 seconds. Do you know why this might be happening? Not that its a huge problem, I can just increase the time, but it would interesting to know if its me or something else. Also, can you point me to any good documentation on coroutines just so I can read up for the future? Thanks once again, $$anonymous$$att
Answer by Bunny83 · Sep 20, 2011 at 12:57 PM
Another way would be to Use an infinite loop inside the Coroutine. But the disadvantage is that you can't stop it from outside. To be able to stop it you could again use a boolean outside of the coroutine.
function Start ()
{
RandomPowerup();
}
function RandomPowerup()
{
while (true)
{
yield WaitForSeconds(5);
//
// ...
//
}
}
or to be able to stop it use something like this:
var RandomPowerup_allowed = true;
function RandomPowerup()
{
while (RandomPowerup_allowed)
{
Note that I start this coroutine only once at Start, not in Update!
Your answer
Follow this Question
Related Questions
Wierd issue with Coroutines? 2 Answers
Coroutine not running after yield return new WaitForSeconds 3 Answers
Another yield not working problem 2 Answers
Script gets stuck on WaitForSeconds() 1 Answer
Waypoint / Yield help 1 Answer