fa icon indicating copy to clipboard operation
fa copied to clipboard

Rework how formations are computed

Open Garanas opened this issue 1 year ago • 12 comments

While looking at how selections work I stumbled upon formations. It was an intriguing find, not only do we have full control over the behavior of formations but the existing implementation sets the garbage collector on fire.

When are formations applied

The first interesting find is that formations are computed often. So often in fact that I would consider it a hot spot. It triggers when:

  • (1) A player issues an order that may involve movement. These orders apply the attack or growth formations depending on the preference of the user
  • (2) A unit that is on guard and another unit leaves or joins the guard order
  • (3) The formation orders via script issue a formation

Another interesting find is that the formation are computed twice. It is computed once in UI and then another time in the simulation. It is computed in the UI to generate a preview. It is computed in the sim to apply the formation in the simulation.

And last but not least, an interesting combination is the Cybran build drone with (2). Build drones issue guard commands separately and therefore each time a Cybran engineer starts/stops assisting a construction the guard formation needs to be recomputed. These drones entirely ignore the guard formation but the guard formation is recomputed in the simulation.

The costs of computing a formation

In the existing implementation there are two relevant costs:

  • (1) For attack and growth formations there's a flat cost of about 5kb of memory allocation regardless of the size of the selection.
  • (2) For attack and growth formations the computations to create the formation are complicated and computationally expensive.
  • (3) Formations scale over the size of the selection. This makes sense for the output (as you need to map every unit to an offset) but it does not make sense for the intermediate computations. The computations rely on the footprint and the categories of a unit. Those are the same for all units of the same type.

Because formations are computed twice the costs are doubled - it is computed in the UI (for the player on the local machine) and in the simulation (for every order that involves some movement from all players and/or script).

more to come

Garanas avatar Feb 16 '24 20:02 Garanas

I noticed that when units in formation are given a formation facing in the opposite direction, one unit from the front tries to go to a position near the new front, when it should be going to a position in the near back. Is this possible to fix here?

https://github.com/FAForever/fa/assets/82986251/cbaa247b-33d1-4bdb-a4e2-7ffb73c19e03

Seems like since the front row has more units than the back, it has to grab 1 unit from the back to place in the front row, but it places that unit right in the middle of the front row instead of the closest position in the front row.

lL1l1 avatar Feb 17 '24 02:02 lL1l1

That's engine behavior I'm afraid. All we can tell the engine is what category a given position should have, not what specific unit should end up there.

For my idea, how do you enable that path finding preview?

Garanas avatar Feb 17 '24 07:02 Garanas

how do you enable that path finding preview?

Console commands dbg NavWaypoints, dbg NavSteering, and dbg NavPath or, since dbg autocompletes, just dbg navw dbg navs dbg navp.

lL1l1 avatar Feb 17 '24 09:02 lL1l1

image

image

image

Garanas avatar Feb 26 '24 19:02 Garanas

Now we need to take into account the footprint somehow 😃 !

Garanas avatar Feb 26 '24 19:02 Garanas

Some initial data on the performance. For roughly 800 units (600 direct fire, 80 anti air, 50 scouts, 80 artillery):

  • New growth formation: roughly 1.0 - 1.5 milliseconds
  • Old attack formation: roughly 7.0 - 8.0 milliseconds

Note that a the simulation has a budget 100 milliseconds before the simulation slows down. And the UI has a budget of 16 milliseconds before your frame rate dips below 60fps!

Garanas avatar Feb 27 '24 20:02 Garanas

Interesting enough, in this game of 52 minutes:

  • https://replay.faforever.com/21942580

You can observe the following formation counts:

  • GuardFormation: +/- 11.000 which is +/- 211 a minute
  • AttackFormation: +/- 2.800 which is +/- 53 a minute
  • GrowthFormation: +/- 700 which is +/- 13 a minute

The guard formation explodes because of the Cybran build drones ( @zhanghm18 ). It's called so often that it triggers almost four times per second 😃

And for this 38 minutes of replay:

  • https://replay.faforever.com/21924449

  • GuardFormation: +/- 6000 which is +/- 157 a minute

  • AttackFormation: +/- 7300 which is +/- 189 a minute (!!)

  • GrowthFormation: +/- 300 which is +/- 8 a minute

Garanas avatar Feb 28 '24 20:02 Garanas

image

Garanas avatar Mar 02 '24 13:03 Garanas

image

Garanas avatar Mar 03 '24 10:03 Garanas

With features such as https://forum.faforever.com/topic/7351/ctrl-ui-mod this becomes even more relevant 😃

Garanas avatar Mar 23 '24 16:03 Garanas

There's an interesting engine bug with the Guard formation: usually they map fine when the unit (that is being guarded) is on the move but when the unit rotates across some threshold then suddenly all units are mapped completely differently, causing a lot of path finding pain:

https://github.com/FAForever/fa/assets/15778155/300a0317-fa2e-4294-8e49-9b8b275bc8e6

At first I thought it was related to the spiral pattern that I want to introduce:

https://github.com/FAForever/fa/assets/15778155/1e825212-116a-4125-af70-fa12f58e714c

But it occurs, regardless of the pattern.

Garanas avatar Mar 27 '24 17:03 Garanas

First working examples of sub-formations:

https://github.com/FAForever/fa/assets/15778155/fe654bc5-86e5-4fbf-94d6-f33735b447ee

https://github.com/FAForever/fa/assets/15778155/9e3ce00a-0f99-4249-9c7a-68e6fd6a8d9d

image

Garanas avatar Mar 29 '24 21:03 Garanas