Reducing Lag
Does your map lag a lot, or do you get connection splits? This tutorial will teach you how to fix all this, and help to make your map run smoothly.
1. Map Initialization Lag
Ever have players almost lagging out at map initialization? These may be some of the causes:
A. Unit & Hero Creation
Everytime you create a hero or unit, the game has to load all of the unit's attributes; it's abilities, model(s), and attributes. This problem can be solved by Preloading.
B. Massive Amounts of Code
Sometimes if you do too much at the map initialization, it will lag and the player will be unable to look around the map (as they usually do as soon as the game starts) and see the game's environment, and see what they are supposed to do.
You can fix this by adding a short cinematic, say 5-10 seconds, and then during that time, set all the variables. Even a tiny amount of waits can make a huge difference.
C. Loading the Map
The other players lag may also be because of how large your map is. If your map is Epic, or Large sized, you may want to add a loading time at the beginning of the map, just so players can load everything that is preplaced, and the models.
2. Game Lag
As the game progresses, does your map seem to get laggier, and laggier? It may be from one of the following causes:
A. Memory Leaks
a. Removing GUI Leaks
Did you know that every time you use a "Pick every Unit in..." or a "Create Units at Location" that you create a memory leak? These are the biggest cause for in-game lag. There are many variables that leak:
Points, Unit Groups, Player Groups, Special Effects, Lightning Effects, Floating Text, and Countdown Timers.
To remove these memory leaks, every time that you use any of these variable types in a line of GUI, you must set a variable to it, and then use custom script/JASS to remove them.
Code:
Events
Unit - A unit enters Region 0001 <gen>
Conditions
Actions
Unit - Create 1 Footman for Player 1 (Red) at (Position of (Entering unit)) facing Default building facing degrees Your first step is to identify all the values that you can change, and their variable type.
In this trigger the digit 1 (An Integer), Footman (A Unit-Type), Player 1 (Red) (A player), Position of (Entering unit) (A Point), Entering unit (A Unit), and Default building facing degrees (A Real).
Your next step is to check to see which of these variables leaks.
1 (Integer) = Integers do not leak.
Footman (Unit-Type) = Unit-Types do not leak.
Player 1 (Red) (Player) = Players do not leak.
Position of (Entering unit) (Point)= Points do leak.
Entering unit (Unit)= Units do not leak.
Default buliding facing degrees (Real) = Reals do not leak
As you can see, I have found that one of my variables leaks; my point variable, Position of (Entering unit).
So what you must do, is you set a temporary variable to that point, BEFORE the line of text that has the memory leak, and use the variable as the point in the leaking line:
Code:
Events
Unit - A unit enters Region 0001 <gen>
Conditions
Actions
Set TEMP_Point = (Position of (Entering unit))
Unit - Create 1 Footman for Player 1 (Red) at TEMP_Point facing Default building facing degrees Now you have made it so that you can destroy the leak. Each leaking variable has its own custom script to destroy it however, so you must memorize these lines:
Points, Unit Groups, Player Groups, Special Effects, Lightning Effects, Floating Text, and Countdown Timers::
Code:
Custom script: call RemoveLocation (udg_*Temp variable name here*)
Custom script: call DestroyGroup (udg_*Temp variable name here*)
Custom script: call DestroyEffect (udg_*Temp variable name here*)
Custom script: call DestroyLightning (udg_*Temp variable name here*)
Custom script: call DestroyTextTag (udg_*Temp variable name here*)
Custom script: call DestroyTimer (udg_*Temp variable name here*)
For the Special Effect, Blizzard already created a Line that destroys it:
Code:
Special Effect - Destroy (Last created special effect)
You may want to watch out for the tricky leaks, such as this double point location leak:
Code:
Events
Unit - A unit enters Region 0001 <gen>
Conditions
Actions
Unit - Create 1 Footman for Player 1 (Red) at ((Position of (Entering Unit)) offset by 50 towards 90 degrees) facing Default building facing degrees It looks like one leak, right? But there are actually 2 leaks here; Position of (Entering unit) leaks, but so does the point created by offsetting it. You would take care of this kind of a leak like this:
Code:
Events
Unit - A unit enters Region 0001 <gen>
Conditions
Actions
Set TEMP_Point = Position of (Entering unit)
Set TEMP_Point2 = (TEMP_Point) offset by 50 towards 90 degrees
Unit - Create 1 Footman for Player 1 (Red) at TEMP_Point2 facing Default building facing degrees
call RemoveLocation(udg_TEMP_Point)
call RemoveLocation(udg_TEMP_Point2) Another type of variable that leaks is a Region, but unless the region is not a default region (Playable Map Area), or a Preplaced region (Region XXXX <gen>), it will not leak. However the custom script to destroy a region is:
Code:
Custom script: call RemoveRect(udg_*Temp variable name here*)
This is how it would be a leak:
Code:
Events
Unit - A unit enters Region 0001 <gen>
Conditions
Actions
Unit - Create 1 Footman for Player 1 (Red) at (Center of (Region (100.00 200.00 300.00 400.00))) As you can see this creates a region (Anything you have not already preplaced, leaks), AND a point. You would do the same thing as with the double point leak... destroy it, setting the variables to the insides first.
You may also be creating leaks if you are using locals in Jass, if you haven't nulled all local variables.
b. Nulling Local Variables
Just like not removing a location can leak, leaving any local handle variable with a value will cause a leak. To fix this, you have to nullify it.
A handle variable includes every single type of variables, except boolean, integer, real, and string, although string still leaks if not nullified.
So, basically if you have any functions that have a part in them that starts out like this:
local VARIABLETYPE NAME , it is creating a local, and if it's not an integer real or boolean, it needs to be nullified like this:
set NAME = null
or, for strings:
set NAME = ""
B. Trigger Enhanced Spells
Even if all of your leaks are taken care of, there still may be lag from trigger enhanced spells.
Most triggered spells will not create lag, but if it uses any Periodic events with it happening every 0.03 seconds or so, it can get laggy.
Here are some tips to keep your map as lag-less as possible
-Use as few periodic triggered spells as you can.
-Try to only have a few units using periodic triggered spells at a time; this may include only letting heroes have these kinds of abilities, if you have tons of regular units.
-Try having your spell JASS enhanced, and making it so it will run as quickly as possible, including removing useless BJ functions, and fixing the stupid GUI generated code.
-Try and see if there is any way you can have your ability made using regular abilities.
-Don't use massive amounts of Special Effects. They are laggy, and projectile like ones can be done by moving a unit with the model of the Special Effect.
-Usually, for a slide effect, 0.04 or 0.03 is smooth enough. 0.02, and 0.01 are extremely quick, and should almost never be used.
C. Periodic Events
Periodic events are extremely helpful. They can be used to trigger events very often. However, they can be misused if triggered too often.
Before setting how often the event will be triggered, ask yourself... Is my trigger going to do tons of stuff, or just a few minor things, like setting a variable?
For example, you wouldn't want a periodic trigger that creates a unit every 0.10 seconds, unless you were to only be having the trigger on for a few seconds. You wouldn't want 10 units being created every second, for the duration of the game, just as much as you wouldn't want a trigger that checks the hp of every single unit on the map, unless your map is small, with around 1-60 units.
Of course, if you're just setting an integer to itself + 1, you'd be fine with doing it every 0.01 seconds. There's almost no lag in that, and it consumes almost no CPU.
D. Massive Amounts of Objects
Having lots of units, doodads, special effects, and unneeded destructibles can be laggy too. Try to cut down on the amount you have on the map at any one time. For example, spawning 50 units or so all at one time can be very laggy, or even having too many on the map at one time. If you have hundreds and hundreds of grass doodads in a small place, it can cause lag. Special effects can be very laggy, especially if they are all on your screen at once. And lastly, having tons of destructibles on the map can lag.
If you're waaay over the limit of destructibles, and are using the No Limits tool, then try and cut down on the amount. Try and make all of your units more expensive, or stronger, and cut down on the amount of units you can get. Try and use dummy units with the same model as the SFX you are using, and moving them around to create the same effect. And try and use as few doodads in an area as you can, while still creating the same effect.
3. PreLoading
A. Units
Again, everytime a unit or hero is created, the game has to load the unit. You can reduce the in-game lag by preplacing all the units, and as soon as the game starts, remove the units. Even dummy casters should be preloaded, otherwise when the first time an ability is cast, it will lag.
B. Abilities
If you add any abilities to units, then you should also create a special unit, that already has the abilities, just for preloading. Just preplace this unit, and remove it as soon as the map initializes. Make sure you preload spellbooks, as they will lag the most if not preloaded.
4. Optimization Tools
A. Loading Times
All this preloading, and having everything already on the map will cause the map to take longer to load. This can be solved by using an optimization tool, such as the Widgetizer.
The Widgetizer is a tool specially designed to reduce loading time and make your map run a bit faster. All you must do is download the tool, open your map with it, and save it as the filename you will be using to host it, under the downloaded maps area. (Make sure your original map isn't under there, so you don't get confused when hosting it, as the maps will have the same name still). Your map may get bigger, but at least it'll load faster.
What the widgetizer actually does *Thanks to SFilip for this section*
All Warcraft's original object data (such as a footman, knight etc.) is actually stored inside SLK files in the MPQ. When you create something custom you will add it to a special file inside your map which needs to be converted and initialized while the map is loading along with all the SLK files even if you don't use something there. The widgetizer simply directly converts all the custom data intro SLK files thus removing any units/abilities/whatever you haven't used, which can greatly reduce your map's loading time. Yet the problem is that SLK files are larger and they need to contain units even if you haven't changed them at all, so this might increase your map's size.
B. Script Optimization
Thankfully, instead of removing all useless BJ functions, and making your script better yourself, Vexorian created the Map Optimizer, which will automatically go through your script and do it for you.
This really helps increase the speed of your map, and it can also remove some of your memory leaks for you.
Another useful tool to help optimize and clean leaks is Im_On_56k's Leak Check v2 it is a tool that will help show you where some of your leaks are in your GUI script.
~Super Credits to Dfett.
Hope you enjoy it :happy8se: