HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Making a unit appear to move very fast (JASS)

12-20-2005, 06:18 PM#1
aaero
Here's the issue. I've got an ultimate where I want it to appear that a hero is moving very fast in straight lines forming an "X" over a stationary target. I accomplish this by doing some math and calculating where the units position should be...well, I'll just show some code.

Collapse JASS:
    local unit Target
    local location TargetSpot
    local unit Caster
    local integer a
    local lightning array Lightning
    local unit array Assassins
    set Target = GetSpellTargetUnit()
    set Caster = GetTriggerUnit()
    set TargetSpot = GetUnitLoc(Target)
    call PauseUnitBJ( true, Target )
    call PolledWait( 0.75 )
    call SetUnitInvulnerable( Target, true )
    call ShowUnitHide( Caster )
    // --------------------------------------------------------------------------------

    // ----------------------------------- X marks the Spot ---------------------------
    // ------------------- Top left to Bottom Right
    call CreateNUnitsAtLoc( 1, EtherealAssassin_ID(), GetOwningPlayer(Caster), PolarProjectionBJ(TargetSpot, 300.00, 135.00), 315.00 )
    set Assassins[0] = GetLastCreatedUnit()
    call SetUnitVertexColorBJ( GetLastCreatedUnit(), 100, 100, 100, 75.00 )
    
// -------------- Here is where I actually move the unit in a loop ------------
    set a = 1
    loop
        exitwhen a > 4
        if ( a != 2 ) then
            call SetUnitPositionLoc( Assassins[0], PolarProjectionBJ(TargetSpot, ( ( I2R(a) - 2.00 ) * 150.00 ), 315.00) )
            call IssuePointOrderLocBJ( Assassins[0], "move", PolarProjectionBJ(TargetSpot, 1000.00, 315.00) )
            if ( a < 4 ) then
                call TriggerSleepAction( 0.03 )
            else
            endif
        else
        endif
        set a = a + 1
    endloop
// ---------------- End Unit Move Loop ------------------------------------


// ---------------- Everything below here is basically a duplicate of the above code
// ----------- the only difference is the physical location is different. -------------

    // ----------------------- Top right to bottom left
    set a = 0
    loop
        exitwhen a > 4
        if ( a != 2 ) then
            // Set the actual position
            call SetUnitPositionLoc( Assassins[0], PolarProjectionBJ(TargetSpot, ( ( I2R(a) - 2.00 ) * 150.00 ), 225.00) )
            // Order the unit to move so it looks like she's traveling a certain way
            call IssuePointOrderLocBJ( Assassins[0], "move", PolarProjectionBJ(TargetSpot, 1000.00, 225.00) )
            if ( a < 4 ) then
                call TriggerSleepAction( 0.03 )
            else
            endif
        else
        endif
        set a = a + 1
    endloop

I cut some special effects and sound code because I don't think it's relevant.

The problem is that this happens much much slower than i would like. It seems that delays of less than .10 still count as a delay of .10 (I think I remember reading that anyway). I also remember reading in a different thread that SetUnitX and SetUnitY are much faster than SetUnitPosition, but I sincerely doubt that's the issue. I will try it though. Any other cleanup suggestions are welcome as well.

Thanks for any help!
12-20-2005, 06:32 PM#2
Starcraftfreak
I'm sorry to say, but my eyes are hurting seeing your code full of BJ-junk. Don't take this as an insult, but maybe you want to change some functions to their common.j equivalents.

Additionally you should not use handle-based variable types like location if there is an alternative. This will prevent memory leaks. Other than that, the location-funcs are not slower. Just make sure you always destroy every handle-based variable once it's no longer needed. And where possible, look for an alternative. PolarProjectionBJ is also a leaky function for example.

The wait doesn't work very accurate. For example a wait of 0.0 is still more, almost 0.1 if I'm not wrong. 0.1 is more than 0.1 and so on. So you might want to reduce the wait time.


If that post doesn't help you a lot, I can only suggest, that you read about leaks and how to prevent them. Your code would leak like hell. Again no insult
12-20-2005, 06:33 PM#3
Blade.dk
The minimum delay is like 0.1, no matter what value you specify.

You should use the Caster System or the handle vars to fix that, check the following tutorials to know how to use the handle vars:

Using the Handle Vars
Using Timers and Handle Vars.

EDIT: Funny, Starcraftfreak posted at the same time as me. Just listen to his advice and use handle vars or caster system, that should fix all your trouble.

And better use jass tags instead of code tags.
12-20-2005, 06:34 PM#4
iNfraNe
TriggerSleep is just WAAY to slow. The way you should do this is with a timer and a looping trigger, or with a periodic event (which is basically the same anyway). You can create the trigger + timers when the ability is cast. If you need further help with this just ask and ill write some code.

You should also use SetUnitX and SetUnitY instead of SetUnitPosition since they are faster

edit: lol 3 posts at the same time (and im last :()
12-20-2005, 06:41 PM#5
Starcraftfreak
Quote:
Originally Posted by iNfraNe
You should also use SetUnitX and SetUnitY instead of SetUnitPosition since they are faster

edit: lol 3 posts at the same time (and im last :()
As I said those shouldn't be faster per se, but they help prevent leaks, thus they will be "faster" in the long run.

Hehe, I was first , then comes blade (+1min), then you (+2min).
12-20-2005, 06:57 PM#6
aaero
I guess the forums are alive again! Thanks for all the quick posts.

I'm going to try what Blade suggested since I really have a lot of spells that would benefit from what handle variables seem to do -- that is, that you can get the benefits of a local variable (specific instance for each instance of the trigger that runs) and a global (can call it from more than one spot).

I'm still pretty new to JASS, and thanks scfreak for the heads up on the BJ functions. I think I remember reading in another thread they were bad. When you say switch it to the common.j equivalent, do you just mean calling the function with a similar name without the BJ? If I understand it right, as an example the PauseUnitBJ looks something like this.

Collapse JASS:
function PauseUnitBJ takes bool PauseUnit, Unit UnitToPause returns nothing
    call PauseUnit(whatever PauseUnit params are)
endfunction

So in that example, I should just call PauseUnit to save wc3 the trouble of making both function calls.

Also, as far as using handle-based types instead of native types, do you mean to say I can use a native type to store location? In my experience its looked like I could use an int to store a unit(since I think a unit is just a 4 character hex string), but I'm not really sure. Can I see an example of using a native type in place of a location variable?

For example, how would I change this

Collapse JASS:
local location TargetSpot = GetUnitLoc(GetTriggerUnit())
to use a native type?

Thanks again for all the help everyone. I'm technically at work right now so I don't want to start trying to implement Kattana's handle system but I imagine I'll do it tonight (6 hours from now where I live).
12-20-2005, 06:58 PM#7
iNfraNe
Quote:
Originally Posted by Starcraftfreak
As I said those shouldn't be faster per se, but they help prevent leaks, thus they will be "faster" in the long run.

Wrong, setunitx&y are actually alot faster, becuz setunitx/y dont check pathing and just move a unit. It is also better to check pathing manually cuz then you would know when a hero cant move further and you can stop there trigger.

Here's an example map, run it (then it uses setunitx) and then press escape. If after pressing escape it doesnt lag for you try placing more units.
Attached Files
File type: w3xtest.w3x (17.9 KB)
12-20-2005, 06:58 PM#8
Anitarf
Quote:
Originally Posted by Starcraftfreak
As I said those shouldn't be faster per se, but they help prevent leaks, thus they will be "faster" in the long run.
No, no, SetUnitX() and SetUnitY() are faster. They're faster than SetUnitPosition(), which also takes x and y coordinates. They don't interrupt orders or animations, the only thing to look out for is moving a unit outside of map bounds with this, as it causes a crash.

Otherwise, native functions that use locations are generaly equally fast to functions that use coordinates, but there's the cost of creating and cleaning up locations to be considered.

Anyway, my suggestion is that you make a sliding system using a periodic trigger or timers (depends on how many units you expect to be sliding at the same time), so you can use it for this spell or any other. There's a nice sliding system in mine and iNfraNe's cinematic, tSoV (shameless plug :) ), but it's not documented well because we had to rush the map for blizzard's contest, so perhaps making your own or finding another one would suit you better.
12-20-2005, 07:04 PM#9
Blade.dk
In fact, it is faster to pass a location to a function than to pass to reals. But better use reals, cleanup, creation and the fact that most location using functions just calls their real equivilants is making it slower and often quite painful.
12-20-2005, 07:08 PM#10
Starcraftfreak
Hehe, you guys bet me to SetUnitX/Y. One has never learnt enough about Jass. But I'd use the X/Y functions anyway

@aaero:
location is also a native type. What I mean is that you should prefer base-types (boolean, int, real) over handle-based ones.
Wehn replacing functions, just be sure to use the correct number and order of parameters. Blizzard shuffled a lot so look up the two script files.

Edit:
Quote:
Originally Posted by Blade.dk
In fact, it is faster to pass a location to a function than to pass to reals. But better use reals, cleanup, creation and the fact that most location using functions just calls their real equivilants is making it slower and often quite painful.
Thats not true. There is a lot of native location-equivalents. The sad thing is that there is no equivalent to GetSpellTargetLoc().
12-20-2005, 07:16 PM#11
Blade.dk
Agreed, that is sad. Ok, it isn't most functions, but passing a loc is faster than passing two reals. If you want to, I can try to find the post with the benchmarks (unless that it's not true is only directed at the location calling reals part of the post ).
12-20-2005, 10:08 PM#12
Starcraftfreak
Quote:
Originally Posted by Blade.dk
If you want to, I can try to find the post with the benchmarks (unless that it's not true is only directed at the location calling reals part of the post ).
Yeah, please do so.
12-20-2005, 10:11 PM#13
Anitarf
Passing a single loc may be faster than two reals, but there's the creation and cleanup cost of locations to be considered. Also, when talking about moving units, SetUnitX and SetUnitY just own everything else, not that much in speed (because if you want to make it safe and do map-bounds and pathability checks, you waste some time there) but also in the fact they don't interrupt unit animations and orders.

Aaero, regarding learning Jass, I suggest you check your functions at www.wc3jass.com, there's a nice function finder there, you can always look up your BJ functions there and see what functions they call. Be careful, not every function that doesn't have a BJ at the end is a native. Some functions even leak memory because they don't nullify locals.

An alternative to the website is getting a jass editing program, I suggested the site because the program I have only displays names of functions, not their content, but there are probably better programs than the one I have. However, for looking up user created functions, wc3jass is the place to go to. Reading those (at least the ones simple enough for you to understand) can be very educational.
12-20-2005, 10:12 PM#14
Blade.dk
http://www.wc3jass.com/viewtopic.php?p=4353#4353

Those are my benchmarks. If you want to see the map aswell I might be able to find it, but you shouldn't need it since the code is in the post anyway .

Of course this is only about passing the values, it doesn't take creation and cleanup in consideration.
12-20-2005, 10:55 PM#15
iNfraNe
Well.. yes it would seem obvious passing 1 value instead of 2 would be faster. But its deffinatly not at the same level as creating/removing the loc.