Using “Wait” Wisely

Using “Wait” Wisely

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.

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.

The Solution

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.

Conclusion

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.

Great tutorial. Although in my game, I have SMART AI’s, so they navigate around obstacles and jump over/climb over them. Really advanced coding. Anyways, since it does SO many calculations to find out if the player/target is to the left/right/above/below/behind something, this is REALLY useful. And it is also very BAD too. Because if it needs to jump over something, it will wait 5 seconds to jump. So, I shall make it .25 seconds and use some handy-dandy globals to remove some lag. :D

I haven’t had this problem before but I’ll try it with my scripts. I hope people use this in zombie games. Now I can help my buddies without getting attacked instantly. I get maybe 2 – 5 seconds to kill it! :D

this is awesome but what about 20 zombies you can get one too chase that person but how do you get the rest of 19 zombies to chase that person too alsoi how do you make yourown gunn and your own zombie

is there a way to override the default lowest-possible delay time? what i’m trying to do mostly relates to being able to tween a GUI object’s transparency, and 1/30 second doesn’t look like it’s smooth enough.

That’s impossible. Use your common sense. wait() runs at the frame-rate. You can’t just say “I want the game to go twice as fast”, the reason wait() isn’t running quickly enough is your processor isn’t fast enough to process the action fast enough (Or in the case of a non-local script, roblox’s servers)

Hmm
Zombies…
Roblox’s Typical zombies are have brown chestpalte and brown legs and green head and green arms…
What Changes Doing in The Stamper Zombie…
I CANT WAITTTTTTT

Ideas: We have a Zombie Hat Using this OR
Make a New Meshes [like terordactyl]Moving and atacking…
We Know it Easter zombies Are Stupid, they says “BLOAAHHRGH BLUULUARGHHH BLUUUUGH”
They Make A New Sound I Think…
And They Useful in stamper tool+with a cage xd

findClosestEnemy() would simply return as the closest enemy the one closest to a specific point – you solve this by having the script on every zombie to track from a position relative to them(say, closest to that zombie’s torso for instance)

Makes sense, but being wise with wait()s isn’t going to make every game out there not-laggy. My game lags because of physics. Now if it were possible to somehow downgrade the quality of physics, make it be less precise, that could maybe help also.

firing the function every time the zombie moved would cause bugs, and also be very inefficient(the events pretty much fire every frame, which means that it will be just as worse as a simple no argument wait() function call.

Weird, I never get lag anywhere even with infinite loops waiting only 0.0000000001 seconds (the wait time my zombies normally use for both ray-casting, interpolated path finding, and enemy tracking) per cycle.