Kā mēs uzlabojām ballistisko aprēķinu mehāniku mobilajam Ŕāvējam ar tÄ«kla latentuma kompensācijas algoritmu

Kā mēs uzlabojām ballistisko aprēķinu mehāniku mobilajam Ŕāvējam ar tÄ«kla latentuma kompensācijas algoritmu

Sveiki, es esmu Ņikita Brižaks, serveru izstrādātājs no Pixonic. Å odien es vēlos runāt par nobÄ«des kompensÄ“Å”anu mobilajā vairāku spēlētāju spēlē.

Par servera kavÄ“Å”anās kompensāciju ir rakstÄ«ti daudzi raksti, arÄ« krievu valodā. Tas nav pārsteidzoÅ”i, jo Ŕī tehnoloÄ£ija ir aktÄ«vi izmantota vairāku spēlētāju FPS izveidē kopÅ” 90. gadu beigām. Piemēram, jÅ«s varat atcerēties QuakeWorld mod, kas bija viens no pirmajiem, kas to izmantoja.

Mēs to izmantojam arÄ« savā mobilajā vairāku spēlētāju Ŕāvējā Dino Squad.

Å ajā rakstā mans mērÄ·is nav atkārtot to, kas jau ir rakstÄ«ts tÅ«kstoÅ” reižu, bet gan pastāstÄ«t, kā mēs savā spēlē ieviesām nobÄ«des kompensāciju, ņemot vērā mÅ«su tehnoloÄ£iju steku un spēles galvenās funkcijas.

Daži vārdi par mūsu garozu un tehnoloģijām.

Dino Squad ir tÄ«kla mobilā PvP Ŕāvēja. Spēlētāji kontrolē dinozaurus, kas aprÄ«koti ar dažādiem ieročiem, un cÄ«nās savā starpā 6 pret 6 komandās.

Gan klients, gan serveris ir balstÄ«ti uz Unity. ArhitektÅ«ra ir diezgan klasiska Ŕāvējiem: serveris ir autoritārs, un klienta prognozÄ“Å”ana darbojas uz klientiem. Spēles simulācija ir uzrakstÄ«ta, izmantojot iekŔējo ECS, un tiek izmantota gan serverÄ«, gan klientā.

Ja Ŕī ir pirmā reize, kad dzirdat par kavējuma kompensāciju, Å”eit ir Ä«ss ieskats Å”ajā jautājumā.

Vairāku spēlētāju FPS spēlēs mačs parasti tiek simulēts attālā serverÄ«. Spēlētāji nosÅ«ta savu ievadi (informāciju par nospiestajiem taustiņiem) serverim, un, atbildot uz to, serveris nosÅ«ta viņiem atjauninātu spēles stāvokli, ņemot vērā saņemtos datus. Izmantojot Å”o mijiedarbÄ«bas shēmu, aizkave starp pogas uz priekÅ”u nospieÅ”anu un brÄ«di, kad spēlētāja varonis pārvietojas uz ekrāna, vienmēr bÅ«s lielāka nekā ping.

Kamēr lokālajos tÄ«klos Ŕī aizkave (tautā saukta ievades aizkave) var bÅ«t nepamanāma, spēlējot internetā, tā rada ā€œslÄ«dÄ“Å”anas pa leduā€ sajÅ«tu, kontrolējot tēlu. Å Ä« problēma ir divtik aktuāla mobilajiem tÄ«kliem, kur par lielisku savienojumu joprojām tiek uzskatÄ«ts gadÄ«jums, kad spēlētāja ping ir 200 ms. Bieži vien ping var bÅ«t 350, 500 vai 1000 ms. Tad kļūst gandrÄ«z neiespējami spēlēt ātro Ŕāvēju ar ievades nobÄ«di.

Å Ä«s problēmas risinājums ir klienta puses simulācijas prognozÄ“Å”ana. Å eit klients pats piemēro ievadi spēlētāja varonim, negaidot atbildi no servera. Un, kad tiek saņemta atbilde, tā vienkārÅ”i salÄ«dzina rezultātus un atjaunina pretinieku pozÄ«cijas. Aizkave starp taustiņa nospieÅ”anu un rezultāta parādÄ«Å”anu ekrānā Å”ajā gadÄ«jumā ir minimāla.

Å eit ir svarÄ«gi saprast niansi: klients vienmēr zÄ«mē sevi pēc pēdējās ievades, bet ienaidnieki - ar tÄ«kla aizkavi, saskaņā ar iepriekŔējo stāvokli no servera datiem. Tas ir, Å”aujot uz ienaidnieku, spēlētājs redz viņu pagātnē attiecÄ«bā pret sevi. Vairāk par klientu prognozÄ“Å”anu mēs rakstÄ«jām iepriekÅ”.

Tādējādi klienta prognozÄ“Å”ana atrisina vienu problēmu, bet rada citu: ja spēlētājs Å”auj vietā, kur agrāk bija ienaidnieks, serverÄ«, Å”aujot tajā paŔā punktā, ienaidnieks var vairs neatrasties Å”ajā vietā. Servera kavÄ“Å”anās kompensācija mēģina atrisināt Å”o problēmu. Kad tiek izÅ”auts ierocis, serveris atjauno spēles stāvokli, ko spēlētājs redzēja lokāli Ŕāviena brÄ«dÄ«, un pārbauda, ā€‹ā€‹vai viņŔ tieŔām varēja trāpÄ«t ienaidniekam. Ja atbilde ir ā€œjāā€, trāpÄ«jums tiek ieskaitÄ«ts, pat ja ienaidnieks tajā brÄ«dÄ« vairs neatrodas serverÄ«.

Izmantojot Ŕīs zināŔanas, mēs sākām ieviest servera kavÄ“Å”anās kompensāciju Dino Squad. Pirmkārt, mums bija jāsaprot, kā serverÄ« atjaunot to, ko klients redzēja? Un kas tieÅ”i ir jāatjauno? MÅ«su spēlē ieroču un spēju trāpÄ«jumi tiek aprēķināti, izmantojot staru pārraides un pārklājumus, tas ir, mijiedarbojoties ar ienaidnieka fiziskajiem sadursmēm. AttiecÄ«gi mums vajadzēja reproducēt Å”o sadursmju pozÄ«ciju, ko spēlētājs ā€œredzējaā€ lokāli, serverÄ«. Tajā laikā mēs izmantojām Unity versiju 2018.x. Fizikas API tur ir statiska, fiziskā pasaule pastāv vienā eksemplārā. Nav iespējams saglabāt tā stāvokli un pēc tam atjaunot to no kastes. Tātad, ko darÄ«t?

Risinājums bija uz virsmas; visus tā elementus mēs jau izmantojām citu problēmu risināŔanai:

  1. Katram klientam mums ir jāzina, kurā brÄ«dÄ« viņŔ redzēja pretiniekus, nospiežot taustiņus. Mēs jau esam ierakstÄ«juÅ”i Å”o informāciju ievades pakotnē un izmantojām to, lai pielāgotu klienta prognozi.
  2. Mums ir jāspēj saglabāt spēļu stāvokļu vēsturi. TieÅ”i tajā mēs noturēsim pretinieku (un lÄ«dz ar to arÄ« viņu sadursmju) pozÄ«cijas. Mums serverÄ« jau bija valsts vēsture, mēs to izmantojām, lai izveidotu deltas. Zinot pareizo laiku, mēs varētu viegli atrast pareizo stāvokli vēsturē.
  3. Tagad, kad mums ir pieejams spēles stāvoklis no vēstures, mums ir jāspēj sinhronizēt spēlētāju datus ar fiziskās pasaules stāvokli. EsoÅ”ie kolÄ«deri - pārvietojiet, trÅ«kstoÅ”ie - izveidojiet, nevajadzÄ«gie - iznÄ«ciniet. ArÄ« Ŕī loÄ£ika jau bija uzrakstÄ«ta un sastāvēja no vairākām ECS sistēmām. Mēs to izmantojām, lai vienā Unity procesā rÄ«kotu vairākas spēļu istabas. Un tā kā fiziskā pasaule katram procesam ir viena, tā bija atkārtoti jāizmanto starp telpām. Pirms katras simulācijas atzÄ«mÄ“Å”anas mēs "atiestatÄ«jām" fiziskās pasaules stāvokli un atkārtoti to inicializējām ar paÅ”reizējās telpas datiem, cenÅ”oties pēc iespējas vairāk izmantot Unity spēles objektus, izmantojot gudru apvienoÅ”anas sistēmu. Atlika tikai atsaukties uz to paÅ”u pagātnes spēles stāvokļa loÄ£iku.

Saliekot visus Å”os elementus kopā, mēs ieguvām ā€œlaika maŔīnuā€, kas varētu atgriezt fiziskās pasaules stāvokli uz pareizo brÄ«di. Kods izrādÄ«jās vienkārÅ”s:

public class TimeMachine : ITimeMachine
{
     //Š˜ŃŃ‚Š¾Ń€Šøя ŠøŠ³Ń€Š¾Š²Ń‹Ń… сŠ¾ŃŃ‚Š¾ŃŠ½ŠøŠ¹
     private readonly IGameStateHistory _history;

     //Š¢ŠµŠŗущŠµŠµ ŠøŠ³Ń€Š¾Š²Š¾Šµ сŠ¾ŃŃ‚Š¾ŃŠ½ŠøŠµ Š½Š° сŠµŃ€Š²ŠµŃ€Šµ
     private readonly ExecutableSystem[] _systems;

     //ŠŠ°Š±Š¾Ń€ сŠøстŠµŠ¼, рŠ°ŃŃŃ‚Š°Š²Š»ŃŃŽŃ‰Šøх ŠŗŠ¾Š»Š»Š°Š¹Š“ŠµŃ€Ń‹ Š² фŠøŠ·ŠøчŠµŃŠŗŠ¾Š¼ Š¼ŠøрŠµ 
     //ŠæŠ¾ Š“Š°Š½Š½Ń‹Š¼ ŠøŠ· ŠøŠ³Ń€Š¾Š²Š¾Š³Š¾ сŠ¾ŃŃ‚Š¾ŃŠ½Šøя
     private readonly GameState _presentState;

     public TimeMachine(IGameStateHistory history, GameState presentState, ExecutableSystem[] timeInitSystems)
     {
         _history = history; 
         _presentState = presentState;
         _systems = timeInitSystems;  
     }

     public GameState TravelToTime(int tick)
     {
         var pastState = tick == _presentState.Time ? _presentState : _history.Get(tick);
         foreach (var system in _systems)
         {
             system.Execute(pastState);
         }
         return pastState;
     }
}

Atlika tikai izdomāt, kā izmantot Å”o maŔīnu, lai viegli kompensētu kadrus un spējas.

VienkārŔākajā gadÄ«jumā, kad mehānika ir balstÄ«ta uz vienu trāpÄ«jumu skenÄ“Å”anu, Ŕķiet, ka viss ir skaidrs: pirms spēlētājs Å”auj, viņam ir jāatgriež fiziskā pasaule vēlamajā stāvoklÄ«, jāveic raycast, jāuzskaita sitiens vai netrāpÄ«jums un atgriezt pasauli sākotnējā stāvoklÄ«.

Bet tādu mehāniÄ·u Dino Squad ir ļoti maz! Lielākā daļa spēlē esoÅ”o ieroču rada Ŕāviņus - ilgstoÅ”as ā€‹ā€‹lodes, kas lido pēc vairākām simulācijas ērcēm (dažos gadÄ«jumos desmitiem ērču). Ko ar viņiem darÄ«t, cikos viņiem vajadzētu lidot?

Š’ sens raksts par Half-Life tÄ«kla steku puiÅ”i no Valve uzdeva to paÅ”u jautājumu, un viņu atbilde bija Ŕāda: Ŕāviņa lag kompensācija ir problemātiska, un no tā labāk izvairÄ«ties.

Mums nebija Ŕīs iespējas: uz Ŕāviņiem balstÄ«ti ieroči bija galvenā spēles dizaina iezÄ«me. Tāpēc mums bija kaut kas jāizdomā. Pēc nelielas prāta vētras mēs formulējām divas iespējas, kas, Ŕķiet, darbojas:

1. Mēs piesienam Ŕāviņu tā spēlētāja laikam, kurÅ” to izveidoja. Katrs servera simulācijas Ä·eksÄ«tis, katra spēlētāja katra lode, mēs atgriezÄ«sim fizisko pasauli uz klienta stāvokli un veicam nepiecieÅ”amos aprēķinus. Å Ä« pieeja ļāva nodroÅ”ināt sadalÄ«tu slodzi uz serveri un paredzamu Ŕāviņu lidojuma laiku. PrognozējamÄ«ba mums bija Ä«paÅ”i svarÄ«ga, jo mums ir visi lādiņi, tostarp ienaidnieka lādiņi, prognozēti uz klienta.

Kā mēs uzlabojām ballistisko aprēķinu mehāniku mobilajam Ŕāvējam ar tÄ«kla latentuma kompensācijas algoritmu
Attēlā spēlētājs ar atzÄ«mi 30, gaidot, izÅ”auj raÄ·eti: viņŔ redz, kurā virzienā skrien ienaidnieks, un zina aptuveno raÄ·etes ātrumu. Lokāli viņŔ redz, ka trāpÄ«ja mērÄ·Ä« pie 33. Ä·eksÄ«Å”a. Pateicoties nobÄ«des kompensācijai, tas parādÄ«sies arÄ« serverÄ«

2. Darām visu tāpat kā pirmajā variantā, bet, saskaitot vienu lodes simulācijas Ä·eksÄ«ti, neapstājamies, bet turpinām simulēt tā lidojumu viena servera Ä·eksÄ«Å”a ietvaros, katru reizi tuvinot tā laiku serverim pa vienam atzÄ«mējiet un atjauniniet sadursmju pozÄ«cijas. Mēs to darām, lÄ«dz notiek viena no divām lietām:

  • Lodei ir beidzies derÄ«guma termiņŔ. Tas nozÄ«mē, ka aprēķini ir beiguÅ”ies, varam skaitÄ«t garām vai sitienu. Un tas ir pie tās paÅ”as Ä·eksÄ«Å”a, kurā tika izdarÄ«ts Ŕāviens! Mums tas bija gan pluss, gan mÄ«nuss. Pluss - jo Ŕāvējam tas ievērojami samazināja aizkavi starp sitienu un ienaidnieka veselÄ«bas samazināŔanos. NegatÄ«vā puse ir tāda, ka tas pats efekts tika novērots, kad pretinieki Ŕāva uz spēlētāju: Ŕķiet, ka ienaidnieks izŔāva tikai lēnu raÄ·eti, un bojājumi jau bija ieskaitÄ«ti.
  • Lode ir sasniegusi servera laiku. Å ajā gadÄ«jumā tā simulācija turpināsies nākamajā servera atzÄ«mÄ“Å”anā bez kavÄ“Å”anās kompensācijas. Lēniem Ŕāviņiem tas teorētiski varētu samazināt fizikas apgāŔanās skaitu salÄ«dzinājumā ar pirmo iespēju. Tajā paŔā laikā palielinājās nevienmērÄ«ga simulācijas slodze: serveris vai nu darbojās dÄ«kstāvē, vai arÄ« vienā servera Ä·eksÄ« aprēķināja duci simulācijas ērču vairākām aizzÄ«mēm.

Kā mēs uzlabojām ballistisko aprēķinu mehāniku mobilajam Ŕāvējam ar tÄ«kla latentuma kompensācijas algoritmu
Tas pats scenārijs kā iepriekŔējā attēlā, bet aprēķināts pēc otrās shēmas. RaÄ·ete ā€œpaķēraā€ servera laiku tajā paŔā Ä·eksÄ«Å”a brÄ«dÄ«, kad notika Ŕāviens, un trāpÄ«jumu var ieskaitÄ«t jau ar nākamo Ä·eksÄ«ti. Pie 31. Ä·eksÄ«Å”a Å”ajā gadÄ«jumā nobÄ«des kompensācija vairs netiek piemērota

MÅ«su ievieÅ”anā Ŕīs divas pieejas atŔķīrās tikai ar pāris koda rindiņām, tāpēc mēs izveidojām abas, un ilgu laiku tās pastāvēja paralēli. AtkarÄ«bā no ieroča mehānikas un lodes ātruma katram dinozauram izvēlējāmies vienu vai otru variantu. Pagrieziena punkts Å”eit bija parādÄ«Å”anās mehānikas spēlē, piemēram, "ja tu trāpÄ«si ienaidniekam tik daudz reižu tādā un tādā laikā, saņemiet tādu un tādu bonusu." JebkurÅ” mehāniÄ·is, kurā spēlētāja sitiena ienaidniekam bija svarÄ«ga loma, atteicās strādāt ar otro pieeju. Tāpēc mēs izvēlējāmies pirmo iespēju, un tagad tas attiecas uz visiem ieročiem un visām aktÄ«vajām spējām spēlē.

AtseviŔķi ir vērts izvirzÄ«t jautājumu par veiktspēju. Ja jÅ«s domājāt, ka tas viss bremzēs, es atbildu: tā ir. Unity diezgan lēni pārvietojas kolaideros un tos ieslēdz un izslēdz. Dino komandā "sliktākajā" gadÄ«jumā kaujā vienlaikus var bÅ«t vairāki simti Ŕāviņu. Kodinātāju pārvietoÅ”ana, lai saskaitÄ«tu katru Ŕāviņu atseviŔķi, ir nepieejama greznÄ«ba. Tāpēc mums bija absolÅ«ti nepiecieÅ”ams samazināt fizikas ā€œatcelÅ”anuā€ skaitu. Lai to izdarÄ«tu, ECS izveidojām atseviŔķu komponentu, kurā ierakstām spēlētāja laiku. Mēs to pievienojām visām entÄ«tijām, kurām nepiecieÅ”ama kavÄ“Å”anās kompensācija (Ŕāviņi, spējas utt.). Pirms sākam apstrādāt Ŕādas entÄ«tijas, mēs tās lÄ«dz Å”im brÄ«dim sagrupējam un apstrādājam kopā, katrai klasterim vienreiz atgriežot fizisko pasauli.

Å ajā posmā mums ir vispārēji strādājoÅ”a sistēma. Tā kods nedaudz vienkārÅ”otā formā:

public sealed class LagCompensationSystemGroup : ExecutableSystem
{
     //ŠœŠ°ŃˆŠøŠ½Š° Š²Ń€ŠµŠ¼ŠµŠ½Šø
     private readonly ITimeMachine _timeMachine;

     //ŠŠ°Š±Š¾Ń€ сŠøстŠµŠ¼ Š»Š°Š³ŠŗŠ¾Š¼ŠæŠµŠ½ŃŠ°Ń†ŠøŠø
     private readonly LagCompensationSystem[] _systems;
     
     //ŠŠ°ŃˆŠ° рŠµŠ°Š»ŠøŠ·Š°Ń†Šøя ŠŗŠ»Š°ŃŃ‚ŠµŃ€ŠøŠ·Š°Ń‚Š¾Ń€Š°
     private readonly TimeTravelMap _travelMap = new TimeTravelMap();

    public LagCompensationSystemGroup(ITimeMachine timeMachine, 
        LagCompensationSystem[] lagCompensationSystems)
     {
         _timeMachine = timeMachine;
         _systems = lagCompensationSystems;
     }

     public override void Execute(GameState gs)
     {
         //ŠŠ° Š²Ń…Š¾Š“ ŠŗŠ»Š°ŃŃ‚ŠµŃ€ŠøŠ·Š°Ń‚Š¾Ń€ ŠæрŠøŠ½ŠøŠ¼Š°ŠµŃ‚ тŠµŠŗущŠµŠµ ŠøŠ³Ń€Š¾Š²Š¾Šµ сŠ¾ŃŃ‚Š¾ŃŠ½ŠøŠµ,
         //Š° Š½Š° Š²Ń‹Ń…Š¾Š“ Š²Ń‹Š“Š°ŠµŃ‚ Š½Š°Š±Š¾Ń€ Ā«ŠŗŠ¾Ń€Š·ŠøŠ½Ā». Š’ ŠŗŠ°Š¶Š“Š¾Š¹ ŠŗŠ¾Ń€Š·ŠøŠ½Šµ Š»ŠµŠ¶Š°Ń‚ эŠ½Ń‚ŠøтŠø,
         //ŠŗŠ¾Ń‚Š¾Ń€Ń‹Š¼ Š“Š»Ń Š»Š°Š³ŠŗŠ¾Š¼ŠæŠµŠ½ŃŠ°Ń†ŠøŠø Š½ŃƒŠ¶Š½Š¾ Š¾Š“Š½Š¾ Šø тŠ¾ Š¶Šµ Š²Ń€ŠµŠ¼Ń ŠøŠ· ŠøстŠ¾Ń€ŠøŠø.
         var buckets = _travelMap.RefillBuckets(gs);

         for (int bucketIndex = 0; bucketIndex < buckets.Count; bucketIndex++)
         {
             ProcessBucket(gs, buckets[bucketIndex]);
         }

         //Š’ ŠŗŠ¾Š½Ń†Šµ Š»Š°Š³ŠŗŠ¾Š¼ŠæŠµŠ½ŃŠ°Ń†ŠøŠø Š¼Ń‹ Š²Š¾ŃŃŃ‚Š°Š½Š°Š²Š»ŠøŠ²Š°ŠµŠ¼ фŠøŠ·ŠøчŠµŃŠŗŠøŠ¹ Š¼Šøр 
         //Š² ŠøсхŠ¾Š“Š½Š¾Šµ сŠ¾ŃŃ‚Š¾ŃŠ½ŠøŠµ
         _timeMachine.TravelToTime(gs.Time);
     }

     private void ProcessBucket(GameState presentState, TimeTravelMap.Bucket bucket)
     {
         //ŠžŃ‚ŠŗŠ°Ń‚Ń‹Š²Š°ŠµŠ¼ Š²Ń€ŠµŠ¼Ń Š¾Š“ŠøŠ½ рŠ°Š· Š“Š»Ń ŠŗŠ°Š¶Š“Š¾Š¹ ŠŗŠ¾Ń€Š·ŠøŠ½Ń‹
         var pastState = _timeMachine.TravelToTime(bucket.Time);

         foreach (var system in _systems)
         {
               system.PastState = pastState;
               system.PresentState = presentState;

               foreach (var entity in bucket)
               {
                   system.Execute(entity);
               }
          }
     }
}

Atlika tikai konfigurēt detaļas:

1. Saprast, cik ļoti ierobežot maksimālo kustības attālumu laikā.

Mums bija svarÄ«gi padarÄ«t spēli pēc iespējas pieejamāku slikto mobilo tÄ«klu apstākļos, tāpēc ierobežojām stāstu ar 30 atzÄ«mēm (ar Ä·eksÄ«Å”u ātrumu 20 Hz). Tas ļauj spēlētājiem trāpÄ«t pretiniekiem pat pie ļoti lieliem pingiem.

2. Nosakiet, kurus objektus var pārvietot laikā un kurus nevar.

Mēs, protams, iekustinām pretiniekus. Bet, piemēram, uzstādāmi enerÄ£ijas vairogi tādi nav. Mēs nolēmām, ka labāk ir dot priekÅ”roku aizsardzÄ«bas spējām, kā tas bieži tiek darÄ«ts tieÅ”saistes Ŕāvēju spēlēs. Ja spēlētājs jau ir ievietojis vairogu tagadnē, pagātnes lodes, kas kompensē nokavÄ“Å”anos, nedrÄ«kst lidot tam cauri.

3. Izlemiet, vai ir nepiecieÅ”ams kompensēt dinozauru spējas: sakodiens, astes sitiens utt. Mēs izlēmām, kas nepiecieÅ”ams, un apstrādājam tos pēc tādiem paÅ”iem noteikumiem kā lodes.

4. Nosakiet, ko darÄ«t ar spēlētāja, kuram tiek veikta nobÄ«des kompensācija, sadursmēm. Labā nozÄ«mē, viņu pozÄ«cijai nevajadzētu novirzÄ«ties pagātnē: spēlētājam vajadzētu redzēt sevi tajā paŔā laikā, kurā viņŔ tagad atrodas serverÄ«. Tomēr mēs arÄ« atceļam Ŕāvēja spēlētāja sadursmes, un tam ir vairāki iemesli.

Pirmkārt, tas uzlabo klasterizāciju: mēs varam izmantot vienu un to paÅ”u fizisko stāvokli visiem spēlētājiem ar tuvu ping.

Otrkārt, visos raycasts un pārklājumos mēs vienmēr izslēdzam tā spēlētāja kolÄ«derus, kuram pieder spējas vai Ŕāviņi. Spēlē Dino Squad spēlētāji kontrolē dinozaurus, kuriem pēc Ŕāvēja standartiem ir diezgan nestandarta Ä£eometrija. Pat ja spēlētājs Å”auj neparastā leņķī un lodes trajektorija iet caur spēlētāja dinozauru triecienu, lode to ignorēs.

TreÅ”kārt, mēs aprēķinām dinozaura ieroča pozÄ«cijas vai spēju pielietojuma punktu, izmantojot ECS datus pat pirms nobÄ«des kompensācijas sākuma.

LÄ«dz ar to atpalicÄ«bas kompensētā spēlētāja kolÄ«deru reālā pozÄ«cija mums ir mazsvarÄ«ga, tāpēc gājām pa produktÄ«vāku un reizē vienkārŔāku ceļu.

TÄ«kla latentumu nevar vienkārÅ”i noņemt, to var tikai maskēt. Tāpat kā jebkura cita maskÄ“Å”anas metode, servera kavÄ“Å”anās kompensācijai ir savi kompromisi. Tas uzlabo tā spēlētāja spēļu pieredzi, kurÅ” Å”auj uz tā spēlētāja rēķina, uz kuru tiek Å”auts. Tomēr Dino Squad izvēle Å”eit bija acÄ«mredzama.

Protams, par to visu bija jāmaksā arÄ« servera koda pieaugoŔā sarežģītÄ«ba kopumā ā€“ gan programmētājiem, gan spēļu dizaineriem. Ja agrāk simulācija bija vienkārÅ”s secÄ«gs sistēmu izsaukums, tad ar nobÄ«des kompensāciju tajā parādÄ«jās ligzdotas cilpas un zari. Mēs arÄ« veltÄ«jām daudz pūļu, lai ar to bÅ«tu ērti strādāt.

2019. gada versijā (un varbÅ«t nedaudz agrāk) Unity pievienoja pilnÄ«gu atbalstu neatkarÄ«gām fiziskām ainām. Mēs tos ieviesām serverÄ« gandrÄ«z uzreiz pēc atjaunināŔanas, jo gribējām ātri atbrÄ«voties no visām telpām kopÄ«gās fiziskās pasaules.

Katrai spēļu telpai pieŔķīrām savu fizisko ainu un tādējādi novērsām nepiecieÅ”amÄ«bu ā€œnotÄ«rÄ«tā€ ainu no blakus esoŔās istabas datiem pirms simulācijas aprēķināŔanas. Pirmkārt, tas ievērojami palielināja produktivitāti. Otrkārt, tas ļāva atbrÄ«voties no veselas kļūdu klases, kas radās, ja programmētājs pieļāva kļūdu ainas tÄ«rÄ«Å”anas kodā, pievienojot jaunus spēles elementus. Šādas kļūdas bija grÅ«ti atkļūdot, un tās bieži izraisÄ«ja fizisko objektu stāvokli vienā telpā, kas "ieplÅ«st" citā telpā.

Turklāt mēs veicām dažus pētÄ«jumus par to, vai fiziskās ainas var izmantot fiziskās pasaules vēstures glabāŔanai. Tas ir, nosacÄ«ti, katrai telpai pieŔķiriet nevis vienu ainu, bet 30 ainas un izveidojiet no tām ciklisku buferi, kurā glabāt stāstu. Kopumā variants izrādÄ«jās sekmÄ«gs, taču mēs to neieviesām: tas neuzrādÄ«ja nekādu traku produktivitātes pieaugumu, bet prasÄ«ja diezgan riskantas izmaiņas. Bija grÅ«ti paredzēt, kā serveris uzvedÄ«sies, ilgstoÅ”i strādājot ar tik daudzām ainām. Tāpēc mēs ievērojām noteikumu: "Ja tas nav salauzts, to nevar novērst'.

Avots: www.habr.com

Pievieno komentāru