• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Improve Missile Movement - Less lagg possible?

Status
Not open for further replies.

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
I use this trigger to move missiles

  • Unit Move
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Move and do (Actions)
        • Loop - Actions
          • Set TempPoint1 = (Position of (Picked unit))
          • Set TempPoint2 = (TempPoint1 offset by 50.00 towards (Facing of (Picked unit)) degrees)
          • Unit - Move (Picked unit) instantly to TempPoint2
          • Custom script: call RemoveLocation (udg_TempPoint1)
          • Custom script: call RemoveLocation (udg_TempPoint2)
      • Unit Group - Pick every unit in MoveLaser and do (Actions)
        • Loop - Actions
          • Set TempPoint1 = (Position of (Picked unit))
          • Set TempPoint2 = (TempPoint1 offset by 45.00 towards (Facing of (Picked unit)) degrees)
          • Unit - Move (Picked unit) instantly to TempPoint2
          • Custom script: call RemoveLocation (udg_TempPoint1)
          • Custom script: call RemoveLocation (udg_TempPoint2)
Is there any way of optimizing it, so it will make hundreds of missiles lagg less? Or won't JASS script make any big difference in this case?

Since I don't know, I have to ask!
 
Level 17
Joined
Apr 13, 2008
Messages
1,597
The code can't be optimized further, but I believe you could make a different, less resource-eating algorythm for this problem.
So why don't you post what exactly you want to do with this trigger and we could see if we can figure out a better method than moving your units every 0.05 seconds.
 
  • Like
Reactions: TKF

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
The code can't be optimized further, but I believe you could make a different, less resource-eating algorythm for this problem.
So why don't you post what exactly you want to do with this trigger and we could see if we can figure out a better method than moving your units every 0.05 seconds.

Hmm, to bad it cannot be optimized further, and this is the least resource-eating trigger i can make, but if increasing the timer helps against the lagg, I will do it, but I it cannot be more than 0.08 sec, cuz the missiles will then "jump" through the shields.
 
Level 17
Joined
Apr 13, 2008
Messages
1,597
Yup. Since you could just make these missiles units with very high movement speed. And order them only ONCE to move or attack or whatever you want to do with them when they are "launched".
To prevent players control them you could just make a trigger:

E:player selects a unit
C:Unit is a YourMissile'sUnitType
A:Make player deselect unit.

I don't know how fast the game deselects the units, so the player might can give it instructions if he has cobra-like reflexes. But you could just throw up another 3-liner to prevent further player interference.
But it's just an example, tell us what your trigger is supposed to do and we might be able to figure out something better together.
 

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
Well, I use selectable missiles which is not owned by the player who launch them, but each and one of these missiles has a custom value which is used as identification of the killer.

They get killed by a shield which has phönix fire ability, or other anti missile weapons. So they can't have locust ability

no need for anti selection triggers or detection system for the missiles. The expiration timer decides when the missiles dies. Before firing, it head towards a random enemy structure.


The purpose of the trigger is simple. Move missiles. emperors_dust's first response was my only answer to my question that I did seek.
 
Level 17
Joined
Apr 13, 2008
Messages
1,597
Hmm, okay. Well I guess there's a reason why you want to move them the way you do.
Well, turning this into a JASS script might make it run faster by a few percent. If you turn this whole trigger into custom text and post it I'll see if it can be done or not, but I'm too lazy to create this in gui ^^
 
Last edited:
Level 9
Joined
May 27, 2006
Messages
498
1. Your trigger leaks twice every 0,05 second... And thats probably the reason why the lag occurs. You should use set bj_wantDestroyGroup = true script placed right before Pick Unit Group action to remove those two leaks.
Example:
  • Actions:
    • Trigger - some actions...
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (blahblah)...
      • Unit - some actions...
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (blahblah)...
      • Unit - some actions...
2.
To prevent players control them you could just make a trigger:

E:player selects a unit
C:Unit is a YourMissile'sUnitType
A:Make player deselect unit.
Nonsense. Just add "Locust" ability to the missile-unit to make it uncontrollable/untargetable. It will still be able to move, attack, cast spells, just other units wont be able to damage it. You'll just have to change your system a bit to use anti-missiles to destroy rockets with this ability.
 
Level 9
Joined
May 27, 2006
Messages
498
Well, if the missiles have to be damaged by some kind of automatic missile turrets, then doing a deselect trigger is really the only option, thought...

(Altough i'd stay with the locust ability and making some triggers to fire turrets at it when it gets close enough...)
 
Level 23
Joined
Nov 29, 2006
Messages
2,482
1. Your trigger leaks twice every 0,05 second... And thats probably the reason why the lag occurs. You should use set bj_wantDestroyGroup = true script placed right before Pick Unit Group action to remove those two leaks.
Example:
  • Actions:
    • Trigger - some actions...
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (blahblah)...
      • Unit - some actions...
    • Custom script: set bj_wantDestroyGroup = true
    • Unit Group - Pick every unit in (blahblah)...
      • Unit - some actions...
2.
Nonsense. Just add "Locust" ability to the missile-unit to make it uncontrollable/untargetable. It will still be able to move, attack, cast spells, just other units wont be able to damage it. You'll just have to change your system a bit to use anti-missiles to destroy rockets with this ability.

I dont think that will do any difference in memory usage guys...
I mean, he has an event running every 0.05 seconds... Creating a unit group everytime, and then destroy it with intervals so small we wont notice it is just going to make the code slower.

Thats my point of view.
Right now his unit groups doesnt leak more than the fact that it is a unit group taking up some space from the memory. You see he already has a variable for each unit group.
Destroying them he has to set a new one...

Edit: When creating a new unit group locusts are not always added... For that he needs PurplePoots amazing Jass Locust codes.
 

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
The units are added in a different trigger which detects missiles being built. The move unit group is never empty through the entire game, so I don't see the necessaries with destroying the unit group, since the units isn't created in the same trigger.

IMO picking units from an existing group = creating new group for picked units = leak...
But i dont know, im just making never-released maps, not getting into technical details of WC3 :p
Are you sure about it. Does the unit group leak? But the trigger is only designed to work as a missile mover, I cannot recreate groups in this trigger.
 
Level 9
Joined
May 27, 2006
Messages
498
Look at second line of my post, i thought it tells clearly that im not sure if picking units from existing unit group leaks :p

But when you're picking units in range/region/whatever, not from group - this leaks for sure.

And anyway, you can test your trigger - place the leak-removing script before the two unit groups, then run your map and check if it works properly.
 
Level 9
Joined
Mar 25, 2005
Messages
252
Converted to jass your script looks like this:
JASS:
function Trig_Unit_Move_Func001A takes nothing returns nothing
    set udg_TempPoint1 = GetUnitLoc(GetEnumUnit())
    set udg_TempPoint2 = PolarProjectionBJ(udg_TempPoint1, 50.00, GetUnitFacing(GetEnumUnit()))
    call SetUnitPositionLoc( GetEnumUnit(), udg_TempPoint2 )
    call RemoveLocation(udg_TempPoint1)
    call RemoveLocation(udg_TempPoint2)
endfunction

function Trig_Unit_Move_Func002A takes nothing returns nothing
    set udg_TempPoint1 = GetUnitLoc(GetEnumUnit())
    set udg_TempPoint2 = PolarProjectionBJ(udg_TempPoint1, 50.00, GetUnitFacing(GetEnumUnit()))
    call SetUnitPositionLoc( GetEnumUnit(), udg_TempPoint2 )
    call RemoveLocation(udg_TempPoint1)
    call RemoveLocation(udg_TempPoint2)
endfunction

function Trig_Unit_Move_Actions takes nothing returns nothing
    call ForGroupBJ( udg_Move, function Trig_Unit_Move_Func001A )
    call ForGroupBJ( udg_MoveLaser, function Trig_Unit_Move_Func002A )
endfunction

//===========================================================================
function InitTrig_Unit_Move takes nothing returns nothing
    set gg_trg_Unit_Move = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic( gg_trg_Unit_Move, 0.05 )
    call TriggerAddAction( gg_trg_Unit_Move, function Trig_Unit_Move_Actions )
endfunction
from that I can tell you that it doesn't leak groups or anything else.

When you pick units in range and do actions to them in GUI a group is created and not destroyed unless you set bj_wantDestroyGroup to true before the action. If you already have a group a new one is not made so there won't be such a leak.

This is a bit more optimized:
JASS:
function Trig_Unit_Move_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+50.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+50.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Actions takes nothing returns nothing
    call ForGroup(udg_Move, function Trig_Unit_Move_Enum)
    call ForGroup(udg_MoveLaser, function Trig_Unit_Move_Enum)
endfunction

//===========================================================================
function InitTrig_Unit_Move takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.05, true, function Trig_Unit_Move_Actions)
endfunction
About the only change that affects performance in this is that I used reals instead of locations and inlined a few BJ functions. This could be further optimized by calling SetUnitX() + SetUnitY() instead of SetUnitPosition(), but doing so chrashes the map if the point is outside the map.
 
Last edited:
  • Like
Reactions: TKF

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
...
This is a bit more optimized:
JASS:
function Trig_Unit_Move_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+50.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+50.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Actions takes nothing returns nothing
    call ForGroup(udg_Move, function Trig_Unit_Move_Enum)
    call ForGroup(udg_MoveLaser, function Trig_Unit_Move_Enum)
endfunction

//===========================================================================
function InitTrig_Unit_Move takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.05, true, function Trig_Unit_Move_Actions)
endfunction
About the only change that affects performance in this is that I used reals instead of locations and inlined a few BJ functions. This could be further optimized by calling SetUnitX() + SetUnitY() instead of SetUnitPosition(), but doing so chrashes the map if the point is outside the map.

There's one problem. I have recently implemented a missile jamming system, so this will crash cuz the jammed missiles is often pointing outside the map sometimes.
 
Level 9
Joined
Mar 25, 2005
Messages
252
There's one problem. I have recently implemented a missile jamming system, so this will crash cuz the jammed missiles is often pointing outside the map sometimes.

It wont crash. I tested it. You are confusing SetUnitPosition with SetUnitX and SetUnitY. The latter two can cause a crash but not SetUnitPosition. In fact your original script uses SetUnitPositionLoc...
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Hm well, if that is the fact, that it creates a new group just for picking units... then yes

otherwise I wouldnt bother?.-.

Learn about pointers D:

Every time you declare a pointer (location variable, group varialbe, SFX variable etc) you create a object (location object, group object, SFX object etc) and the variable you declared is just pointing to that object.

This is why BEFORE nulling (only applies for locals), you must destroy the object (applies for every kind of variable in case it will be changed through the game, for example, a unit will die, in contrast to a invulnerable unit which will stay all the game), or else you will have no way to destroy it later, as the variable that "pointed" to it was nulled.

If from the start you are not attaching the object to any pointer, for example call SetUnitX(some_unit, GetRectCenter(some_rect) // I do not remember if this is the correct syntax - here you made a location object which holds the x/y of the center of the given rect, and yet it has no pointer.
This mean that after you got the value once you have no access to that location object and therefore it just steals your memory.
 
Level 5
Joined
Jan 15, 2007
Messages
199
Forgroups do not create another group, you wount need to do the 'set bj_wantDestroyGroup = true' .

Also, looping through each unit in a group is more efficient than using ForGroup afaik.
 
Level 9
Joined
Mar 25, 2005
Messages
252
Looping a group with 171 units 6000 times pauses my screen for ~19 seconds
Using ForGroup on a group with 171 units 6000 times pauses my screen for ~6 seconds.

Each looping and forgroup was initiated with an evaluate call to get past the op limit.
I also tested and made sure that both went through all the units by having counters in the loops (but I took them out for that test). I also assigned the looped unit to a global variable on each iteration. For the loop version this just ment set GU = u, but for the ForGroup version set GU = GetEnumUnit(). I did this to include that GetEnumUnit call in the ForGroup test to simulate practical uses.

In conclusion looping a group with FirstOfGroup sucks and has always sucked when it comes to performance. It is a retarded myth that it's the other way around.

Here's the code for the test which you can CnP to a map to see for yourself. As you will see I didn't recycle groups or do anything extraordinary. This is because no one else does either.
JASS:
scope XXA initializer init
    globals
        private unit GU
        private integer COUNTER
    endglobals
    private function loopTest takes group g returns nothing
        local unit u
        local group copy = CreateGroup()
        //call GroupAddGroup(g, copy)
        set bj_groupAddGroupDest = copy
        call ForGroup(g, function GroupAddGroupEnum)
        loop
            set u = FirstOfGroup(copy)
            exitwhen u == null
            //set COUNTER = COUNTER + 1
            set GU = u
            call GroupRemoveUnit(copy, u)
        endloop
        call DestroyGroup(copy)
        set copy = null
    endfunction
    private function callback takes nothing returns nothing
        set GU = GetEnumUnit()
        //set COUNTER = COUNTER + 1
    endfunction
    private function forTest takes group g returns nothing
        call ForGroup(g, function callback)
    endfunction
    private function init2 takes nothing returns nothing
        local integer i
        local group g = CreateGroup()
        call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, null)
        call TriggerSleepAction(1)
        call BJDebugMsg("Units in test group: "+I2S(CountUnitsInGroup(g))+".\r\nThat makes "+I2S(6000*CountUnitsInGroup(g))+" iterations per test.")
        call TriggerSleepAction(10)
        call BJDebugMsg("loopTest begins")
        set i = 6000
        set COUNTER = 0
        loop
            call loopTest.evaluate(g)
            exitwhen i == 0
            set i = i - 1
        endloop
        call BJDebugMsg("loopTest ends after "+I2S(COUNTER)+" iterations")
        call TriggerSleepAction(30)
        call BJDebugMsg("forTest begins")
        set i = 6000
        set COUNTER = 0
        loop
            call forTest.evaluate(g)
            exitwhen i == 0
            set i = i - 1
        endloop
        call BJDebugMsg("forTest ends after "+I2S(COUNTER)+" iterations")
        call TriggerSleepAction(5)
    endfunction
    private function init takes nothing returns nothing
        call init2.execute()
    endfunction
endscope
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
The reason people like the FirstOfGroup method is because it saves extra functions, and mucking about with passing your locals. It's generally accepted that ForGroup is faster, though I'm surprised it's that much faster (Although in reality you have to subtract about half that time, since you also are copying the group which takes a significant portion of the execution...)

Also, having set GU = u is a stupid operation increase in the FoG loop, since there would never be a reason to putting it there, and GetEnumUnit() should be compared to FoG itself.

I'll probably try it later, replacing the script with the following, to reduce the margin of error (This needs to assume g is global). I might also adapt it to fix the problem of the unnecessary margin of error due to copying the group, which in many cases wouldn't be done...

JASS:
scope XXA initializer init
    globals
        private unit GU
        private group g
        private integer COUNTER
    endglobals
    private function loopTest takes nothing returns nothing
        local unit u
        local group copy = CreateGroup()
        loop
            set u = FirstOfGroup(g)
            exitwhen u == null
            //set COUNTER = COUNTER + 1
            call GroupRemoveUnit(g,u)
            call GroupAddUnit(copy, u)
        endloop
        call DestroyGroup(g)
        set g = copy
        set copy = null
    endfunction
    private function callback takes nothing returns nothing
        set GU = GetEnumUnit()
        //set COUNTER = COUNTER + 1
    endfunction
    private function forTest takes nothing returns nothing
        call ForGroup(g, function callback)
    endfunction
    private function init2 takes nothing returns nothing
        local integer i
        set g = CreateGroup()
        call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, null)
        call TriggerSleepAction(1)
        call BJDebugMsg("Units in test group: "+I2S(CountUnitsInGroup(g))+".\r\nThat makes "+I2S(6000*CountUnitsInGroup(g))+" iterations per test.")
        call TriggerSleepAction(10)
        call BJDebugMsg("loopTest begins")
        set i = 6000
        set COUNTER = 0
        loop
            call loopTest.evaluate()
            exitwhen i == 0
            set i = i - 1
        endloop
        call BJDebugMsg("loopTest ends after "+I2S(COUNTER)+" iterations")
        call TriggerSleepAction(30)
        call BJDebugMsg("forTest begins")
        set i = 6000
        set COUNTER = 0
        loop
            call forTest.evaluate()
            exitwhen i == 0
            set i = i - 1
        endloop
        call BJDebugMsg("forTest ends after "+I2S(COUNTER)+" iterations")
        call TriggerSleepAction(5)
    endfunction
    private function init takes nothing returns nothing
        call init2.execute()
    endfunction
endscope
 
Level 9
Joined
Mar 25, 2005
Messages
252
Also, having set GU = u is a stupid operation increase in the FoG loop, since there would never be a reason to putting it there, and GetEnumUnit() should be compared to FoG itself.

If you can turn the results around by removing one read of a local from the other version then... well more power to you.
Also did you come to think of this: when you need to refer to each unit once (excluding the times the loop needs to do so) you need to call GetEnumUnit once, or refer to the variable 'u' once depending on the method used. That is what I tried to simulate in my test. Perhaps writing the unit into a local and using it a few times, as well as referring to the unit variable a few times in the other version might reflect reality more precicely, but I just don't see how that is going to make the difference.


Also in most cases where you don't need to copy the group you don't need a group in the first place either, since you can do your actions in the boolexpr you are using to get the units into the group. Don't forget to include that in your tests if you go as far as to not copy the group.


Can you tell me of what use it is to "save functions"? I don't really get that part.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
since you can do your actions in the boolexpr you are using to get the units into the group.
You wouldn't always do that for the same reason that you wouldn't always use ForGroup() over FirstOfGroup()

but I just don't see how that is going to make the difference.
I never said it would - I don't see a logical way FoG() could be the faster of the two either way, I'd just like to try to get a more accurate result. However, when you set a 100% useless variable 1026000 times, I think it just might make a difference, don't you?

EDIT: With my above code, ForGroup is ~1.5x as fast as FirstOfGroup.

However, I may remove the difference in copying completely.

We really should stopwatch this, though...
 
Level 9
Joined
Mar 25, 2005
Messages
252
However, when you set a 100% useless variable 1026000 times, I think it just might make a difference, don't you?

You just dont get it...

I understand why you don't want it there. But you can't seriously suggest that it doesn't reflect a real practical scenario when it is there.


oh and btw your definition of margin of error is imaginary

EDIT: continued
You wouldn't always do that for the same reason that you wouldn't always use ForGroup() over FirstOfGroup()
but this discussion isn't about those reasons
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
I understand why you don't want it there. But you can't seriously suggest that it doesn't reflect a real practical scenario when it is there.
If you needed it as a global, you would just completely remove the local in favor of it.

So yes, I can.

but this discussion isn't about those reasons
I know it isn't, but your definition of when just using the boolexpr from GroupEnum is not completely accurate (And thus, what is relevant for the test).

oh and btw your definition of margin of error is imaginary
What I meant was all the added garbage to the first test.
 
Level 23
Joined
Nov 29, 2006
Messages
2,482
May I interrupt?

So basically if I want to loop a group as fast as possible, and if I dont need any locals (which is handy for FirstOfGroup()), I can use ForGroup, without losing anything on it?

Oh and yea isnt this starting to get just a little offtopic?
 
Level 9
Joined
Mar 25, 2005
Messages
252
If you needed it as a global, you would just completely remove the local in favor of it.

So yes, I can.

I wasn't talking about the global write, I was talking about accessing the unit. Maybe this example that I had in mind when writing my test clears things up:
JASS:
//=====================================================
//    ForGroup
//
function GroupKillUnitsEnum takes nothing returns nothing
    call KillUnit(GetEnumUnit()) // GetEnumUnit is used once, like I did in my test.
endfunction
function GroupKillUnits takes group g returns nothing
    call ForGroup(g, function GroupKillUnitsEnum)
endfunction

//=====================================================
//    FoG loop
//
function GroupKillUnits takes group g returns nothing
    local unit u
    local group copy = CreateGroup()
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call KillUnit(u) // u is used once, like I did in my test.
        call GroupRemoveUnit(g,u)
        call GroupAddUnit(copy, u)
    endloop
    call DestroyGroup(g)
    set g = copy
    set copy = null
endfunction
The global writes that were in my test, but not here, were there because they were the lightest thing I could come up with that let me include the access of the looped units in the test.

You said that the one reading of the variable 'u' is 100% useless. How am I going to kill a unit without referring to it? Really useless garbage indeed.

And yes it is more common to set the result of GetEnumUnit to a local variable and use it instead, in which case the call to GetEnumUnit should be compared to the call to FirstOfGroup in the alternative, but that doesn't take this scenario away.

Oh and the write to the global unit was in both tests for a reason, so don't come saying that it is biased towards ForGroup anymore please.


I know it isn't, but your definition of when just using the boolexpr from GroupEnum is not completely accurate (And thus, what is relevant for the test).

See the 15th post in this thread. Now, are you still sure that GroupEnums aren't relevant when it comes to looping temporary groups?


unnecessary margin of error due to copying the group

If you let the FoG loop clear the group, your aren't testing what I was anymore. You aren't testing two scripts that have the exact same result, whereas I was, and more importantly you aren't testing the same thing I was. That doesn't fix any error. That tells you something else, about something else.


PS: I did one test that reflected one common scenario, that proved what I, and so many others already knew: ForGroup is significantly faster. Why would I have conducted more tests? Why would I have gone through different scenarios when it was apparent that the results would not change to the favor of the loser? Why would I care that much about some little detail that you seem to find extremely important, and for what reason? To prove that ForGroup isn't 2x+ faster but 1.5x+ faster? No thanks.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
PS: I did one test that reflected one common scenario, that proved what I, and so many others already knew: ForGroup is significantly faster. Why would I have conducted more tests? Why would I have gone through different scenarios when it was apparent that the results would not change to the favor of the loser? Why would I care that much about some little detail that you seem to find extremely important, and for what reason? To prove that ForGroup isn't 2x+ faster but 1.5x+ faster? No thanks.
Yes, ForGroup is significantly faster, but misrepresenting the speed (3x or so originally) can make people irrationally not use the best method for the situation.

See the 15th post in this thread. Now, are you still sure that GroupEnums aren't relevant when it comes to looping temporary groups?
I never said they weren't. I was saying that, for the same reasons as ForGroup, they aren't practical in many cases.

The global writes that were in my test, but not here, were there because they were the lightest thing I could come up with that let me include the access of the looped units in the test.
That only applies if you only do one operation given the units in the entire loop, which is rather too specific, and in which there are other reasons for which to not use FoG anyways.

You said that the one reading of the variable 'u' is 100% useless. How am I going to kill a unit without referring to it? Really useless garbage indeed.
No, I'm saying that an extra use in one test is biased.

Oh and the write to the global unit was in both tests for a reason, so don't come saying that it is biased towards ForGroup anymore please.
But in ForGroup there was no local write as well...

That's like saying the following are no different:

JASS:
globals
    integer X
endglobals

function Case1 takes nothing returns nothing
    local integer x = 5
    set X = x
endfunction

function Case2 takes nothing returns nothing
    set X = 5
endfunction


It seems like you're misinterpreting the greater part of what I'm saying =/
 
Level 9
Joined
Mar 25, 2005
Messages
252
Yes, ForGroup is significantly faster, but misrepresenting the speed (3x or so originally) can make people irrationally not use the best method for the situation.
I appologize for not explaining in my first post that I tested a situation where each unit in a group is accessed once. I most propably should have stated that right at the beginning instead of trusting the included simple piece of code to make that clear to the reader, but that is as far as I ever should have gone to represent the test or its results more clearly. That being said the test's results still stand.


Quoted in chronological order from oldest to newest:
PurplePoot said:
I know it isn't, but your definition of when just using the boolexpr from GroupEnum is not completely accurate (And thus, what is relevant for the test).
DiscipleOfLife said:
See the 15th post in this thread. Now, are you still sure that GroupEnums aren't relevant when it comes to looping temporary groups?
PurplePoot said:
I never said they weren't. I was saying that, for the same reasons as ForGroup, they aren't practical in many cases.
You might have wanted to read what you really posted before writing that last sentence.
Also, excluding GroupEnums from that kind of test for reasons that equally apply to ForGroup is plain stupid.


Again some quotes in chronological order:
PurplePoot said:
However, when you set a 100% useless variable 1026000 times, I think it just might make a difference, don't you?
DiscipleOfLife said:
I understand why you don't want it there. But you can't seriously suggest that it doesn't reflect a real practical scenario when it is there.
PurplePoot said:
If you needed it as a global, you would just completely remove the local in favor of it.

So yes, I can.
DiscipleOfLife said:
The global writes that were in my test, but not here, were there because they were the lightest thing I could come up with that let me include the access of the looped units in the test.
PurplePoot said:
That only applies if you only do one operation given the units in the entire loop, which is rather too specific, and in which there are other reasons for which to not use FoG anyways.

So with "100% useless", and something that does not reflect a real practical scenario you actually ment something that does apply when one operation is done to each unit, which is ofcourse a real practical scenario? Not being able to figure that out is not misinterprating: it is being unable to read another's mind.


PurplePoot said:
No, I'm saying that an extra use in one test is biased.
You mean: would be, but isn't because there is no such extra use in my tests.


PurplePoot said:
But in ForGroup there was no local write as well...
It is an integral part of FoG loop that is always there, but not so in ForGroup, and never should when each unit is accessed only once. Do I need to remind you that my test reflected a scenario where each unit is referred to only once?

PurplePoot said:
That's like saying the following are no different:
-
So by saying that set GU = equals to set GU = I'm saying some crap you came up with? Mmmm, no.


PurplePoot said:
It seems like you're misinterpreting the greater part of what I'm saying =/
Its quite hard to interpret something that redefines its meaning everytime you make another post.



Btw. I have nothing more to say on this matter. Everything I have had to say can already be found in this thread and most of it numerous times, which is also the reason why most of this post consists of quotes.
 

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
I didn't understand much what you said...

JASS:
function Trig_Unit_Move_Code_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+60.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+60.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Code_Enum_Fast takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+90.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+90.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Code_Enum_Slow takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+18.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+18.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Code_Actions takes nothing returns nothing
    call ForGroup(udg_Move, function Trig_Unit_Move_Code_Enum)
    call ForGroup(udg_MoveLaser, function Trig_Unit_Move_Code_Enum)
    call ForGroup(udg_MoveFast, function Trig_Unit_Move_Code_Enum_Fast)
    call ForGroup(udg_MoveSlow, function Trig_Unit_Move_Code_Enum_Slow)
endfunction

//===========================================================================
function InitTrig_Unit_Move_Code takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.06, true, function Trig_Unit_Move_Code_Actions)
endfunction

This is the one I made (with help of DicipleofLife code). It's working at least, but the lagg is different and more choppy, instead of pure extended lagg stop.

But it seems like I cannot turn off this trigger. I don't understand why :S
 
Level 9
Joined
Mar 25, 2005
Messages
252
This is the one I made (with help of DicipleofLife code). It's working at least, but the lagg is different and more choppy, instead of pure extended lagg stop.

You're using a timeout of 0.06 which is twice as slow as 0.03 which is what people most commonly use nowadays. That might very well be the cause of the choppyness. (I know I used 0.05 in earlier but it looked fine to me then)
If that isn't the case, then your computer is just too old or you have an insane amount of units being moved around.

But it seems like I cannot turn off this trigger. I don't understand why :S

That is because the script uses a timer with a callback code instead of a timer and a trigger which fires whenever the timer expires.

Try this code:
JASS:
function Trig_Unit_Move_Code_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+30.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+30.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Code_Enum_Fast takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+45.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+45.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Code_Enum_Slow takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+9.0*Cos(GetUnitFacing(u)*bj_DEGTORAD), GetUnitY(u)+9.0*Sin(GetUnitFacing(u)*bj_DEGTORAD))
    set u = null
endfunction

function Trig_Unit_Move_Code_Actions takes nothing returns nothing
    call ForGroup(udg_Move, function Trig_Unit_Move_Code_Enum)
    call ForGroup(udg_MoveLaser, function Trig_Unit_Move_Code_Enum)
    call ForGroup(udg_MoveFast, function Trig_Unit_Move_Code_Enum_Fast)
    call ForGroup(udg_MoveSlow, function Trig_Unit_Move_Code_Enum_Slow)
endfunction

//===========================================================================
function InitTrig_Unit_Move_Code takes nothing returns nothing
    set gg_trg_Unit_Move_Code = CreateTrigger()
    call TriggerAddAction(gg_trg_Unit_Move_Code, function Trig_Unit_Move_Code_Actions)
    call TriggerRegisterTimerEvent(gg_trg_Unit_Move_Code, 0.03, true)
endfunction
This uses a 0.03 timeout and can be turned off normally.
 

TKF

TKF

Level 19
Joined
Nov 29, 2006
Messages
1,266
hmm. okay.

JASS:
function Trig_Unit_Move_Code_Enum takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+50.0*Cos(GetUnitFacing(u)*0.01745), GetUnitY(u)+50.0*Sin(GetUnitFacing(u)*0.01745))
    set u = null
endfunction

function Trig_Unit_Move_Code_Enum_Fast takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+75.0*Cos(GetUnitFacing(u)*0.01745), GetUnitY(u)+75.0*Sin(GetUnitFacing(u)*0.01745))
    set u = null
endfunction

function Trig_Unit_Move_Code_Enum_Slow takes nothing returns nothing
    local unit u = GetEnumUnit()
    call SetUnitPosition(u, GetUnitX(u)+15.0*Cos(GetUnitFacing(u)*0.01745), GetUnitY(u)+15.0*Sin(GetUnitFacing(u)*0.01745))
    set u = null
endfunction

function Trig_Unit_Move_Code_Actions takes nothing returns nothing
    call ForGroup(udg_Move, function Trig_Unit_Move_Code_Enum)
    call ForGroup(udg_MoveLaser, function Trig_Unit_Move_Code_Enum)
    call ForGroup(udg_MoveFast, function Trig_Unit_Move_Code_Enum_Fast)
    call ForGroup(udg_MoveSlow, function Trig_Unit_Move_Code_Enum_Slow)
endfunction

//===========================================================================
function InitTrig_Unit_Move_Code takes nothing returns nothing
    set gg_trg_Unit_Move_Code = CreateTrigger()
    call TriggerAddAction(gg_trg_Unit_Move_Code, function Trig_Unit_Move_Code_Actions)
    call TriggerRegisterTimerEvent(gg_trg_Unit_Move_Code, 0.05, true)
endfunction

I changed the timer to 0.05 for my own needs. Also I replaced bj_DEGTORADs with the magical number of 0.01745!!!
 
Status
Not open for further replies.
Top