Many scripts want to run little bits of code at frequent intervals. For example, a script might update the behavior of a zombie. It needs to update conditions repeatedly, like checking the location of the nearest player.
Today, ROBLOX’s Chief Scientist, Erik Cassel, discusses proper use of the wait function.
A very common way to do this in ROBLOX is with the handy “wait” statement. Here is an example:
There is one problem with this code. Can you see it? The wait function takes an optional argument, which is the time that the script should sleep. If you don’t supply an argument, then the function will typically return in 0.03 seconds. That means the script is looking for an enemy to attack 30 times a second! The findClosestEnemy function isn’t cheap. It probably needs to iterate over all the players and find the closest one. That might be fine if you have one zombie in your game, but what about a hoard of 50 zombies? Do you really want 50 zombies rethinking who they will attack 30 times a second? That amounts to 1,500 enemy updates per second.
This isn’t a contrived example. I’ve been analyzing laggy games. A large fraction of them are laggy because of scripts that suck up all the compute time.
Let’s think about zombies for a minute. Zombies are stupid. Once a zombie finds an enemy, he is unlikely to change his mind and go after a new enemy for a while. Let’s make a tiny change to our script:
We supplied a reasonable wait time of five seconds. Once the zombie spots a player, it will go after him for five seconds before looking to see if anybody else is closer. Now our 50-zombie game does 10 updates per second, rather than 1,500.
I have found games that try to wait for 0.0000001 seconds. That means they try to run complex operations 10 million times per second. We may have fast computers these days, but not that fast! These kinds of games suffer from terrible lag.
If your game is laggy, check your script performance. In ROBLOX Studio, there is a great Script Performance panel. Look down the Activity column. It will tell you what percentage of your overall time that a script is taking up. Anything greater than 3% should set off alarm bells.
Better Resuming from a Wait
Another thing to keep in mind is that wait is not guaranteed to return in precisely the time interval you requested. Let’s say your game fills up with 1,000 zombies. Even our optimized scripts might take up a lot of time in aggregate. In that case, ROBLOX will decide that it can’t run all the scripts fast enough, and it will automatically wait longer than requested. We do this because ROBLOX needs to run other processes, like networking, physics and rendering. By “throttling” the script code, we can try to avoid lag.
Let’s write a script that gradually changes the time of day. If you put this script in a game you will see the sun gradually rising:
The script asks to wait for one quarter of a second. However, let’s say that your game is temporarily running out of CPU time. In that case ROBLOX will decide to make your script wait longer than 0.25 seconds, and the sun will rise slower! Here is the solution to the problem:
As stated in the documentation, the wait function returns the actual elapsed time. With that bit of information, we can adjust the time of day accordingly. If the elapsed time is longer than 0.25 seconds, then we’ll skip the time of day forward proportionally.
Lag is often preventable. I’ve found that many games are laggy because of runaway scripts that spend valuable compute time on unnecessarily frequent computation. If you use wait correctly, you’ll be on the way to lag-free game building.