• 🏆 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!

[General] Move unit by X,Y

Status
Not open for further replies.

sentrywiz

S

sentrywiz

Okay, I read somewhere around here (or in some map) that a much faster way of moving a unit (I am talking about a dummy projectile unit, with locust and moving it via locs and a constant loop) is to set its X and Y in a loop instead of blinking it through locations. so messy...

I'm guessing this is JASS, or done with custom scripts. It sounds like a MUCH MORE cleaner, faster and efficient way of doing things with moving dummies or just any unit in general, like knockback, jumps (if you can manipulate Z as well) and lots of stuff.

Can someone explain how this is done, or even post a trigger or two? Links are good as well, but I'm not jass savvy though I understand the basics.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
For dummys you can use the following natives...
JASS:
native SetUnitX takes unit whichUnit,real newX returns nothing
native SetUnitY takes unit whichUnit,real newY returns nothing
These do not perform collision checks or interrupt the unit making them ideal for dummy units and a lot faster than other moves.

The other way is using...
JASS:
native SetUnitPosition takes unit whichUnit,real newX,real newY returns nothing
Which is the X and Y version of the GUI move action. This means both collision (with displacement) and implicit stop order occur. This call is actually slower (or so people said, I personally have no proof) than the one using a location because it takes an extra parameter however the difference is more than compensated by not having to create location objects to feed it.

What really improves the speed is you can perform geometric optimizations not possible in GUI. For example a unit moving at a constant velocity can be achieved with a constant vX and vY value being added to the current unit position every cycle (no trig every cycle, only some at start).
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
To add to what DSG has said, SetUnitX/Y are what you are looking for. In creating my knockback2D trigger, I found that SetUnitX/Y with a dummy order id and an item to check for pathing were faster than SetUnitPosition. However, if you pause the unit during movement with SetUnitPosition, the performance skyrockets, though it still checks for pathing. I haven't tested projectiles without collision sizes, but SetUnitPosition with paused missiles without collision could be faster than SetUnitX/Y
 

sentrywiz

S

sentrywiz

For dummys you can use the following natives...
JASS:
native SetUnitX takes unit whichUnit,real newX returns nothing
native SetUnitY takes unit whichUnit,real newY returns nothing
These do not perform collision checks or interrupt the unit making them ideal for dummy units and a lot faster than other moves.

The other way is using...
JASS:
native SetUnitPosition takes unit whichUnit,real newX,real newY returns nothing
Which is the X and Y version of the GUI move action. This means both collision (with displacement) and implicit stop order occur. This call is actually slower (or so people said, I personally have no proof) than the one using a location because it takes an extra parameter however the difference is more than compensated by not having to create location objects to feed it.

What really improves the speed is you can perform geometric optimizations not possible in GUI. For example a unit moving at a constant velocity can be achieved with a constant vX and vY value being added to the current unit position every cycle (no trig every cycle, only some at start).

To add to what DSG has said, SetUnitX/Y are what you are looking for. In creating my knockback2D trigger, I found that SetUnitX/Y with a dummy order id and an item to check for pathing were faster than SetUnitPosition. However, if you pause the unit during movement with SetUnitPosition, the performance skyrockets, though it still checks for pathing. I haven't tested projectiles without collision sizes, but SetUnitPosition with paused missiles without collision could be faster than SetUnitX/Y

Okay, but how to calculate the next X and Y where the dummy is supposed to be? In gui, you do it with two locations: current one and the offset one by direction the unit is facing. How do you do it here? Its rather complicated when i try to think of a solution, so why don't any of you just tell me?

Also, how do I check for collisions? Because these are for use of projectiles, do I just do the same thing with unit group with condition units within range of location of projectile?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Sine and cosine baby. Geometry is what we need, here.

JASS:
x = x + Cos(angleInRadians) * offsetDistance
y = y + Sin(angleInRadians) * offsetDistance

Collision is a little different.

JASS:
local unit u
call GroupEnumUnitsInRange(udg_DontDestroyThisUnitGroup, x, y, radius, null
loop
    set u = FirstOfGroup(udg_DontDestroyThisUnitGroup)
    exitwhen u == null
    call GroupRemoveUnit(udg_DontDestroyThisUnitGroup, u)
    //unit u is the picked unit
endloop
 
Level 7
Joined
Aug 15, 2012
Messages
318
Sine and cosine baby. Geometry is what we need, here.

JASS:
x = x + Cos(angleInRadians) * offsetDistance
y = y + Sin(angleInRadians) * offsetDistance

Collision is a little different.

JASS:
local unit u
call GroupEnumUnitsInRange(udg_DontDestroyThisUnitGroup, x, y, radius, null
loop
    set u = FirstOfGroup(udg_DontDestroyThisUnitGroup)
    exitwhen u == null
    call GroupRemoveUnit(udg_DontDestroyThisUnitGroup, u)
    //unit u is the picked unit
endloop

I always wanted to have a use for geometry again ;) I know this is offtopic but would that collision work with trees aswell?
 

sentrywiz

S

sentrywiz

Oh no, i don't like geometry at all. but i will try to understand on my own, maybe google sin and cos.
 
I hear ya, I had to sorta learn it myself when I updated my beam system to not use location variables. If you want to find the angle and/or distance between two x/y coordinates that you already have, there they are (please correct me if I'm wrong anyone):

Assume that you want to find the angle from x1/y1 to x2/y2



Angle (In Radians)
JASS:
set angle = Atan2(y2 - y1, x2 - x1)
Use * bj_RADTODEG to convert it to degrees if you need to. bj_DEGTORAD converts degrees to radians.



Distance
JASS:
set dx = x2 - x1
set dy = y2 - y1
set distance = SquareRoot(dx * dx + dy * dy)
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
No one has problems doing 1+2. You'll have to admit trigonometry is a tad more complicated than that.
Really?

AB^2 + AC^2 = BC^2
<A = 90°
Tan(<B) = AC/AB
Tan(<C) = AB/AC
etc.

It is not more complicated, it is just that you use different things than 1 2 and 3.
It is just that people dont see how because they dont try.
Do you remember the first time you entered the trigger editor?
I bet you closed it immediately because it looked too complicated.
Right now, I must say that it is too simple.

Doing it with coordinates instead of a triangle has only got one difference.
That both coordinates can have the same X or Y, which would lead to a divide by 0 before you know it.

@Sentrywiz
To just take a simple example of how this works in WC3, you can just look at the implementation of PolarProjectionBJ(), AngleBetweenPoints() and DistanceBetweenPoints().

JASS:
function PolarProjectionBJ takes location source, real dist, real angle returns location
    local real x = GetLocationX(source) + dist * Cos(angle * bj_DEGTORAD)
    local real y = GetLocationY(source) + dist * Sin(angle * bj_DEGTORAD)
    return Location(x, y)
endfunction

function DistanceBetweenPoints takes location locA, location locB returns real
    local real dx = GetLocationX(locB) - GetLocationX(locA)
    local real dy = GetLocationY(locB) - GetLocationY(locA)
    return SquareRoot(dx * dx + dy * dy)
endfunction

function AngleBetweenPoints takes location locA, location locB returns real
    return bj_RADTODEG * Atan2(GetLocationY(locB) - GetLocationY(locA), GetLocationX(locB) - GetLocationX(locA))
endfunction

Looking at these functions always reminds me of the simple way of geometry when I code in JASS.

To use these in JASS without locations, you can simply implement an AngleBetweenCoordinates() and DistanceBetweenCoordinates().
For PolarProjectionBJ(), you have to return two real values (x and y) so you need a proper struct or returning global real array variable, or just implement the calculation directly.
JASS:
    function DistanceBetweenCoordinates takes real x1, real y1, real x2, real y2 returns real
        local real x = x2 - x1
        local real y = y2 - y1
        return SquareRoot(x*x + y*y)
    endfunction
    
    function AngleBetweenCoordinates takes real x1, real y1, real x2, real y2 returns real
        return bj_RADTODEG * Atan2(y2 - y1, x2 - x1)
    endfunction

    function foo takes nothing returns nothing
        local real old_X = GetRandomReal(0, 123)
        local real old_Y = GetRandomReal(0, 456)
        local real new_X
        local real new_Y
        
        local real distance = GetRandomReal(0, 500)
        local real angle = GetRandomReal(0, 360)
        
        set new_X = old_X + distance*Cos(angle*bj_DEGTORAD)
        set new_Y = old_Y + distance*Sin(angle*bj_DEGTORAD)
        
    endfunction

I have a library with a pretty large list of functions like these which you use in many situations.
 

sentrywiz

S

sentrywiz

AB^2 + AC^2 = BC^2
<A = 90°
Tan(<B) = AC/AB
Tan(<C) = AB/AC
etc.

It is not more complicated, it is just that you use different things than 1 2 and 3.
It is just that people dont see how because they dont try.
Do you remember the first time you entered the trigger editor?
I bet you closed it immediately because it looked too complicated.
Right now, I must say that it is too simple.

The problem is, since I and others like me are hypocrites. We want an efficient method based on geometry and formulas but are scared and/or lazy to learn ourselves. Also it looks scary, especially if you were dodging geometry classes in school (like I did) which is why I had problems with math in high school and had to go for months to extra classes just to catch up on things. Now its all void knowledge...

But you're correct on the world editor thing. With enough repetition and practice, anything becomes easy and a habit.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
The problem is, since I and others like me are hypocrites. We want an efficient method based on geometry and formulas but are scared and/or lazy to learn ourselves. Also it looks scary, especially if you were dodging geometry classes in school (like I did) which is why I had problems with math in high school and had to go for months to extra classes just to catch up on things. Now its all void knowledge...
Your fault? Governments give you that knowledge for free so why not take it? Worse is if your parents actually paid for you to be taught that stuff (money thrown away).

Good article explaining trigonometry.
Good article explaining Euclidian distance (distance between two points).
Good article with information about sine, including how to compute it.
Article explaining Radians (the unit of angle used by JASS trigonometric functions).
Article explaining degrees (angle used by unit facing and GUI).
Information about vectors which are useful when dealing with multi dimensional positions.
Information about matrix mathematics, useful for manipulating vectors in multi dimensional space.

You might have noticed all this is from Wikipedia. Most countries in the world should have access to it. Sure not all the information is relevant to WC3 such as the computation of sine using a Taylor series as WC3 already computes it for you however contained within is all you really need to know about the subject. Even if the articles do not contain everything, they will link everything.

The reason there are no guides for doing this stuff in WC3 is because it really is so simple to do you might as well write guides how to "add 1+1".
 

sentrywiz

S

sentrywiz

Your fault? Governments give you that knowledge for free so why not take it? Worse is if your parents actually paid for you to be taught that stuff (money thrown away).

Good article explaining trigonometry.
Good article explaining Euclidian distance (distance between two points).
Good article with information about sine, including how to compute it.
Article explaining Radians (the unit of angle used by JASS trigonometric functions).
Article explaining degrees (angle used by unit facing and GUI).
Information about vectors which are useful when dealing with multi dimensional positions.
Information about matrix mathematics, useful for manipulating vectors in multi dimensional space.

You might have noticed all this is from Wikipedia. Most countries in the world should have access to it. Sure not all the information is relevant to WC3 such as the computation of sine using a Taylor series as WC3 already computes it for you however contained within is all you really need to know about the subject. Even if the articles do not contain everything, they will link everything.

The reason there are no guides for doing this stuff in WC3 is because it really is so simple to do you might as well write guides how to "add 1+1".

Money is always spent, wasted or traded. You can always make more money, but you can't make more time.

I can re-learn geometry but I don't want to spend time to learn JASS. This is the real problem for me.
That's why I want someone to show me a way so that I can easily modify and re-use it.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,190
That's why I want someone to show me a way so that I can easily modify and re-use it.
The problem is that is not possible or does not work because the principles behind trigonometry are so simple they are used similar to addition or subtraction in a trigger. You derive the statements as required instead of consulting a template.

This only stops being the case when the mathematics becomes considerably more complicated or time consuming to derive. For example when doing 3D vector manipulation you will grab a ready-to-use transformation matrix instead of deriving one yourself due to how tedious and error prone the matrices are to produce.

Wietlol has given some examples of what you can do using trigonometry. These are the sort of examples seen in hundreds of maps in the spell section.
 

sentrywiz

S

sentrywiz

The problem is that is not possible or does not work because the principles behind trigonometry are so simple they are used similar to addition or subtraction in a trigger. You derive the statements as required instead of consulting a template.

This only stops being the case when the mathematics becomes considerably more complicated or time consuming to derive. For example when doing 3D vector manipulation you will grab a ready-to-use transformation matrix instead of deriving one yourself due to how tedious and error prone the matrices are to produce.

Wietlol has given some examples of what you can do using trigonometry. These are the sort of examples seen in hundreds of maps in the spell section.

True. The decision is mine anyway if I want to learn JASS and re-learn math.
 
Status
Not open for further replies.
Top