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

SetUnitX / Y problem

Status
Not open for further replies.
Level 12
Joined
May 22, 2015
Messages
1,051
I have a few non-moving units (basically wards, I guess) and when I move them with SetUnitX and SetUnitY, the models don't move with the unit. The health bar shifts over along with all the collision and stuff, but the model is just sitting where it came from.

I did not have this problem at all with the GUI function for setting a unit's position, but I am having it now after redoing a few triggers in JASS.

Is there an extra step I'm missing? Should I just swap out the models with non-doodad ones? Thanks in advance.

EDIT:
I actually just noticed it with the forgotten one tentacles. They are not doodads normally, so I don't quite know what is causing it.
 
Last edited by a moderator:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
Know problem. Also happens if you move buildings except also the collision map stays put.

Either give the unit movement or use SetUnitPosition.
JASS:
native SetUnitPosition takes unit whichUnit,real newX,real newY returns nothing
This is basically what GUI uses. It is considerably slower but that is due to it running collision checks, attempting displacement and correctly moving buildings. If you call it once every few seconds it is ok, SetUnitX/Y is only needed in performance critical code like 0.03 period systems.

There might be some hacky fix with the unit type itself. If it is treated like the units which model moves then it will also move. However I do not know of any off the top of my head. If anything it will have to do with movement or classification flags.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Yep, came here to mention the same things DSG has.

- Do these dummy units need to be targeted? If not, then you can add the Locust unit ability to them to hide their health bar and prevent them from being selected.

- If so, do these dummies attack? If not, you can have their movement speed set to an above-0 value so SetUnitX/Y will work.
 
Level 5
Joined
May 12, 2014
Messages
133
If you need the model to move with the unit, it needs to have a movement speed higher than 0. I don't know if you need to change the movement type to something other than none, but I would change it to fly if the unit isn't being directly controlled.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
If you need the model to move with the unit, it needs to have a movement speed higher than 0.

No, you just need to use SetUnitPosition.

I don't know if you need to change the movement type to something other than none, but I would change it to fly if the unit isn't being directly controlled.

The movement type is only a factor if it needs a certain collision type check when using SetUnitPosition or if it were moving around on its own without the help of triggers.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Thanks for the answers, everyone. I'll most likely just use SetUnitPosition.

Is SetUnitPosition with X and Y values significantly faster than creating a point, using the GUI set position, and deleting the point? I am curious how much of a speed improvement it is.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
Hmm.. if I replace my Move Unit (Instantly) with custom script SetUnitX and SetUnitY, do I need to set 2 temp reals to the point's X and Y or is "SetUnitX/Y to X/Y of Temp_Point" leak free as it is?
It is leak free because only primitives are used (no complex objects created). The real values fit inside the actual variable, as opposed to locations which are a complex object so have a handle placed inside the actual variable.

Is SetUnitPosition with X and Y values significantly faster than creating a point, using the GUI set position, and deleting the point? I am curious how much of a speed improvement it is.
Yes and no. It is faster if you work with the X / Y coordinates separately (no location) as the slower call is offset by no object allocation. No it is not faster if you already have locations and are reading their X/Y values since you are calling extra functions and passing more arguments.
 
Level 12
Joined
May 22, 2015
Messages
1,051
Hmm, so it IS faster if I have some pre-set points which X's and Y's I've saved in (global, real) variables, since "real" variables aren't objects?

You can also work purely with X and Y values. No locations. There are JASS functions to get the X and Y values for basically everything you can interact with in the code (GetUnitX, GetUnitY). You can figure out where they offset to using sin and cos.

Locations would do this anyway, so you are not losing that computation time on unnecessary math functions, but you don't deal with objects being created etc.



One last thing on SetUnitPosition. Does it tell the unit to stop like the GUI set unit position function?
 
Level 12
Joined
Jan 2, 2016
Messages
973
I'm kind a trying to reowork my sliding trigger (I was using move unit (instantly) until now), but I can't figure out how to set the unit's x and y to variables. I used "call GetUnitX(GetEnumUnit())", but I don't know how to add the value to a local real x.
EDIT: Note that I'm trying to do this in GUI, using custom scripts. I still can't use JASS.
 
Last edited:
Level 12
Joined
Jan 2, 2016
Messages
973
This is my trigger:
  • Sliding
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
      • (Sliding_Group is empty) Equal to False
    • Actions
      • Custom script: local real x
      • Custom script: local real y
      • Unit Group - Pick every unit in Sliding_Group and do (Actions)
        • Loop - Actions
          • Set Sliding_Effect_1 = (Load (Key Effect_1) of (Key (Picked unit)) from Sliding_Table)
          • Set Sliding_Angle = (Load (Key Angle) of (Key (Picked unit)) from Sliding_Table)
          • Set Sliding_Speed = (Load (Key Speed) of (Key (Picked unit)) from Sliding_Table)
          • Set Sliding_Time = (Load (Key Time) of (Key (Picked unit)) from Sliding_Table)
          • Custom script: call GetUnitX(GetEnumUnit())
          • Custom script: call GetUnitY(GetEnumUnit())
          • Set Temp_Point = ((Position of (Picked unit)) offset by (Sliding_Speed x 0.03) towards Sliding_Angle degrees)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Sliding_Time Greater than 0.00
            • Then - Actions
              • Custom script: call SetUnitX( GetEnumUnit() , 1000 )
              • Custom script: call SetUnitY( GetEnumUnit() , 1000 )
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Sliding_Effect_1 Equal to True
                • Then - Actions
                  • Destructible - Pick every destructible within 150.00 of Temp_Point and do (If ((Destructible-type of (Picked destructible)) Equal to Ruins Tree Wall) then do (Destructible - Kill (Picked destructible)) else do (Do nothing))
                  • Special Effect - Create a special effect at Temp_Point using Abilities\Spells\Human\FlakCannons\FlakTarget.mdl
                  • Special Effect - Destroy (Last created special effect)
                • Else - Actions
              • Hashtable - Save (Sliding_Time - 0.03) as (Key Time) of (Key (Picked unit)) in Sliding_Table
            • Else - Actions
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Sliding_Table
              • Unit Group - Remove (Picked unit) from Sliding_Group
The SetUnitX/Y are set to 1000, cuz I wanted to see if it's working.
I wanna replace the 1000 with x//y// + cos//sin//(angle)*speed*0,03

Can you rework my trigger and make it do that?
(I started improving my triggers just a while ago and I still haven't removed the leaks from this one, but don't mind them)
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
You can move the local real x/y between the "Loop - Actions" statement and the first hashtable load, otherwise they won't work. If you converted the trigger to JASS, you would see why: enums are in a different function.

Keep in mind you don't need to use locals. You could just do:

  • Custom script: call SetUnitX(GetEnumUnit(), GetLocationX(udg_TempPoint))
  • Custom script: call SetUnitY(GetEnumUnit(), GetLocationY(udg_TempPoint))
Although, it would be better to ditch the location altogether. I notoced you are leaking (Position of (Picked unit)) so you can do this:

  • Set Sliding_Speed = Sliding_Speed x 0.03
  • Custom script: set udg_TempReal = GetUnitX(GetEnumUnit())
  • Set TempReal = ((Cos(Sliding_Angle) x Sliding_Speed) + TempReal)
  • Custom script: call SetUnitX(GetEnumUnit(), udg_TempReal)
  • Custom script: set udg_TempReal = GetUnitY(GetEnumUnit())
  • Set TempReal = ((Sin(Sliding_Angle) x Sliding Speed) + TempReal)
  • Custom script: call SetUnitY(GetEnumUnit(), udg_TempReal)
Keep in mind you do not multiply the unit's x to the cos/sin*distance product.
 
Level 12
Joined
Jan 2, 2016
Messages
973
Yeah, now it works, and it doesn't prevent the units form doing what they were ordered to :)
I just don't understand why "set x = GetUnitX(GetEnumUnit())" wasn't working and "set udg_Temp_Real = GetUnitX....." IS working... did I define x the wrong way? And if so, why wasn't it giving me errors?
Anyways, thanks for the help :)
This is the complete trigger working:
  • Sliding SetUnitX Y
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
      • (Sliding_Group is empty) Equal to False
    • Actions
      • Unit Group - Pick every unit in Sliding_Group and do (Actions)
        • Loop - Actions
          • Set Sliding_Angle = (Load (Key Angle) of (Key (Picked unit)) from Sliding_Table)
          • Set Sliding_Speed = (Load (Key Speed) of (Key (Picked unit)) from Sliding_Table)
          • Set Sliding_Time = (Load (Key Time) of (Key (Picked unit)) from Sliding_Table)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Sliding_Time Greater than 0.00
            • Then - Actions
              • Custom script: set udg_Temp_Real = GetUnitX(GetEnumUnit())
              • Set Temp_Real = (Temp_Real + ((Cos(Sliding_Angle)) x (Sliding_Speed x 0.03)))
              • Custom script: call SetUnitX( GetEnumUnit() , udg_Temp_Real )
              • Custom script: set udg_Temp_Real = GetUnitY(GetEnumUnit())
              • Set Temp_Real = (Temp_Real + ((Sin(Sliding_Angle)) x (Sliding_Speed x 0.03)))
              • Custom script: call SetUnitY( GetEnumUnit() , udg_Temp_Real )
              • Hashtable - Save (Sliding_Time - 0.03) as (Key Time) of (Key (Picked unit)) in Sliding_Table
            • Else - Actions
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Sliding_Table
              • Unit Group - Remove (Picked unit) from Sliding_Group
I will keep the old version too, cuz sometimes I need a "stuning sliding" :p

EDIT: (A bit offtopic, but lol) With this trigger, if I set Sliding_Angle to unit's facing, and if I remove the unit from Sliding_Group only when it's attacked (and IT is the attacking unit) or when it's ordered to stop. And if I put the unit back in the group if it's ordered to "move" or "smart" - I can make a nice speed booster :D (Sliding_Speed x 0,03 can be replaced with a constant)
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
The reason you were getting compile errors, as I said before, was because you declare the local variables at the top of the trigger. If you want to use locals when you pick all units in a group, you have to declare a new set at the top of the "loop - actions" block.

  • Unit Group - Pick all units in ...
    • Loop - Actions
      • Custom script: local real x
      • Custom script: local real y
Keep in mind that any locals you declare in one function will not be accessible from outside of it. Until you have a better understanding of scope, it is a good idea to avoid locals and stick to globals.
 
Level 12
Joined
Jan 2, 2016
Messages
973
The reason you were getting compile errors, as I said before, was because you declare the local variables at the top of the trigger. If you want to use locals when you pick all units in a group, you have to declare a new set at the top of the "loop - actions" block.

  • Unit Group - Pick all units in ...
    • Loop - Actions
      • Custom script: local real x
      • Custom script: local real y
Keep in mind that any locals you declare in one function will not be accessible from outside of it. Until you have a better understanding of scope, it is a good idea to avoid locals and stick to globals.
Ah, I see... I was just misinformed that I always need to declare local variables in the begining of my triggers.
Otherwise I am using local variables in other triggers and they work just fine :p
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
Do we actually have a benchmark about how much slower SetUnitPosition() is compared to SetUnitX/Y?

What factor are we talking about exactly, here? Factor 10?

I'd love to know that, since SetUnitPosition() offers many advantages over SetUnitX/Y...

SetUnitX/Y is 6 times faster. I wrote about this in the lab. And that's with a paused unit with no collision.
 
Status
Not open for further replies.
Top