Megapack: kā Factorio izstrādātājiem izdevās atrisināt problēmu ar vairāku spēlētāju spēli 200 spēlētājiem

Megapack: kā Factorio izstrādātājiem izdevās atrisināt problēmu ar vairāku spēlētāju spēli 200 spēlētājiem
Šī gada maijā es piedalījos kā spēlētājs MMO pasākumi KatherineOfSky. Es pamanīju, ka tad, kad spēlētāju skaits sasniedz noteiktu skaitu, ik pēc dažām minūtēm daži no viņiem “nokrīt”. Par laimi tev (bet ne man), es biju viens no tiem spēlētājiem, kas atslēdzās katru reizi, pat ar labu savienojumu. Es to uztvēru kā personisku izaicinājumu un sāku meklēt problēmas cēloņus. Pēc trīs nedēļu ilgas atkļūdošanas, testēšanas un labošanas kļūda beidzot tika novērsta, taču ceļojums nebija tik viegls.

Problēmas ar vairāku spēlētāju spēlēm ir ļoti grūti izsekot. Tie parasti notiek ļoti specifiskos tīkla parametros un ļoti specifiskos spēles apstākļos (šajā gadījumā ar vairāk nekā 200 spēlētājiem). Un pat tad, ja problēmu var atkārtot, to nevar pareizi atkļūdot, jo pārtraukuma punktu ievietošana aptur spēli, sajauc taimerus un parasti izraisa savienojuma taimautu. Bet, pateicoties neatlaidībai un brīnišķīgam rīkam, ko sauc neveikls Man izdevās noskaidrot, kas notiek.

Īsāk sakot, kļūdas un nepilnīgas latentuma stāvokļa simulācijas ieviešanas dēļ klients dažkārt nonāktu situācijā, kad viņam bija jānosūta tīkla pakete, kas sastāv no spēlētāja ievades atlases darbībām aptuveni 400 spēļu entītiju vienā pulksteņa ciklā ( mēs to saucam par "mega-paketi"). Pēc tam serverim ir ne tikai pareizi jāsaņem visas šīs ievades darbības, bet arī jānosūta tās visiem citiem klientiem. Ja jums ir 200 klientu, tas ātri kļūst par problēmu. Saite uz serveri ātri tiek aizsērējusi, izraisot pakešu zudumu un atkārtoti pieprasītu pakešu kaskādi. Ievades darbības aizkavēšana liek vēl vairāk klientu sūtīt megapaketes, izraisot lavīnu, kas kļūst vēl lielāka. Laimīgajiem klientiem izdodas atgūties, pārējie atkrīt.

Megapack: kā Factorio izstrādātājiem izdevās atrisināt problēmu ar vairāku spēlētāju spēli 200 spēlētājiem
Problēma bija diezgan būtiska, un man vajadzēja 2 nedēļas, lai to atrisinātu. Tas ir diezgan tehniski, tāpēc es paskaidrošu sulīgās tehniskās detaļas zemāk. Taču vispirms ir jāzina, ka kopš 0.17.54. jūnijā izdotās versijas 4, saskaroties ar īslaicīgām savienojuma problēmām, vairāku spēlētāju spēle ir kļuvusi stabilāka, un kavēšanās slēpšana ir kļuvusi daudz mazāk kļūdaina (mazāk palēninās un teleportējas). Esmu arī mainījis veidu, kā tiek slēpta cīņas kavēšanās, un es ceru, ka tas padarīs to nedaudz gludāku.

Multiplayer Mega Pack — tehniskā informācija

Vienkārši sakot, vairāku spēlētāju spēle spēlē darbojas šādi: visi klienti simulē spēles stāvokli, saņemot un nosūtot tikai spēlētāja ievadi (sauktas par "ievades darbībām", Ievades darbības). Servera galvenais uzdevums ir pārsūtīšana Ievades darbības un kontrolēt, lai visi klienti veiktu vienas un tās pašas darbības vienā un tajā pašā pulksteņa ciklā. Plašāku informāciju par to varat lasīt ierakstā FFF-149.

Tā kā serverim ir jāpieņem lēmumi par to, kādas darbības veikt, spēlētāja darbības virzās aptuveni pa šo ceļu: spēlētāja darbība -> spēles klients -> tīkls -> serveris -> tīkls -> spēles klients. Tas nozīmē, ka katra spēlētāja darbība tiek veikta tikai pēc tam, kad ir veicis braucienu pa tīklu. Šī iemesla dēļ spēle varētu šķist šausmīgi lēna, tāpēc gandrīz uzreiz pēc vairāku spēlētāju režīma ieviešanas spēlē tika ieviests mehānisms, lai slēptu kavēšanos. Slēpšanas aizkave simulē spēlētāja ievadi, neņemot vērā citu spēlētāju darbības un servera lēmumus.

Megapack: kā Factorio izstrādātājiem izdevās atrisināt problēmu ar vairāku spēlētāju spēli 200 spēlētājiem
Factorio ir spēles stāvoklis Spēles stāvoklis ir pilns kartes, atskaņotāja, entītiju un visa pārējā stāvoklis. Tas tiek deterministiski simulēts visos klientos, pamatojoties uz darbībām, kas saņemtas no servera. Spēles stāvoklis ir svēts, un, ja tas kādreiz sāk atšķirties no servera vai jebkura cita klienta, notiek desinhronizācija.

Bet Spēles stāvoklis mums ir kavēšanās Latenta stāvoklis. Tajā ir neliela pamata stāvokļa apakškopa. Latenta stāvoklis nav svēts un vienkārši atspoguļo priekšstatu par to, kāds spēles stāvoklis izskatīsies nākotnē, pamatojoties uz spēlētāja ievadi Ievades darbības.

Šim nolūkam mēs glabājam izveidotā kopiju Ievades darbības kavēšanās rindā.

Megapack: kā Factorio izstrādātājiem izdevās atrisināt problēmu ar vairāku spēlētāju spēli 200 spēlētājiem
Tas ir, procesa beigās klienta pusē attēls izskatās apmēram šādi:

  1. Pieteikties Ievades darbības visiem spēlētājiem Spēles stāvoklis veids, kā šīs ievades darbības tika saņemtas no servera.
  2. Mēs noņemam visu no kavēšanās rindas Ievades darbības, kas, pēc servera domām, jau ir pielietoti Spēles stāvoklis.
  3. Noņemt Latenta stāvoklis un atiestatiet to, lai tas izskatās tieši tāpat kā Spēles stāvoklis.
  4. Mēs piemērojam visas darbības no aizkaves rindas līdz Latenta stāvoklis.
  5. Pamatojoties uz datiem Spēles stāvoklis и Latenta stāvoklis Mēs atdodam spēli spēlētājam.

Tas viss atkārtojas katrā mērā.

Pārāk grūts? Neatslābsti, tas vēl nav viss. Lai kompensētu neuzticamus interneta savienojumus, esam izveidojuši divus mehānismus:

  • Neatbildēti atzīmes: kad serveris to nolemj Ievades darbības tiks izpildīts spēles sitienā, tad, ja nesaņēma Ievades darbības kāds spēlētājs (piemēram, palielinātas kavēšanās dēļ), viņš negaidīs, bet informēs šo klientu “Es neņēmu vērā jūsu Ievades darbības, es mēģināšu tos pievienot nākamajā joslā. Tas tiek darīts, lai viena spēlētāja savienojuma (vai datora) problēmu dēļ kartes atjaunināšana nepalēninātu visiem pārējiem. Ir vērts to atzīmēt Ievades darbības netiek ignorēti, bet vienkārši nolikti malā.
  • Pilns turp un atpakaļ latentums: serveris mēģina uzminēt, kāds ir katra klienta turp un atpakaļ latentums starp klientu un serveri. Ik pēc 5 sekundēm tas vajadzības gadījumā vienojas par jaunu latentumu ar klientu (pamatojoties uz to, kā savienojums ir izturējies iepriekš), un attiecīgi palielina vai samazina turp un atpakaļ latentumu.

Atsevišķi šie mehānismi ir diezgan vienkārši, taču, tos lietojot kopā (kas bieži notiek ar savienojuma problēmām), koda loģika kļūst grūti pārvaldāma un ar daudziem malas gadījumiem. Turklāt, kad šie mehānismi sāk darboties, serverim un aizkaves rindai ir pareizi jāievieš īpašais Ievades darbība aicināja StopMovementInTheNextTick. Pateicoties tam, ja rodas problēmas ar savienojumu, varonis neskrien pats (piemēram, vilciena priekšā).

Tagad mums ir jāpaskaidro, kā darbojas entītiju atlase. Viens no pārraidītajiem veidiem Ievades darbība ir entītijas atlases stāvokļa izmaiņas. Tas visiem norāda, virs kuras entītijas spēlētājs virza kursoru. Kā jau varat iedomāties, šī ir viena no visbiežāk izmantotajām ievades darbībām, ko sūta klienti, tāpēc, lai ietaupītu joslas platumu, esam to optimizējuši, lai aizņemtu pēc iespējas mazāk vietas. Tas darbojas šādi: kad tiek atlasīta katra entītija, tā vietā, lai saglabātu absolūtas augstas precizitātes kartes koordinātas, spēle saglabā zemas precizitātes relatīvo nobīdi no iepriekšējās atlases. Tas darbojas labi, jo peles atlases parasti ir ļoti tuvas iepriekšējai atlasei. Tas izvirza divas svarīgas prasības: Ievades darbības Tos nekad nedrīkst izlaist, un tie ir jāaizpilda pareizā secībā. Šīs prasības ir izpildītas Spēles stāvoklis. Bet kopš uzdevuma Latenta stāvoklis Spēlētājam "izskatās pietiekami labi", viņi nav apmierināti ar kavēšanos. Latenta stāvoklis neņem vērā daudzi malas gadījumi, kas saistīts ar pulksteņa ciklu izlaišanu un pārraides kavējumu maiņu turp un atpakaļ.

Jūs jau varat uzminēt, kur tas notiek. Mēs beidzot sākam redzēt megapakas problēmas iemeslus. Problēmas pamatā ir entītiju atlases loģika Latenta stāvoklis, un šis stāvoklis ne vienmēr satur pareizo informāciju. Tāpēc tiek ģenerēta megapakete, kas līdzinās šim:

  1. Atskaņotājam ir savienojuma problēmas.
  2. Tiek izmantoti mehānismi pulksteņa ciklu izlaišanai un turp un atpakaļ pārraides aizkaves regulēšanai.
  3. Aizkaves stāvokļa rindā šie mehānismi netiek ņemti vērā. Tādējādi dažas darbības tiek priekšlaicīgi noņemtas vai veiktas nepareizā secībā, kā rezultātā tiek veiktas nepareizas darbības Latenta stāvoklis.
  4. Spēlētājam ir savienojuma problēma un, lai panāktu serveri, viņš simulē līdz 400 cikliem.
  5. Pie katras atzīmes tiek ģenerēta jauna darbība, mainot entītijas atlasi, un sagatavota nosūtīšanai uz serveri.
  6. Klients nosūta uz serveri 400+ entītiju atlases izmaiņu mega partiju (un ar citām darbībām: fotografēšanas stāvokļi, pastaigas stāvokļi utt. arī cieta no šīs problēmas).
  7. Serveris saņem 400 ievades darbības. Tā kā nav atļauts izlaist ievades darbības, tas liek visiem klientiem veikt šīs darbības un nosūta tās pa tīklu.

Ironija ir tāda, ka mehānisms, kas paredzēts joslas platuma taupīšanai, radīja milzīgas tīkla paketes.

Mēs novērsām šo problēmu, labojot visus atjaunināšanas un atpalikušo rindu atbalsta malas gadījumus. Lai gan tas prasīja diezgan daudz laika, galu galā bija vērts to sakārtot, nevis paļauties uz ātriem uzlaušanas gadījumiem.

Avots: www.habr.com

Pievieno komentāru