- Joined
- Mar 27, 2012
- Messages
- 3,232
One of the main things that makes big maps lag is inefficient use of the object editor. This tutorial is meant to bring out some things that can be used to prevent that. This tutorial is not limited to object editor stuff, but it somewhat focuses on it.
Common mistake 1:
Making an ability with 100 levels can be all fine and dandy, but lets imagine that each ability level takes 0.05 seconds to load. Quite little time, isn't it? But now suddenly your map loads 5 seconds longer from just 1 ability.
This is not a real life example, but it can be used to show the difference.
This is all because in any practical way if you make an ability with lots of levels, then it will have many purple fields.
Note that number values are very cheap, as seen in Benchmarks.
Now imagine what would happen if you made an ability with 10 000 levels? You can try it out, but be warned that it will lag the editor(and increase loading times).
I used to use 100-level abilities for making units gain combat experience. So that a unit with critical strike ability would have a greater chance to crit when it actually has been in a fight.
The solution to this is coded criticals.
Note that this is not an easy solution(aww, triggers...), but it saves huge amounts of power.
This can be applied to any stat. I just used critical hits as an example. Due to numbers being cheap you do not need such system for criticals, you only need to avoid having lots of text fields(only create text for the first field).
Changing stats such as health can be tricky, that's why you should combine the previous approach with a Bonusmod system.
If you use a custom editor such as JNGPE, then you can even make hero units out of non-heroes and the other way around, without using purple fields. On highly customized heroes this might even be worth it if you know a non-hero unit similar to your hero idea.
*When one of the text fields is empty, then the editor uses the text from the previous field, if the previous is also empty, then it goes one more step back, and so on.
*Always keep brush list disabled. It hasn't got anything to do with loading times, but it makes mapping much faster.
Widgetizing is not a mistake, but a way of optimizing the map. Essentially it makes the map use different base files(slk/txt), which simply load a lot faster due to being in a different format.
One of the limitations of widgetizing is that abilities are limited to 3 levels(no room in the tables).
In a sense the widgetizer fixes one of the mistakes that blizzard made.
Widgetizer
Widgetizing has been told to decrease loading times by up to 80%, but increases map size.
However, note that widgetizing can cause crashes when you play a non-widgetized map right after playing a widgetized map.
Typically the game loads things only when it needs to. Things can be loaded before they are really needed by placing them on the map or though a special JASS function.
This example preloads the wisp model:
The Preload function is typically used in melee games to prevent lag when a new unit type appears or some spell is cast for the first time.
Anything that happens during map initialization, including creation of preplaced units, makes the loading time longer, so it's better to create things after the map has loaded.
Models are loaded when they first appear.
Abilities are loaded the first time they are given to a unit.
This means that if you have an ability with 9999999999999999999999 levels and there's a preplaced unit that has it, it will make the loading time very long.
However, if you create the unit just 0.01 seconds after loading, it instead creates a huge lag spike after the game starts.
When you have a map with lots of abilities it's reasonable to preload everything over a long time so players won't notice any lag.
Preloading is useful because it lets you prevent random lag spikes by making them happen at a specific time.
Testmap with 1 custom critical strike(neutral)
Test1: No purple fields - 4 seconds
Test2: 101 purple fields - 4 seconds
Test3: 1001 purple fields - 4 seconds
Test4: 3001 purple fields - 4 seconds
On each of those tests there was 1 integer field and the rest were reals. There might have been up to a 0.5 second loading time difference, but I consider it insignificant, considering the amount of fields.
Test5: 6001 purple fields - 35 seconds.
On this test I filled 3000 text fields. Elseway it's like test 4.
Test6: 101 purple fields - 8 seconds.
This time it was the levels field and 100 tooltip fields.
Quite apparently strings take way more time to load than reals.
Testmap with 1 custom Raise Dead
Test1: 1001 purple fields - 8 seconds
1000 of the fields are unittype fields.
Apparently unittype fields are somewhat costly. It seems that a unittype field is a string with 4 letters.
The reason to strings/unittypes being expensive seems to be that while every number variable is 32 bits a string is 32 for every letter.
It also seems that it has something to do with strings beings processed in an inefficient manner.
Whenever you change something in the object editor it is written down. The base values are all unchangeable. What the editor really does is create a new unit and write down how it is different from the base unit.
Purple color marks the fields that have been changed and thus, are written into the map file.
Purple color marks the fields that have been changed and thus, are written into the map file.
Whatever you do, one thing is for certain. You can only avoid purple fields if you are making a melee map.
What you can do, however, is use the purple fields wisely.
What you can do, however, is use the purple fields wisely.
Common mistake 1:
Making an ability with 100 levels can be all fine and dandy, but lets imagine that each ability level takes 0.05 seconds to load. Quite little time, isn't it? But now suddenly your map loads 5 seconds longer from just 1 ability.
This is not a real life example, but it can be used to show the difference.
This is all because in any practical way if you make an ability with lots of levels, then it will have many purple fields.
Note that number values are very cheap, as seen in Benchmarks.
Now imagine what would happen if you made an ability with 10 000 levels? You can try it out, but be warned that it will lag the editor(and increase loading times).
Does each level really make a considerable difference ingame?
What is the lowest amount of levels that this ability must have.
What is the lowest amount of levels that this ability must have.
I used to use 100-level abilities for making units gain combat experience. So that a unit with critical strike ability would have a greater chance to crit when it actually has been in a fight.
The solution to this is coded criticals.
Note that this is not an easy solution(aww, triggers...), but it saves huge amounts of power.
- Get a damage detection system
- Get a unit indexer
- Create a variable array for the critical chance of units(preferrably integer, because integers are less expensive than reals. Not that it matters that much. )
- Every time a unit deals damage check if it is allowed to have critical strikes(if it has ability). If it is, then add some amount to critical hit chance
Changing stats such as health can be tricky, that's why you should combine the previous approach with a Bonusmod system.
If you use a custom editor such as JNGPE, then you can even make hero units out of non-heroes and the other way around, without using purple fields. On highly customized heroes this might even be worth it if you know a non-hero unit similar to your hero idea.
*When one of the text fields is empty, then the editor uses the text from the previous field, if the previous is also empty, then it goes one more step back, and so on.
*Always keep brush list disabled. It hasn't got anything to do with loading times, but it makes mapping much faster.
Widgetizing is not a mistake, but a way of optimizing the map. Essentially it makes the map use different base files(slk/txt), which simply load a lot faster due to being in a different format.
One of the limitations of widgetizing is that abilities are limited to 3 levels(no room in the tables).
In a sense the widgetizer fixes one of the mistakes that blizzard made.
Widgetizer
Widgetizing has been told to decrease loading times by up to 80%, but increases map size.
However, note that widgetizing can cause crashes when you play a non-widgetized map right after playing a widgetized map.
A lot of the loading time can be taken up by various things that happen at initialization. Some of those things can be done at other times though.
How it's typically done:
How it's typically done:
-
Trigger
-
Events
- Map initialization
- Conditions
-
Actions
- -------- Doing stuff here --------
-
Events
-
Trigger
-
Events
- Time - Elapsed game time is 0.01 seconds
- Conditions
-
Actions
- -------- Doing stuff here --------
-
Events
Typically the game loads things only when it needs to. Things can be loaded before they are really needed by placing them on the map or though a special JASS function.
This example preloads the wisp model:
JASS:
call Preload( "units\\nightelf\\Wisp\\Wisp.mdx" )
Anything that happens during map initialization, including creation of preplaced units, makes the loading time longer, so it's better to create things after the map has loaded.
Models are loaded when they first appear.
Abilities are loaded the first time they are given to a unit.
This means that if you have an ability with 9999999999999999999999 levels and there's a preplaced unit that has it, it will make the loading time very long.
However, if you create the unit just 0.01 seconds after loading, it instead creates a huge lag spike after the game starts.
When you have a map with lots of abilities it's reasonable to preload everything over a long time so players won't notice any lag.
Preloading is useful because it lets you prevent random lag spikes by making them happen at a specific time.
Testmap with 1 custom critical strike(neutral)
Test1: No purple fields - 4 seconds
Test2: 101 purple fields - 4 seconds
Test3: 1001 purple fields - 4 seconds
Test4: 3001 purple fields - 4 seconds
On each of those tests there was 1 integer field and the rest were reals. There might have been up to a 0.5 second loading time difference, but I consider it insignificant, considering the amount of fields.
Test5: 6001 purple fields - 35 seconds.
On this test I filled 3000 text fields. Elseway it's like test 4.
Test6: 101 purple fields - 8 seconds.
This time it was the levels field and 100 tooltip fields.
Quite apparently strings take way more time to load than reals.
Testmap with 1 custom Raise Dead
Test1: 1001 purple fields - 8 seconds
1000 of the fields are unittype fields.
Apparently unittype fields are somewhat costly. It seems that a unittype field is a string with 4 letters.
The reason to strings/unittypes being expensive seems to be that while every number variable is 32 bits a string is 32 for every letter.
It also seems that it has something to do with strings beings processed in an inefficient manner.
Attachments
-
Purple Field Testmap1.w3x6.5 KB · Views: 216
-
Purple Field Testmap2.w3x7 KB · Views: 190
-
Purple Field Testmap3.w3x12.1 KB · Views: 194
-
Purple Field Testmap4.w3x23.3 KB · Views: 199
-
Purple Field Testmap5.w3x82.3 KB · Views: 194
-
Purple Field Testmap6.w3x81.5 KB · Views: 194
-
Purple Field Testmap7.w3x9 KB · Views: 208
Last edited: