• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

About the destruction non-variable groups

Level 12
Joined
Jul 5, 2014
Messages
551
I have a whole lotta groups like that:

  • Unit Group - Pick every unit in (Units in First conflict <gen>) and do (Actions)
    • Loop - Actions
      • Unit - Pause (Picked unit)
Groups like that serve as a timer so when the player gets near them, the group gets unpaused, so the player can witness the fighting. In these cases, I know the "set bj_wantDestroyGroup = true" is used to eliminate leaks. However, is there any reason NOT TO destroy a group like that? In my case, the units in the region are picked again for unpausing but I'm not sure whether it doubles the group (despite it picks the exact same units), so technically without the variable, I can't access to the already picked group. Because further reference to the group "(Units in First conflict <gen>)" will have nothing to do with the already included units, rather, it will simply check who's currently in the "first conflict region". So, I wonder if there is any reason (apart from someone wanting to pile leaks) not to destroy the group after the above trigger?
 
Level 20
Joined
Jan 3, 2022
Messages
364
set bj_wantDestroyGroup = true
Depends on the function if it will do this.
It is fine to create a group at the start of the map (after units were spawned) and never remove it. It would not be a "leak" if you know, you are going to use this group in the future.

Consider this example: a looot units in a group, used once at start and then at the final cinematic of the map. Technically you don't need this group to exist for a long period of time, but it's such an insignificant load, it would be more tedious to delete and recreate it.

The problematic leaks in WC3 are those that run on attack or frequent timers and accumulate the lost pointers/unremoved objects. The most prominent offenders are GUI multiboard text set, special effects not being cleared, temporary groups, locations, player groups. From your description it seems you could reuse this group? Then do it. Instinctively I would prefer object reuse and long life objects compared to new-remove-new cycles.
 
Level 12
Joined
Jul 5, 2014
Messages
551
Depends on the function if it will do this.
It is fine to create a group at the start of the map (after units were spawned) and never remove it. It would not be a "leak" if you know, you are going to use this group in the future.

Consider this example: a looot units in a group, used once at start and then at the final cinematic of the map. Technically you don't need this group to exist for a long period of time, but it's such an insignificant load, it would be more tedious to delete and recreate it.

The problematic leaks in WC3 are those that run on attack or frequent timers and accumulate the lost pointers/unremoved objects. The most prominent offenders are GUI multiboard text set, special effects not being cleared, temporary groups, locations, player groups. From your description it seems you could reuse this group? Then do it. Instinctively I would prefer object reuse and long life objects compared to new-remove-new cycles.
Again, the groups I'm talking about refer to multiple non-variable groups.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Again, the groups I'm talking about refer to multiple non-variable groups.
You're leaking a Unit Group every single time you see these words:
  • (Units in First conflict <gen>)
The only way the game can interact with multiple units at a time is by creating a Unit Group object to contain those units. That object can become a memory leak if you do not Destroy it. The only way to Destroy it is by storing it in a variable and then running the appropriate Custom Script.

Here's an example of creating 2 memory leaks and 1 potential memory leak:
  • Set Variable TempGroup = (Units in RegionA <gen>)
  • Set Variable TempGroup = (Units in RegionB <gen>)
  • Set Variable TempGroup = (Units in RegionC <gen>)
  • Each time I Set the TempGroup variable the game has to create a brand new Unit Group object.
  • It then fills this new object with any units that match the given filter. In this case we told it to look for any units in a particular region.
  • It then tracks that object by using the TempGroup variable as a reference to it.

The reason it's only 2 memory leaks is because I still have a reference to the 3rd Unit Group object that I created (the very last one). I can now do this to destroy it and clean up it's memory leak:
  • Set Variable TempGroup = (Units in RegionA <gen>)
  • Set Variable TempGroup = (Units in RegionB <gen>)
  • Set Variable TempGroup = (Units in RegionC <gen>)
  • Custom script: call DestroyGroup(udg_TempGroup)
Understand that this only cleans up the very last object, since that's the last thing I told TempGroup to keep track of. The two objects created before it are now considered permanent leaks - I literally cannot Destroy them.

But the rule to avoid this type of leak is simple -> Set, Use, Remove:
  • Set Variable TempGroup = (Units in RegionA <gen>) /// SET
  • Unit Group - Pick every unit in TempGroup and do (Actions) /// USE
    • Loop - Actions
      • ...
  • Custom script: call DestroyGroup(udg_TempGroup) /// REMOVE
Follow that pattern and you'll avoid most memory leaks.
 
Last edited:
Level 12
Joined
Jul 5, 2014
Messages
551
You're leaking a Unit Group every single time you see these words:
  • (Units in First conflict <gen>)
The only way the game can interact with multiple units at a time is by creating a Unit Group object to contain those units. That object can become a memory leak if you do not Destroy it.

Here's an example of creating 2 memory leaks and 1 potential memory leak:
  • Set Variable TempGroup = (Units in RegionA <gen>)
  • Set Variable TempGroup = (Units in RegionB <gen>)
  • Set Variable TempGroup = (Units in RegionC <gen>)
Each time I Set the TempGroup variable the game has to create a brand new Unit Group object.

It then fills this new object with any units that match the given filter. In this case we told it to look for any units in a particular region.

It then tracks that object by using the TempGroup variable as a reference to it.

Each object contains it's own list of units and acts as it's own separate entity.

The reason it's only 2 memory leaks is because I still have a reference to the 3rd Unit Group object that I created (the very last one). I can now do this to destroy it and clean up it's memory leak:
  • Set Variable TempGroup = (Units in RegionA <gen>)
  • Set Variable TempGroup = (Units in RegionB <gen>)
  • Set Variable TempGroup = (Units in RegionC <gen>)
  • Custom script: call DestroyGroup(udg_TempGroup)
Understand that this only cleans up the very last object, since that's the last thing I told TempGroup to keep track of. The two objects created before it are now considered permanent leaks - I literally cannot Destroy them.

But the rule to avoid this type of leak is simple -> Set, Use, Remove:
  • Set Variable TempGroup = (Units in RegionA <gen>) /// SET
  • Unit Group - Pick every unit in TempGroup and do (Actions) /// USE
    • Loop - Actions
      • ...
  • Custom script: call DestroyGroup(udg_TempGroup) /// REMOVE
Follow that pattern and you'll avoid most memory leaks.
So, in other words, there is no reason to keep around non-variable associated groups, right? Because they just become unaccessible and cause leaks like your tempgroup example.

Would that be a solution:

  • Actions
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (Units in First conflict <gen>) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (Units in Second conflict <gen>) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (Units in Thirs conflict <gen>) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
And so on.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
So, in other words, there is no reason to keep around non-variable associated groups, right? Because they just become unaccessible and cause leaks like your tempgroup example.
Yes, that's basically it. But I would say it the other way around, there's a reason to use variables because they allow you to clean up your memory leaks. If you don't use variables then you cannot clean up the leaks.

Would that be a solution:

  • Actions
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (Units in First conflict <gen>) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (Units in Second conflict <gen>) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (Units in Thirs conflict <gen>) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
And so on.
^ This works as well, you're telling the game that you want to destroy the next Unit Group object that's created. Then you immediately create an object which is then automatically destroyed. Most types of leaks don't have a special secondary option like this, though.
 
Level 12
Joined
Jul 5, 2014
Messages
551
Yes, that's basically it. But I would say it the other way around, there's a reason to use variables because they allow you to clean up your memory leaks. If you don't use variables then you cannot clean up the leaks.


^ This works as well, you're telling the game that you want to destroy the next Unit Group object that's created. Then you immediately create an object which is then automatically destroyed. Most types of leaks don't have a special secondary option like this, though.
Great, thanks. Without the bj, I'd probably have to use variables but I wasn't sure that this spamfest with groups and bj won't cause trouble. I guess technically it would work with a "tempgroup" variable although it would also have a spamfest of clearing up.

By the way, if I have a group, say "tempgroup" and I remove units manually, will a refill cause leak? I'm guessing it would threw a variable but I'm not sure if "pick every unit in the region and add them to tempgroup" would.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
By the way, if I have a group, say "tempgroup" and I remove units manually, will a refill cause leak? I'm guessing it would threw a variable but I'm not sure if "pick every unit in the region and add them to tempgroup" would.
Removing all of the units from a Unit Group object does NOT destroy the object. What you described would probably create another leak - although it does depend on how you do it.

For example, these Add/Remove actions allow you to manage a Unit Group object rather than creating a new object:
  • Unit Group - Add (Triggering unit) to SomeGroup
  • Unit Group - Remove (Triggering unit) from SomeGroup
It's possible to dedicate a Unit Group variable to a specific job and manage it throughout the game without ever having to worry about memory leaks:
  • Events
    • Time - Elapsed game time is 0.00 seconds
  • Conditions
  • Actions
    • Set Variable Player1_Units = (Units owned by Player 1 (Red))
  • Events
    • Unit - A unit Enters (Playable map area)
  • Conditions
    • (Owner of (Triggering unit)) Equal to Player 1 (Red)
  • Actions
    • Unit Group - Add (Triggering unit) to Player1_Units
  • Events
    • Unit - A unit Dies
  • Conditions
    • (Owner of (Triggering unit)) Equal to Player 1 (Red)
  • Actions
    • Unit Group - Remove (Triggering unit) from Player1_Units
^ The above example allows us to track all of Player 1's units throughout the entire game. You never have to worry about memory leaks because you avoid the creation of a new Unit Group object.

At any point in time you can do this without issues:
  • Unit Group - Pick every unit in Player1_Units and do (Actions)
    • Loop - Actions
Just remember that units which get "Removed from the game" never fire the "A unit Dies" Event so they could potentially remain in the Unit Group as a leak. It's fairly easy to avoid that issue, though.
 
Level 12
Joined
Jul 5, 2014
Messages
551
Removing all of the units from a Unit Group object does NOT destroy the object. What you described would probably create another leak - although it does depend on how you do it.

For example, these Add/Remove actions allow you to manage a Unit Group object rather than creating a new object:
  • Unit Group - Add (Triggering unit) to SomeGroup
  • Unit Group - Remove (Triggering unit) from SomeGroup
It's possible to dedicate a Unit Group variable to a specific job and manage it throughout the game without ever having to worry about memory leaks:
  • Events
    • Time - Elapsed game time is 0.00 seconds
  • Conditions
  • Actions
    • Set Variable Player1_Units = (Units owned by Player 1 (Red))
  • Events
    • Unit - A unit Enters (Playable map area)
  • Conditions
    • (Owner of (Triggering unit)) Equal to Player 1 (Red)
  • Actions
    • Unit Group - Add (Triggering unit) to Player1_Units
  • Events
    • Unit - A unit Dies
  • Conditions
    • (Owner of (Triggering unit)) Equal to Player 1 (Red)
  • Actions
    • Unit Group - Remove (Triggering unit) from Player1_Units
^ The above example allows us to track all of Player 1's units throughout the entire game. You never have to worry about memory leaks.

At any point in time you can do this without issues:
  • Unit Group - Pick every unit in Player1_Units and do (Actions)
    • Loop - Actions
Just remember that units which get "Removed from the game" never fire the "A unit Dies" Event so they could potentially remain in the Unit Group as a leak. It's fairly easy to avoid that issue, though.
So, the below option would fill up an empty Tempgroup without issues?

  • Custom script: set bj_wantDestroyGroup = true
  • Unit Group - Pick every unit in (Units in First conflict <gen>) and do (Actions)
    • Loop - Actions
      • Unit Group - Add (Picked unit) to TempGroup
 
Top