Megapaketas: kaip Factorio kūrėjai išsprendė kelių žaidėjų 200 žaidėjų problemą

Megapaketas: kaip Factorio kūrėjai išsprendė kelių žaidėjų 200 žaidėjų problemą
Šių metų gegužę dalyvavau kaip žaidėjas KatherineOfSky MMO renginiai. Pastebėjau, kad žaidėjų skaičiui pasiekus tam tikrą skaičių, kas kelias minutes dalis jų „nukrenta“. Tavo laimei (bet ne man), aš buvau vienas iš tų žaidėjų kiekvieną kartąnet ir esant geram ryšiui. Priėmiau tai kaip asmeninį iššūkį ir pradėjau ieškoti problemos priežasčių. Po trijų savaičių derinimo, testavimo ir taisymo klaida pagaliau ištaisyta, tačiau kelionė nebuvo tokia lengva.

Kelių žaidėjų žaidimų problemas labai sunku atsekti. Paprastai jie atsiranda esant labai specifiniams tinklo parametrams ir labai specifinėms žaidimo būsenoms (šiuo atveju daugiau nei 200 žaidėjų). Ir net kai problema gali būti atkurta, ji negali būti tinkamai derinama, nes įterpus lūžio taškus žaidimas sustabdomas, supainiojami laikmačiai ir dažniausiai dėl skirtojo laiko nutrūksta ryšys. Tačiau dėka atkaklumo ir nuostabaus įrankio, vadinamo gremėzdiškas Man pavyko išsiaiškinti, kas vyksta.

Trumpai tariant, dėl klaidos ir nepilno delsos būsenos modeliavimo įgyvendinimo klientas kartais atsidūrė situacijoje, kai per vieną laikrodžio ciklą turėjo išsiųsti tinklo paketą, susidedantį iš žaidėjo įvesties veiksmų, kad būtų galima pasirinkti maždaug 400 žaidimo objektų ( vadiname „megapaketu“). Po to serveris turi ne tik teisingai gauti visus šiuos įvesties veiksmus, bet ir siųsti juos visiems kitiems klientams. Jei turite 200 klientų, tai greitai tampa problema. Kanalas į serverį greitai užsikemša, todėl prarandami paketai ir iš naujo užklausų paketų. Atidėjus įvesties veiksmus, daugiau klientų pradeda siųsti megapaketus, o jų lavina dar labiau sustiprėja. Sėkmingi klientai sugeba pasveikti, visi kiti atkrenta.

Megapaketas: kaip Factorio kūrėjai išsprendė kelių žaidėjų 200 žaidėjų problemą
Problema buvo gana esminė ir man prireikė 2 savaičių ją išspręsti. Tai gana techniška, todėl toliau paaiškinsiu sultingas technines detales. Tačiau pirmiausia turite žinoti, kad nuo 0.17.54 versijos, išleistos birželio 4 d., susidūrus su laikinomis ryšio problemomis, kelių žaidėjų režimas tapo stabilesnis, o slėpimo uždelsimas yra daug mažiau klaidingas (mažiau stabdomas ir teleportuojamas). Be to, pakeičiau kovos vėlavimų slėpimo būdą ir tikiuosi, kad tai padarys juos šiek tiek sklandžiau.

Kelių žaidėjų mega paketas – techninė informacija

Paprasčiau tariant, kelių žaidėjų režimas žaidime veikia taip: visi klientai imituoja žaidimo būseną, gaudami ir siųsdami tik žaidėjo įvestį (vadinamą „įvesties veiksmais“). Įvesties veiksmai). Pagrindinė serverio užduotis yra perduoti Įvesties veiksmai ir užtikrinti, kad visi klientai atliktų tuos pačius veiksmus tame pačiame cikle. Plačiau apie tai galite perskaityti įraše. FFF-149.

Kadangi serveris turi priimti sprendimus, kokių veiksmų imtis, žaidėjo veiksmai juda tokiu keliu: žaidėjo veiksmas -> žaidimo klientas -> tinklas -> serveris -> tinklas -> žaidimo klientas. Tai reiškia, kad kiekvienas žaidėjo veiksmas atliekamas tik tada, kai jis nukeliauja per tinklą. Dėl šios priežasties žaidimas atrodė siaubingai lėtas, todėl beveik iš karto po kelių žaidėjų pasirodymo žaidime buvo įvestas vėlavimų slėpimo mechanizmas. Latentinis slėpimas imituoja žaidėjo įvestį, neatsižvelgiant į kitų žaidėjų veiksmus ir serverio sprendimų priėmimą.

Megapaketas: kaip Factorio kūrėjai išsprendė kelių žaidėjų 200 žaidėjų problemą
Factorio turi žaidimo būseną žaidimo būsena yra visa žemėlapio, grotuvo, objektų ir viso kito būsena. Jis deterministiškai imituojamas visuose klientuose, remiantis iš serverio gautais veiksmais. Žaidimo būsena yra šventa, ir jei ji kada nors pradeda skirtis nuo serverio ar bet kurio kito kliento, tada įvyksta desinchronizacija.

Bet žaidimo būsena pas mus vėluojama Latentinė būsena. Jame yra nedidelis pagrindinės būsenos poaibis. Latentinė būsena nėra šventas ir tik vaizduoja, kaip žaidimo būsena atrodys ateityje, remiantis žaidėjo įvestimis Įvesties veiksmai.

Norėdami tai padaryti, saugome sukurtos kopijos Įvesties veiksmai vėlavimo eilėje.

Megapaketas: kaip Factorio kūrėjai išsprendė kelių žaidėjų 200 žaidėjų problemą
Tai yra, proceso pabaigoje kliento pusėje paveikslėlis atrodo maždaug taip:

  1. Taikyti Įvesties veiksmai visi žaidėjai žaidimo būsena kaip šie įvesties veiksmai buvo gauti iš serverio.
  2. Pašalinkite viską iš vėlavimo eilės Įvesties veiksmai, kurioms, pasak serverio, jau buvo pritaikyta žaidimo būsena.
  3. Ištrinti Latentinė būsena ir iš naujo nustatykite, kad atrodytų lygiai taip pat kaip žaidimo būsena.
  4. Taikykite visus veiksmus nuo delsos eilės iki Latentinė būsena.
  5. Remiantis duomenimis žaidimo būsena и Latentinė būsena perteikti žaidimą žaidėjui.

Visa tai kartojasi kiekvienu būdu.

Per sunku? Neatsipalaiduokite, tai dar ne viskas. Norėdami kompensuoti nepatikimus interneto ryšius, sukūrėme du mechanizmus:

  • Praleistos varnelės: kai serveris tai nusprendžia Įvesties veiksmai bus įvykdytas žaidimo taktu, tada, jei jis negavo Įvesties veiksmai koks nors žaidėjas (pavyzdžiui, dėl padidėjusio vėlavimo), jis nelauks, o informuos šį klientą „Neatsižvelgiau į jūsų Įvesties veiksmai, pabandysiu juos įtraukti kitoje juostoje. Tai daroma tam, kad dėl vieno žaidėjo ryšio (ar kompiuterio) problemų žemėlapio atnaujinimas nesulėtėtų visiems kitiems. Verta pažymėti, kad Įvesties veiksmai nėra ignoruojami, o tiesiog atidedami.
  • Visas delsos pirmyn ir atgal: serveris bando atspėti, kokia yra kiekvieno kliento kelionės pirmyn ir atgal delsa tarp kliento ir serverio. Kas 5 sekundes ji derasi su klientu dėl naujo vėlavimo pagal poreikį (atsižvelgiant į tai, kaip ryšys elgėsi praeityje), ir atitinkamai padidina arba sumažina kelionės į abi puses delsą.

Patys savaime šie mechanizmai yra gana paprasti, tačiau juos naudojant kartu (tai dažnai nutinka esant ryšio problemoms), kodo logika tampa sunkiai valdoma ir su daugybe kraštutinių atvejų. Be to, pradėjus veikti šiems mechanizmams, serveris ir delsos eilė turi tinkamai įgyvendinti specialųjį Įvesties veiksmas vadinamas StopMovementInTheNextTick. Dėl to, kilus ryšio problemoms, veikėjas nebėgs pats (pavyzdžiui, po traukiniu).

Dabar turiu jums paaiškinti, kaip veikia subjekto pasirinkimas. Vienas iš išlaikytų tipų Įvesties veiksmas yra objekto pasirinkimo būsenos pasikeitimas. Jis visiems nurodo, ant kurio objekto žaidėjas užvedė pelę. Kaip matote, tai vienas iš dažniausiai klientų siunčiamų įvesties veiksmų, todėl taupydami pralaidumą jį optimizavome taip, kad užimtų kuo mažiau vietos. Tai įgyvendinama taip: kai pasirenkamas kiekvienas objektas, užuot saugojęs absoliučias didelio tikslumo žemėlapio koordinates, žaidimas išsaugo žemo tikslumo santykinį poslinkį nuo ankstesnio pasirinkimo. Tai veikia gerai, nes pelės pasirinkimas paprastai vyksta labai arti ankstesnio pasirinkimo. Tai kelia du svarbius reikalavimus: Įvesties veiksmai niekada neturėtų būti praleistas ir turi būti atliktas teisinga tvarka. Šie reikalavimai yra įvykdyti žaidimo būsena. Bet kadangi užduotis latentinė būsena „Pakankamai gerai atrodo“ žaidėjui, jie nėra patenkinti vėlavimo būsena. Latentinė būsena neatsižvelgia daug ribinių atvejųsusiję su laikrodžių praleidimu ir perdavimo vėlavimų keitimu pirmyn ir atgal.

Jau galite atspėti, kur tai vyksta. Galiausiai pradedame matyti megapaketo problemos priežastis. Problemos esmė ta, kad subjekto pasirinkimo logika remiasi Latentinė būsena, ir šioje būsenoje ne visada yra teisinga informacija. Taigi megapaketas generuojamas taip:

  1. Žaidėjui kyla ryšio problemų.
  2. Įsijungia ciklų praleidimo ir perdavimo atgalinio perdavimo delsos reguliavimo mechanizmai.
  3. Vėlavimo būsenos eilė neatsižvelgia į šiuos mechanizmus. Dėl to kai kurie veiksmai pašalinami anksčiau laiko arba atliekami netinkama tvarka, todėl atliekami neteisingi Latentinė būsena.
  4. Grotuvas neturi ryšio problemų ir imituoja iki 400 ciklų, kad pasivytų serverį.
  5. Kiekviename cikle sugeneruojamas ir paruošiamas siųsti į serverį naujas veiksmas, keičiantis objekto pasirinkimą.
  6. Klientas siunčia į serverį 400+ objektų pasirinkimo pakeitimų megapaketą (ir su kitais veiksmais: suaktyvinimo būsena, ėjimo būsena ir tt taip pat nukentėjo nuo šios problemos).
  7. Serveris gauna 400 įvesties veiksmų. Kadangi neleidžiama praleisti vieno įvesties veiksmo, jis nurodo visiems klientams atlikti šiuos veiksmus ir siunčia juos per tinklą.

Ironiška tai, kad pralaidumui taupyti skirtas mechanizmas lėmė didžiulius tinklo paketus.

Išsprendėme šią problemą ištaisydami visus atnaujinimo kraštus ir delsos eilės palaikymą. Nors tai užtruko nemažai laiko, galiausiai verta tai padaryti teisingai, o ne pasikliauti greitais įsilaužimais.

Šaltinis: www.habr.com

Добавить комментарий