ජාල ප්‍රමාද වන්දි ඇල්ගොරිතමයක් සහිත ජංගම වෙඩික්කරුවෙකු සඳහා අපි බැලිස්ටික් ගණනය කිරීම් යාන්ත්‍ර විද්‍යාව වැඩිදියුණු කළ ආකාරය

ජාල ප්‍රමාද වන්දි ඇල්ගොරිතමයක් සහිත ජංගම වෙඩික්කරුවෙකු සඳහා අපි බැලිස්ටික් ගණනය කිරීම් යාන්ත්‍ර විද්‍යාව වැඩිදියුණු කළ ආකාරය

හායි, මම Nikita Brizhak, Pixonic හි සේවාදායක සංවර්ධකයෙක්. අද මම ජංගම බහු ක්‍රීඩකයන්ගේ ප්‍රමාදය සඳහා වන්දි ගෙවීම ගැන කතා කිරීමට කැමැත්තෙමි.

රුසියානු භාෂාව ඇතුළුව සේවාදායක ප්‍රමාද වන්දි ගැන බොහෝ ලිපි ලියා ඇත. 90 දශකයේ අග භාගයේ සිට බහු ක්‍රීඩක FPS නිර්මාණය කිරීමේදී මෙම තාක්ෂණය ක්‍රියාකාරීව භාවිතා කර ඇති බැවින් මෙය පුදුමයක් නොවේ. උදාහරණයක් ලෙස, ඔබට QuakeWorld mod මතක තබා ගත හැකිය, එය මුලින්ම භාවිතා කළ එකක් විය.

අපි එය අපගේ ජංගම බහු ක්‍රීඩක වෙඩික්කරු Dino Squad හි ද භාවිතා කරමු.

මෙම ලිපියෙන්, මගේ ඉලක්කය දැනටමත් දහස් වරක් ලියා ඇති දේ නැවත නැවත කිරීම නොව, අපගේ තාක්‍ෂණික තොගය සහ මූලික ක්‍රීඩා විශේෂාංග සැලකිල්ලට ගනිමින් අපගේ ක්‍රීඩාවේ ප්‍රමාද වන්දි ක්‍රියාත්මක කළ ආකාරය පැවසීමයි.

අපගේ බාහිකය සහ තාක්ෂණය ගැන වචන කිහිපයක්.

Dino Squad යනු ජාල ජංගම PvP වෙඩික්කරුවෙකි. ක්‍රීඩකයින් විවිධ ආයුධ වලින් සන්නද්ධ ඩයිනෝසෝරයන් පාලනය කරන අතර 6v6 කණ්ඩායම් වශයෙන් එකිනෙකා සමඟ සටන් කරයි.

සේවාලාභියා සහ සේවාදායකය යන දෙකම Unity මත පදනම් වේ. වෙඩික්කරුවන් සඳහා ගෘහනිර්මාණ ශිල්පය තරමක් සම්භාව්‍ය ය: සේවාදායකය අධිකාරී වන අතර සේවාදායක පුරෝකථනය සේවාලාභීන් මත ක්‍රියා කරයි. ක්‍රීඩා සමාකරණය ලියා ඇත්තේ අභ්‍යන්තර ECS භාවිතයෙන් වන අතර එය සේවාදායකය සහ සේවාදායකයා යන දෙකෙහිම භාවිතා වේ.

ප්‍රමාද වන්දි ගැන ඔබ අසා ඇති පළමු අවස්ථාව මෙය නම්, මෙන්න එම ගැටලුව පිළිබඳ කෙටි විනෝද චාරිකාවක්.

බහු ක්‍රීඩක FPS ක්‍රීඩා වලදී, තරඟය සාමාන්‍යයෙන් දුරස්ථ සේවාදායකයක් මත අනුකරණය කෙරේ. ක්‍රීඩකයින් ඔවුන්ගේ ආදානය (යතුර එබූ යතුරු පිළිබඳ තොරතුරු) සේවාදායකය වෙත යවන අතර, ප්‍රතිචාර වශයෙන් සේවාදායකය විසින් ලැබුණු දත්ත සැලකිල්ලට ගනිමින් යාවත්කාලීන ක්‍රීඩා තත්වයක් යවයි. මෙම අන්තර්ක්‍රියා යෝජනා ක්‍රමය සමඟ, ඉදිරි යතුර එබීම සහ ක්‍රීඩක චරිතය තිරය මත චලනය වන මොහොත අතර ප්‍රමාදය සෑම විටම පිං එකට වඩා වැඩි වේ.

දේශීය ජාල වල මෙම ප්‍රමාදය (ජනප්‍රිය ආදාන ප්‍රමාදය ලෙස හැඳින්වේ) නොපෙනී යා හැකි අතර, අන්තර්ජාලය හරහා ක්‍රීඩා කරන විට එය චරිතයක් පාලනය කිරීමේදී "අයිස් මත ලිස්සා යාමේ" හැඟීමක් ඇති කරයි. මෙම ගැටළුව ජංගම ජාල සඳහා දෙගුණයක් අදාළ වේ, ක්‍රීඩකයෙකුගේ පිං 200 ms වන අවස්ථාව තවමත් විශිෂ්ට සම්බන්ධතාවයක් ලෙස සැලකේ. බොහෝ විට පිං 350, 500 හෝ 1000 ms විය හැක. එවිට ආදාන ප්‍රමාදය සමඟ වේගවත් වෙඩික්කරුවෙකු ක්‍රීඩා කිරීම පාහේ කළ නොහැක්කකි.

මෙම ගැටලුවට විසඳුම සේවාලාභී පාර්ශ්වයේ අනුකරණ අනාවැකියයි. මෙහිදී සේවාදායකයා විසින්ම සේවාදායකයෙන් ප්‍රතිචාරයක් ලැබෙන තෙක් බලා නොසිට, ක්‍රීඩක චරිතයට ආදානය යොදයි. පිළිතුර ලැබුණු විට, එය හුදෙක් ප්රතිඵල සංසන්දනය කර විරුද්ධවාදීන්ගේ ස්ථාන යාවත්කාලීන කරයි. මෙම අවස්ථාවෙහිදී යතුරක් එබීම සහ ප්‍රතිඵලය තිරය මත ප්‍රදර්ශනය කිරීම අතර ප්‍රමාදය අවම වේ.

මෙහි ඇති සූක්ෂ්මතාවය තේරුම් ගැනීම වැදගත්ය: සේවාදායකයා සෑම විටම එහි අවසාන ආදානයට අනුව අඳින අතර සතුරන් - ජාල ප්‍රමාදය සමඟ, සේවාදායකයේ දත්ත වලින් පෙර තත්වයට අනුව. එනම්, සතුරෙකුට වෙඩි තබන විට, ක්රීඩකයා තමාට සාපේක්ෂව අතීතයේදී ඔහුව දකිනවා. සේවාලාභී පුරෝකථනය පිළිබඳ වැඩි විස්තර අපි කලින් ලිව්වා.

මේ අනුව, සේවාලාභී පුරෝකථනය එක් ගැටළුවක් විසඳයි, නමුත් තවත් ගැටළුවක් නිර්මාණය කරයි: ක්‍රීඩකයෙකු අතීතයේ සතුරා සිටි ස්ථානයේ වෙඩි තැබුවහොත්, එකම ස්ථානයේ වෙඩි තබන විට සේවාදායකය මත, සතුරා තවදුරටත් එම ස්ථානයේ නොසිටිය හැකිය. සේවාදායක ප්‍රමාදය වන්දි මෙම ගැටලුව විසඳීමට උත්සාහ කරයි. ආයුධයක් වෙඩි තැබූ විට, සේවාදායකයා විසින් වෙඩි තබන අවස්ථාවේ ක්‍රීඩකයා දේශීයව දුටු ක්‍රීඩා තත්ත්වය ප්‍රතිෂ්ඨාපනය කරන අතර, ඔහුට සැබවින්ම සතුරාට පහර දිය හැකිද යන්න පරීක්ෂා කරයි. පිළිතුර "ඔව්" නම්, එම අවස්ථාවේදී සතුරා තවදුරටත් සේවාදායකයේ නොමැති වුවද පහර ගණනය කෙරේ.

මෙම දැනුමෙන් සන්නද්ධව, අපි Dino Squad හි සේවාදායක ප්‍රමාද වන්දි ක්‍රියාත්මක කිරීමට පටන් ගත්තෙමු. පළමුවෙන්ම, සේවාදායකයා දුටු දේ සේවාදායකයේ ප්‍රතිස්ථාපනය කරන්නේ කෙසේදැයි අප තේරුම් ගත යුතුය. සහ හරියටම යථා තත්ත්වයට පත් කළ යුත්තේ කුමක්ද? අපගේ ක්‍රීඩාවේදී, ආයුධ සහ හැකියාවන්ගෙන් ලැබෙන පහර ගණනය කරනු ලබන්නේ රේකාස්ට් සහ උඩින් - එනම් සතුරාගේ භෞතික ගැටීම් සමඟ අන්තර්ක්‍රියා කිරීමෙනි. ඒ අනුව, ක්‍රීඩකයා දේශීයව “දුටු” මෙම ඝට්ටනවල පිහිටීම සේවාදායකයේ ප්‍රතිනිෂ්පාදනය කිරීමට අපට අවශ්‍ය විය. ඒ කාලේ අපි පාවිච්චි කළේ Unity version 2018.x. භෞතික විද්‍යාව API එක ස්ථිතිකයි, භෞතික ලෝකය පවතින්නේ තනි පිටපතක. එහි තත්වය සුරැකීමට සහ පසුව කොටුවෙන් එය ප්රතිෂ්ඨාපනය කිරීමට ක්රමයක් නොමැත. ඉතින් මොනවා කරන්නද?

විසඳුම මතුපිට විය; එහි සියලුම අංග දැනටමත් වෙනත් ගැටළු විසඳීම සඳහා අප විසින් භාවිතා කර ඇත:

  1. එක් එක් සේවාදායකයා සඳහා, ඔහු යතුරු එබූ විට විරුද්ධවාදීන් දුටුවේ කුමන වේලාවකදැයි අප දැනගත යුතුය. අපි දැනටමත් මෙම තොරතුරු ආදාන පැකේජයට ලියා ඇති අතර සේවාලාභී පුරෝකථනය සකස් කිරීමට එය භාවිතා කර ඇත.
  2. ක්‍රීඩා ප්‍රාන්තවල ඉතිහාසය ගබඩා කිරීමට අපට හැකි විය යුතුය. අපි අපේ විරුද්ධවාදීන්ගේ (සහ ඒ නිසා ඔවුන්ගේ ගැටෙන්නන්ගේ) තනතුරු දරන්නේ එහි ය. අපට දැනටමත් සේවාදායකයේ රාජ්‍ය ඉතිහාසයක් තිබුණි, අපි එය ගොඩනැගීමට භාවිතා කළෙමු ඩෙල්ටා. නියම වේලාව දැන ගැනීමෙන්, අපට ඉතිහාසයේ නිවැරදි තත්ත්වය පහසුවෙන් සොයාගත හැකිය.
  3. දැන් අප සතුව ඉතිහාසයේ සිට ක්‍රීඩා තත්ත්වය ඇති බැවින්, භෞතික ලෝකයේ තත්ත්වය සමඟ ක්‍රීඩක දත්ත සමමුහුර්ත කිරීමට අපට හැකි විය යුතුය. පවතින ඝට්ටන - චලනය, අතුරුදහන් වූ ඒවා - නිර්මාණය කිරීම, අනවශ්ය ඒවා - විනාශ කිරීම. මෙම තර්කය දැනටමත් ලියා ඇති අතර ECS පද්ධති කිහිපයකින් සමන්විත විය. එක Unity ක්‍රියාවලියක ක්‍රීඩා කාමර කිහිපයක් පැවැත්වීමට අපි එය භාවිතා කළෙමු. භෞතික ලෝකය එක් ක්‍රියාවලියකට එකක් වන බැවින්, එය කාමර අතර නැවත භාවිතා කිරීමට සිදු විය. සමාකරණයේ සෑම ටික් එකකටම පෙර, අපි භෞතික ලෝකයේ තත්වය "නැවත සකසන්න" සහ වත්මන් කාමරය සඳහා දත්ත සමඟ එය නැවත ආරම්භ කර, දක්ෂ සංචිත පද්ධතියක් හරහා යුනිටි ක්‍රීඩා වස්තූන් හැකිතාක් නැවත භාවිතා කිරීමට උත්සාහ කරමු. ඉතිරිව තිබුණේ අතීතයේ සිට ක්‍රීඩා තත්ත්වය සඳහා එකම තර්කනය ඉදිරිපත් කිරීම පමණි.

මෙම සියලුම අංග එකට එකතු කිරීමෙන්, භෞතික ලෝකයේ තත්වය නියම මොහොතට ආපසු හැරවිය හැකි “කාල යන්ත්‍රයක්” අපට ලැබුණි. කේතය සරල විය:

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;
     }
}

ඉතිරිව තිබුණේ වෙඩි සහ හැකියාවන් සඳහා පහසුවෙන් වන්දි ගෙවීම සඳහා මෙම යන්ත්රය භාවිතා කරන්නේ කෙසේදැයි සොයා බැලීමයි.

සරලම අවස්ථාවෙහිදී, යාන්ත්‍ර විද්‍යාව තනි පහරක් මත පදනම් වූ විට, සියල්ල පැහැදිලි බව පෙනේ: ක්‍රීඩකයා වෙඩි තැබීමට පෙර, ඔහුට භෞතික ලෝකය අපේක්ෂිත තත්වයට පෙරළීම, රේකාස්ට් කිරීම, පහර හෝ මග හැරීම ගණනය කිරීම අවශ්‍ය වේ. ලෝකය ආරම්භක තත්වයට ආපසු යන්න.

නමුත් Dino Squad හි එවැනි කාර්මිකයන් සිටින්නේ ඉතා ස්වල්පයකි! ක්‍රීඩාවේ ඇති බොහෝ ආයුධ ප්‍රක්ෂේපණ නිර්මාණය කරයි - සමාකරණ කිනිතුල්ලන් කිහිපයක් සඳහා පියාසර කරන දිගු කාලීන උණ්ඩ (සමහර අවස්ථාවලදී, කිනිතුල්ලන් දුසිම් ගණනක්). ඔවුන් සමඟ කුමක් කළ යුතුද, ඔවුන් පියාසර කළ යුත්තේ කුමන වේලාවටද?

В පැරණි ලිපිය Half-Life ජාල තොගය ගැන, Valve හි යාලුවෝ එකම ප්‍රශ්නය ඇසූ අතර, ඔවුන්ගේ පිළිතුර මෙය විය: ප්‍රක්ෂේපණ ප්‍රමාද වන්දි ගෙවීම ගැටළු සහගත වන අතර එය වළක්වා ගැනීම වඩා හොඳය.

අපට මෙම විකල්පය නොතිබුණි: ප්‍රක්ෂේපණ මත පදනම් වූ ආයුධ ක්‍රීඩා නිර්මාණයේ ප්‍රධාන අංගයක් විය. ඒ නිසා අපට යමක් ඉදිරිපත් කිරීමට සිදු විය. මඳක් කල්පනා කිරීමෙන් පසුව, අපි වැඩ කරන බව පෙනෙන විකල්ප දෙකක් සකස් කළෙමු:

1. අපි එය නිර්මාණය කළ ක්රීඩකයාගේ කාලයට ප්රොජෙක්ටලය බැඳ තබමු. සේවාදායක සමාකරණයේ සෑම ටික් එකක්ම, සෑම ක්‍රීඩකයෙකුගේම සෑම උණ්ඩයක් සඳහාම, අපි භෞතික ලෝකය සේවාදායක තත්වයට පෙරළා අවශ්‍ය ගණනය කිරීම් සිදු කරන්නෙමු. මෙම ප්‍රවේශය මඟින් සේවාදායකයේ බෙදා හරින ලද බරක් සහ ප්‍රක්ෂේපණවල පියාසැරි කාලය පුරෝකථනය කිරීමට හැකි විය. සතුරු ප්‍රක්ෂේපණ ඇතුළු සියලුම ප්‍රක්ෂේපණ සේවාදායකයා මත පුරෝකථනය කර ඇති බැවින් පුරෝකථනය කිරීම අපට විශේෂයෙන් වැදගත් විය.

ජාල ප්‍රමාද වන්දි ඇල්ගොරිතමයක් සහිත ජංගම වෙඩික්කරුවෙකු සඳහා අපි බැලිස්ටික් ගණනය කිරීම් යාන්ත්‍ර විද්‍යාව වැඩිදියුණු කළ ආකාරය
පින්තූරයේ, ටික් 30 හි ක්‍රීඩකයා අපේක්ෂාවෙන් මිසයිලයක් වෙඩි තබයි: සතුරා දුවන්නේ කුමන දිශාවටද යන්න ඔහු දකින අතර මිසයිලයේ ආසන්න වේගය දනී. ඔහු 33 වන ටික් එකේ ඉලක්කයට පහර දුන් බව දේශීයව ඔහු දකී. ප්‍රමාද වන්දි සඳහා ස්තූතියි, එය සේවාදායකයේ ද දිස්වනු ඇත

2. අපි සෑම දෙයක්ම පළමු විකල්පයේ ආකාරයටම කරන්නෙමු, නමුත්, බුලට් සමාකරණයේ එක් ටික් එකක් ගණන් කළ පසු, අපි නතර නොවෙමු, නමුත් එකම සේවාදායක ටික් එක තුළ එහි පියාසැරිය දිගටම අනුකරණය කරන්න, සෑම අවස්ථාවකම එහි කාලය සේවාදායකයට සමීප කරයි. එකින් එක ටික් සහ collider ස්ථාන යාවත්කාලීන කිරීම. දේවල් දෙකෙන් එකක් සිදු වන තුරු අපි මෙය කරන්නෙමු:

  • උණ්ඩය කල් ඉකුත් වී ඇත. මෙයින් අදහස් කරන්නේ ගණනය කිරීම් අවසන් බවයි, අපට මිස් හෝ පහරක් ගණන් කළ හැකිය. මෙය වෙඩි වැදුණු ටික් එකෙහිම වේ! අපට මෙය ප්ලස් සහ අවාසි දෙකම විය. ප්ලස් - වෙඩි තැබීමේ ක්‍රීඩකයාට මෙය පහර සහ සතුරාගේ සෞඛ්‍යයේ අඩුවීම අතර ප්‍රමාදය සැලකිය යුතු ලෙස අඩු කළ බැවිනි. අවාසිය නම් විරුද්ධවාදීන් ක්‍රීඩකයාට වෙඩි තැබූ විට එම බලපෑමම නිරීක්ෂණය වීමයි: සතුරා, පෙනෙන පරිදි, මන්දගාමී රොකට්ටුවක් පමණක් වෙඩි තැබූ අතර, හානිය දැනටමත් ගණන් කර ඇත.
  • උණ්ඩය සේවාදායක වේලාවට ළඟා වී ඇත. මෙම අවස්ථාවේදී, එහි අනුකරණය කිසිදු ප්‍රමාද වන්දියකින් තොරව ඊළඟ සේවාදායක ටික් එකෙහි දිගටම පවතිනු ඇත. මන්දගාමී ප්‍රක්ෂේපණ සඳහා, මෙය පළමු විකල්පයට සාපේක්ෂව භෞතික විද්‍යාව පෙරළීමේ සංඛ්‍යාව න්‍යායාත්මකව අඩු කළ හැකිය. ඒ සමගම, සමාකරණයේ අසමාන භාරය වැඩි විය: සේවාදායකය නිෂ්ක්‍රීය විය, නැතහොත් එක් සේවාදායක ටික් එකකින් එය උණ්ඩ කිහිපයක් සඳහා සමාකරණ කිනිතුල්ලන් දුසිමක් ගණනය කරයි.

ජාල ප්‍රමාද වන්දි ඇල්ගොරිතමයක් සහිත ජංගම වෙඩික්කරුවෙකු සඳහා අපි බැලිස්ටික් ගණනය කිරීම් යාන්ත්‍ර විද්‍යාව වැඩිදියුණු කළ ආකාරය
පෙර පින්තූරයේ මෙන් එකම දර්ශනය, නමුත් දෙවන යෝජනා ක්රමය අනුව ගණනය කරනු ලැබේ. වෙඩි තැබීම සිදු වූ එම ටික් එකේම මිසයිලය සේවාදායකයේ වේලාව සමඟ “අල්ලා” ගත් අතර, පහර ඊළඟ ටික් එක තරම් ඉක්මනින් ගණන් කළ හැකිය. 31 වන ටික් එකේදී, මෙම නඩුවේදී, ප්‍රමාද වන්දි තවදුරටත් අදාළ නොවේ

අපගේ ක්‍රියාත්මක කිරීමේදී, මෙම ප්‍රවේශ දෙක වෙනස් වූයේ කේත පේළි කිහිපයකින් පමණි, එබැවින් අපි දෙකම නිර්මාණය කළ අතර දිගු කලක් ඒවා සමාන්තරව පැවතුනි. ආයුධයේ යාන්ත්‍ර විද්‍යාව සහ උණ්ඩයේ වේගය අනුව, අපි එක් එක් ඩයිනෝසෝරය සඳහා එක් හෝ තවත් විකල්පයක් තෝරා ගත්තෙමු. මෙහි හැරවුම් ලක්ෂ්‍යය වූයේ “මෙවැනි වේලාවක ඔබ සතුරාට කිහිප වතාවක් පහර දුන්නොත්, එවැනි ප්‍රසාද දීමනාවක් ලබා ගන්න” වැනි යාන්ත්‍රික ක්‍රීඩාවේ පෙනී සිටීමයි. ක්‍රීඩකයා සතුරාට පහර දුන් වේලාව වැදගත් කාර්යභාරයක් ඉටු කළ ඕනෑම කාර්මිකයෙකු දෙවන ප්‍රවේශය සමඟ වැඩ කිරීම ප්‍රතික්ෂේප කළේය. එබැවින් අපි පළමු විකල්පය සමඟ අවසන් වූ අතර, එය දැන් ක්‍රීඩාවේ සියලුම ආයුධ සහ සියලුම ක්‍රියාකාරී හැකියාවන් සඳහා අදාළ වේ.

වෙනමම, කාර්ය සාධනය පිළිබඳ ගැටළුව මතු කිරීම වටී. මේ සියල්ල මන්දගාමී වනු ඇතැයි ඔබ සිතන්නේ නම්, මම පිළිතුරු දෙමි: එයයි. ඝට්ටන චලනය කිරීමේදී සහ ඒවා සක්‍රිය සහ අක්‍රිය කිරීමේදී Unity තරමක් මන්දගාමී වේ. Dino Squad හි, "නරකම අවස්ථාවෙහි", සටන්වලදී එකවර ප්‍රක්ෂේපණ සිය ගණනක් පැවතිය හැකිය. එක් එක් ප්‍රක්ෂේපණය තනි තනිව ගණනය කිරීම සඳහා ඝට්ටන චලනය කිරීම දැරිය නොහැකි සුඛෝපභෝගී දෙයකි. එබැවින්, භෞතික විද්යාව "ආපසු හැරීම්" සංඛ්යාව අවම කිරීම සඳහා අපට අතිශයින්ම අවශ්ය විය. මෙය සිදු කිරීම සඳහා, අපි ECS හි වෙනම අංගයක් නිර්මාණය කළෙමු, එහි අපි ක්‍රීඩකයාගේ කාලය සටහන් කරමු. අපි එය ප්‍රමාද වන්දි අවශ්‍ය සියලුම ආයතනවලට එකතු කළෙමු (ව්‍යාපෘති, හැකියාවන්, ආදිය). අපි එවැනි ආයතන සැකසීම ආරම්භ කිරීමට පෙර, අපි මේ කාලය වන විට ඒවා පොකුරු කර ඒවා එකට සකසන්නෙමු, එක් එක් පොකුරු සඳහා භෞතික ලෝකය එක් වරක් පෙරළන්නෙමු.

මෙම අදියරේදී අපට සාමාන්යයෙන් වැඩ කරන පද්ධතියක් ඇත. එහි කේතය තරමක් සරල කළ ආකාරයෙන්:

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);
               }
          }
     }
}

ඉතිරිව ඇත්තේ විස්තර වින්‍යාස කිරීම පමණි:

1. කාලය තුළ චලනය වන උපරිම දුර ප්රමාණය සීමා කිරීමට කොපමණ දැයි තේරුම් ගන්න.

දුර්වල ජංගම දුරකථන ජාල තත්ත්වයන් තුළ ක්‍රීඩාව හැකිතාක් ප්‍රවේශ විය හැකි ලෙස සකස් කිරීම අපට වැදගත් වූ අතර, එබැවින් අපි කිනිතුල්ලන් 30 ක ආන්තිකයකින් (20 Hz ටික් අනුපාතයක් සමඟ) කතාව සීමා කළෙමු. මෙමගින් ක්‍රීඩකයින්ට ඉතා ඉහළ පිං වලදී පවා ප්‍රතිවාදීන්ට පහර දීමට ඉඩ සලසයි.

2. නියමිත වේලාවට ගෙන යා හැකි වස්තූන් සහ කළ නොහැකි දේ තීරණය කරන්න.

ඇත්ත වශයෙන්ම, අපි අපේ විරුද්ධවාදීන් චලනය කරනවා. නමුත් ස්ථාපනය කළ හැකි බලශක්ති ආවරණ, උදාහරණයක් ලෙස, එසේ නොවේ. බොහෝ විට ඔන්ලයින් වෙඩික්කරුවන් තුළ සිදු කරනු ලබන පරිදි ආරක්ෂක හැකියාවට මුල් තැන දීම වඩා හොඳ බව අපි තීරණය කළෙමු. ක්රීඩකයා දැනටමත් වර්තමානයේ පලිහක් තබා ඇත්නම්, අතීතයේ සිට ප්රමාද වූ වන්දි උණ්ඩ එය හරහා පියාසර නොකළ යුතුය.

3. ඩයිනෝසෝරයන්ගේ හැකියාවන් සඳහා වන්දි ගෙවීමට අවශ්යද යන්න තීරණය කරන්න: කටගැස්ම, වලිගය, ආදිය. අපි අවශ්ය දේ තීරණය කළ අතර වෙඩි උණ්ඩවලට සමාන නීතිවලට අනුව ඒවා සකස් කළෙමු.

4. ප්‍රමාද වන්දි ගෙවීම සිදු කරන ක්‍රීඩකයාගේ ගැටීම් සමඟ කළ යුතු දේ තීරණය කරන්න. හොඳ ආකාරයකින්, ඔවුන්ගේ ආස්ථානය අතීතයට මාරු නොවිය යුතුය: ක්රීඩකයා ඔහු දැන් සේවාදායකයේ සිටින කාලය තුළම තමා දැකිය යුතුය. කෙසේ වෙතත්, අපි වෙඩි තැබීමේ ක්‍රීඩකයාගේ ගැටීම් ද පෙරළන්නෙමු, මේ සඳහා හේතු කිහිපයක් තිබේ.

පළමුව, එය පොකුරු වැඩි දියුණු කරයි: අපට සමීප පිං සහිත සියලුම ක්‍රීඩකයින් සඳහා එකම භෞතික තත්වය භාවිතා කළ හැකිය.

දෙවනුව, සියලුම රේකාස්ට් සහ අතිච්ඡාදනය වලදී අපි සෑම විටම හැකියාවන් හෝ ප්‍රක්ෂේපන හිමි ක්‍රීඩකයාගේ ගැටීම් බැහැර කරමු. Dino Squad හි, ක්‍රීඩකයන් ඩයිනෝසෝරයන් පාලනය කරයි, වෙඩික්කරුවන්ගේ ප්‍රමිතීන්ට අනුව සම්මත නොවන ජ්‍යාමිතිය ඇත. ක්‍රීඩකයා අසාමාන්‍ය කෝණයකින් වෙඩි තැබුවද, උණ්ඩයේ ගමන් පථය ක්‍රීඩකයාගේ ඩයිනොසෝර ඝට්ටනය හරහා ගියද, උණ්ඩය එය නොසලකා හරිනු ඇත.

තෙවනුව, අපි ඩයිනොසෝරයාගේ ආයුධයේ පිහිටීම් හෝ ප්‍රමාද වන්දි ආරම්භයට පෙර ECS වෙතින් දත්ත භාවිතා කරමින් හැකියාව භාවිතා කරන ස්ථානය ගණනය කරමු.

එහි ප්‍රතිඵලයක් වශයෙන්, ප්‍රමාද-වන්දි ක්‍රීඩකයාගේ ඝට්ටනවල සැබෑ තත්ත්වය අපට නොවැදගත් නිසා අපි වඩාත් ඵලදායී හා ඒ සමඟම සරල මාර්ගයක් ගත්තෙමු.

ජාල ප්‍රමාදය සරලව ඉවත් කළ නොහැක, එය ආවරණය කළ හැක්කේ පමණි. වෙස්වළා ගැනීමේ වෙනත් ඕනෑම ක්‍රමයක් මෙන්, සේවාදායක ප්‍රමාද වන්දි ගෙවීමට එහි වෙළඳාම් ඇත. එය වෙඩි තබන ක්‍රීඩකයාගේ වියදමින් වෙඩි තබන ක්‍රීඩකයාගේ ක්‍රීඩා අත්දැකීම වැඩි දියුණු කරයි. කෙසේ වෙතත්, Dino Squad සඳහා, මෙහි තේරීම පැහැදිලිය.

ඇත්ත වශයෙන්ම, සමස්තයක් ලෙස සේවාදායක කේතයේ වැඩි සංකීර්ණතාවයෙන් මේ සියල්ල ගෙවිය යුතුය - ක්‍රමලේඛකයින් සහ ක්‍රීඩා නිර්මාණකරුවන් සඳහා. මීට පෙර සමාකරණය යනු පද්ධතිවල සරල අනුක්‍රමික ඇමතුමක් නම්, ප්‍රමාද වන්දි සමඟ, කැදැලි ලූප සහ අතු එහි දිස් විය. ඒ වගේම වැඩ කරන්න පහසු වෙන්න අපි ගොඩක් මහන්සි වුණා.

2019 අනුවාදයේ (සහ සමහරවිට ටිකක් කලින්), Unity ස්වාධීන භෞතික දර්ශන සඳහා පූර්ණ සහාය එක් කළේය. යාවත්කාලීන කිරීමෙන් පසු අපි ඒවා සේවාදායකයේ ක්‍රියාත්මක කළෙමු, මන්ද අපට සියලු කාමරවලට පොදු භෞතික ලෝකය ඉක්මනින් ඉවත් කිරීමට අවශ්‍ය වූ බැවිනි.

අපි සෑම ක්‍රීඩා කාමරයකටම තමන්ගේම භෞතික දර්ශනය ලබා දුන් අතර එමඟින් අනුකරණය ගණනය කිරීමට පෙර අසල්වැසි කාමරයේ දත්ත වලින් දර්ශනය “පැහැදිලි” කිරීමේ අවශ්‍යතාවය ඉවත් කළෙමු. පළමුව, එය ඵලදායිතාවයේ සැලකිය යුතු වැඩි වීමක් ලබා දුන්නේය. දෙවනුව, නව ක්‍රීඩා මූලද්‍රව්‍ය එකතු කිරීමේදී ක්‍රමලේඛකයා දර්ශන පිරිසිදු කිරීමේ කේතයේ දෝෂයක් සිදු කළහොත් පැන නගින දෝෂ සමූහයක් ඉවත් කිරීමට එය හැකි විය. එවැනි දෝෂ නිදොස් කිරීම දුෂ්කර වූ අතර, ඒවා බොහෝ විට එක් කාමරයක දර්ශනයක භෞතික වස්තූන් තවත් කාමරයකට "ගලා යාම" ඇති කරයි.

මීට අමතරව, භෞතික ලෝකයේ ඉතිහාසය ගබඩා කිරීමට භෞතික දර්ශන භාවිතා කළ හැකිද යන්න පිළිබඳව අපි යම් පර්යේෂණයක් කළා. එනම්, කොන්දේසි සහිතව, සෑම කාමරයකටම එක් දර්ශනයක් නොව, දර්ශන 30 ක් වෙන් කර, ඒවායින් චක්රීය බෆරයක් සාදා, කථාව ගබඩා කිරීම සඳහා. පොදුවේ ගත් කල, විකල්පය ක්‍රියාත්මක විය, නමුත් අපි එය ක්‍රියාත්මක කළේ නැත: එය ඵලදායිතාවයේ පිස්සු වැඩිවීමක් නොපෙන්වූ නමුත් තරමක් අවදානම් සහිත වෙනස්කම් අවශ්‍ය විය. මෙතරම් දර්ශන සමඟ දිගු කාලයක් වැඩ කරන විට සේවාදායකය හැසිරෙන්නේ කෙසේදැයි අනාවැකි කීම දුෂ්කර විය. එබැවින්, අපි රීතිය අනුගමනය කළෙමු: "එය කැඩී නැතිනම්, එය නිවැරදි නොකරන්න".

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න