| 10-23-2009, 05:50 AM | #1 |
I'm aware this is a fairly known problem, but I haven't seen any solutions for fixing this general problem on a map with a ton of units. It can't simply be fixed by doing delayed orders bit by bit because just the existence of the units lags all unit commands made by players. Is there any simple solution to this pretty silly problem? If not, I'm just gonna turn pathing off on every unit and implement my own dumb A* algorithm, but I was just wondering if there was any simpler way, such as a setting value to make the game engine spend more time on pathing per iteration? Surely WC3 isn't completely hard coded into not supporting pathing with hundreds of units on today's processors, which can easily handle that... |
| 10-23-2009, 07:52 AM | #2 |
I suggest delayed orders, its surely a better way to just let wc3 handle it. |
| 10-23-2009, 08:14 AM | #3 |
I would, but many of the occurrences of this are either from rally points or players actually doing orders. In my tests, even doing an order that doesn't require movement as a player will still result in the delay before the order is completed. |
| 10-23-2009, 08:25 AM | #4 | |
Quote:
Simple: Split up the ownership. For some ungodly reason, 500+ units owned by one player lags to all hell. However, 5 players owning 100+ units each works fine. (Numbers are completely made up. Actual number of units that cause lag / work properly will vary.) |
| 10-23-2009, 08:41 AM | #5 | |
Quote:
That's interesting.. If only I had extra players to put ownership in, I'd do it. I've already tried having units remove themselves from a player's total unit group then reissuing their order in an attempt to circumvent this, as I suspected the cap was on a per-player basis, but it didn't work. I'm not sure if that could work and I just did it wrong, or it is a futile attempt, though. edit: When I did the reissue orders thing, it was on an event for any issued order, but it either reset the unit custom value if it was at 1 or set the value to 1 as well as redoing the order if not. I don't think it was resulting in any crazy infinite loops, and it didn't seem to have any beneficial/detrimental effect at all. It was just totally useless. The group I used and removed the ordered unit from before redoing its order was only the units owned by the player owning the ordered unit. I'm really not sure if attempting to do this in this way is useless or not (it probably is, I'd guess the engine would be regenerating or using an unaltered version of the player unit groups), but I had to try. I'm eying a constant value in Blizzard.j named bj_MAX_QUEUED_TRIGGERS that is set to 100. Perhaps this is the culprit? Is there a way to override a constant value so I can check it out? |
| 10-23-2009, 09:55 AM | #6 | |
WC3 pathing just fails for that number of units. Quote:
My theory is that they factor in the player's own units, so that they try and walk around each other better, but don't do that for other units. |
| 10-23-2009, 10:51 AM | #7 |
I made this in a few minutes, and I didn't compiled this, but maybe it helps you. This automaticly orders all units to do your order, just with a little delay. JASS:library MassOrder struct MassOrder private unit array units private integer index = 0 private boolean f = false private string s = "" private real x = 0. private real y = 0. private widget tw = null private widget itw = null private string act = "" private static timer t = CreateTimer() private static thistype array instances private static integer i = 0 public method create takes nothing returns thistype local thistype this = thistype.allocate() set thistype.instances[thistype.i] = this set thistype.i = thistype.i + 1 if thistype.i == 1 then call TimerStart(thistype.t, 0.001, true, function thistype.onOrder) endif return this endmethod public static method onOrder takes nothing returns nothing local integer i = 0 if thistype.i > 0 then loop exitwhen i <= thistype.i if i <= thistype.i then if thistype.instances[i].f then if not thistype.instances[i].order() then call thistype.instances[i].destroy set thistype.instances[i] = thistype.instances[thistype.i] set i = i - 1 endif endif endif set i = i + 1 endloop else call PauseTimer(thistype.t) endif endmethod public method order takes nothing returns boolean if .index > 0 then if .act == "iO" then call IssueImmediateOrder(.units[.index], .s) elseif .act == "pO" then call IssuePointOrder(.units[.index], .s, .x, .y) elseif .act == "tO" then call IssueTargetOrder(.units[.index], .s, .tw) endif set .units[.index] = null set .index = .index - 1 return true else return false endif endmethod private method giveOrder takes string s returns boolean if not f then set f = true set .act = s return true else return false endif endmethod public method immediateOrder takes string order returns nothing if .giveOrder("iO") set .s = order endif endmethod public method pointOrder takes string order, real x, real y returns nothing if .giveOrder("pO") set .s = order set .x = x set .y = y endif endmethod public method targetOrder takes string order, widget targetWidget returns nothing if .giveOrder("tO") set .s = order set .tw = targetWidget endif endmethod public method addUnit takes unit u returns nothing set .units[.index] = u set .index = .index + 1 endmethod public method addGroup takes group g returns nothing local unit u loop set u = FirstOfGroup(g) exitwhen u == null call .addUnit(u) call GroupRemoveUnit(g, u) endloop endmethod endstruct endlibrary Steps you need: JASS:local MassOrder mo = MassOrder.create() call mo.addGroup(YourGroup) call mo.pointOrder('smart', pointX, pointY) |
| 10-23-2009, 01:56 PM | #8 |
No, Anachron, that won't work. You need to understand the nature of the bug to understand the nature of how not to induce it. The problem arises from WC3's internal pathing checks. You can have 100 units ordered by the same player without problem if the pathing for their orders is incredibly simple. (Such as straight lines only and no having to check around each other) However, 40 units can cause this bug to occur if the pathing that they're following is incredibly complex. The only solution is to split up ownership of the units, as EF said. Your code will do nothing to help. |
| 10-23-2009, 03:33 PM | #9 |
disable patching for units and control its patch manually. |
| 10-23-2009, 08:39 PM | #10 |
Alright, I'm probably gonna try just rewriting the pathing system. It's gonna be pretty hilarious if this ends up working in bytecode "better" than the native WC3 libraries (on a good processor) due to their limitations... I suppose I can take a couple shortcuts to favor swarming behavior better and perhaps cut down on the operations typically being used. One question, though... Building pathing maps. I'm guessing the IsTerrainPathable function doesn't deal with them, correct? So is placing a dummy unit on the building/checking position the most efficient way to check the pathing maps? I don't mind complexity such as manually preparsing their data or anything, this map is a distraction from doing self-modifying hand-coded assembly... edit: It's a shame that pathing maps are .tga files and WC3 supports images... Except actually getting data from them, only setting and displaying. Anyone messed with this before? Is there a method for directly reading these maps in some niche library? I guess if all else fails, I could parse all the pathing maps into const arrays and just put them directly into JASS. |
| 10-25-2009, 05:12 AM | #11 |
turning pathing off for units wont actually do much (havent tested thoroughly, so this might be wrong, its just what ive seen from that little bit of playing around with it). If you order them to move, they will follow those orders. To my knowledge, theres no way to fix this, besides splitting up ownership (you have 16 players, remember? 12 of them can be humans, leaves 4 that can only be computer controlled). |
| 10-25-2009, 02:11 PM | #12 | |
Quote:
This is true, as far as I can recall. Units who have had their pathing disabled still do path finding. You could turn all units in to flying units with a fly height of 0, but even then they still do some path finding. There is also the issue that when flying units are flying, they will fly in to each other. They only separate when stopped. Really, reducing the number of players your map uses so you can split up ownership further is the only way that will work well enough... |
| 10-25-2009, 06:07 PM | #13 |
I've found that turning off pathing and giving every unit a visible version of ghost turns off enough pathfinding to seriously remove the stuttering problem. They only somewhat move around terrain unwalkable but ignore everything else, and having 500+ units with one player didn't cause probs. Of course, this is completely without trigger based pathing as well. I keep working on other parts of the map besides the A* pathing replacement, but it's almost done. Hopefully it won't be horribly laggy, haha edit: I guess I should add that the A* pathfinding is also coming with collision checks. It'd be pretty dumb to do it otherwise |
| 10-25-2009, 06:45 PM | #14 |
It's the ghost that does it, not really the pathing disabling. The ghost lets units path through the ghosted unit, so they don't have to calculate paths around it instead. I don't really consider that a solution, though, since it looks really lame if your footmen are walking through each other. Anyways, 500+ units on screen at once will cause way more problems with your map than the pathing checks, so be careful. |
| 11-02-2009, 05:24 PM | #15 | |
Quote:
|
