សួស្តី ខ្ញុំគឺ Nikita Brizhak អ្នកបង្កើតម៉ាស៊ីនមេពី Pixonic ។ ថ្ងៃនេះខ្ញុំចង់និយាយអំពីការប៉ះប៉ូវសម្រាប់ភាពយឺតយ៉ាវក្នុងអ្នកលេងច្រើនទូរស័ព្ទ។
អត្ថបទជាច្រើនត្រូវបានសរសេរអំពីសំណងភាពយឺតយ៉ាវរបស់ម៉ាស៊ីនមេ រួមទាំងជាភាសារុស្សីផងដែរ។ នេះមិនមែនជារឿងគួរឱ្យភ្ញាក់ផ្អើលនោះទេ ចាប់តាំងពីបច្ចេកវិទ្យានេះត្រូវបានប្រើប្រាស់យ៉ាងសកម្មក្នុងការបង្កើត FPS អ្នកលេងច្រើនចាប់តាំងពីចុងទសវត្សរ៍ទី 90 ។ ជាឧទាហរណ៍ អ្នកអាចចងចាំនូវ mod QuakeWorld ដែលជាកម្មវិធីដំបូងគេដែលប្រើវា។
យើងក៏ប្រើវានៅក្នុងឧបករណ៍បាញ់ប្រហារតាមទូរស័ព្ទចល័តជាច្រើនរបស់ Dino Squad ។
នៅក្នុងអត្ថបទនេះ គោលដៅរបស់ខ្ញុំគឺមិនមែនចង់និយាយឡើងវិញនូវអ្វីដែលបានសរសេររួចហើយមួយពាន់ដងនោះទេ ប៉ុន្តែដើម្បីប្រាប់ពីរបៀបដែលយើងអនុវត្តសំណងយឺតយ៉ាវនៅក្នុងហ្គេមរបស់យើង ដោយគិតគូរពីជង់បច្ចេកវិទ្យា និងមុខងារសំខាន់ៗនៃការលេងហ្គេមរបស់យើង។
ពាក្យពីរបីអំពី Cortex និងបច្ចេកវិទ្យារបស់យើង។
Dino Squad គឺជាអ្នកបាញ់ PvP ចល័តតាមបណ្តាញ។ អ្នកលេងគ្រប់គ្រងដាយណូស័រដែលបំពាក់ដោយអាវុធជាច្រើនប្រភេទ ហើយប្រយុទ្ធគ្នាជាក្រុម 6v6។
ទាំងម៉ាស៊ីនភ្ញៀវ និងម៉ាស៊ីនមេគឺផ្អែកលើ Unity ។ ស្ថាបត្យកម្មគឺមានលក្ខណៈបុរាណសម្រាប់អ្នកបាញ់ប្រហារ៖ ម៉ាស៊ីនមេគឺផ្តាច់ការ ហើយការទស្សន៍ទាយអតិថិជនដំណើរការលើអតិថិជន។ ការក្លែងធ្វើហ្គេមត្រូវបានសរសេរដោយប្រើ ECS ក្នុងផ្ទះ ហើយត្រូវបានប្រើប្រាស់ទាំងនៅលើម៉ាស៊ីនមេ និងម៉ាស៊ីនភ្ញៀវ។
ប្រសិនបើនេះជាលើកដំបូងដែលអ្នកបានឮអំពីសំណងយឺតយ៉ាវ នេះគឺជាដំណើរកំសាន្តខ្លីៗអំពីបញ្ហានេះ។
នៅក្នុងហ្គេម FPS ដែលមានអ្នកលេងច្រើន ការប្រកួតជាធម្មតាត្រូវបានក្លែងធ្វើនៅលើម៉ាស៊ីនមេពីចម្ងាយ។ អ្នកលេងផ្ញើការបញ្ចូលរបស់ពួកគេ (ព័ត៌មានអំពីគ្រាប់ចុចដែលបានចុច) ទៅម៉ាស៊ីនមេ ហើយជាការឆ្លើយតប សឺវើរបញ្ជូនពួកគេនូវស្ថានភាពហ្គេមដែលបានធ្វើបច្ចុប្បន្នភាពដោយគិតគូរពីទិន្នន័យដែលទទួលបាន។ ជាមួយនឹងគ្រោងការណ៍អន្តរកម្មនេះ ការពន្យាពេលរវាងការចុចគ្រាប់ចុចទៅមុខ និងពេលដែលតួអង្គអ្នកលេងផ្លាស់ទីនៅលើអេក្រង់នឹងតែងតែធំជាង ping ។
ខណៈពេលដែលនៅលើបណ្តាញក្នុងស្រុក ការពន្យារពេលនេះ (ដែលគេនិយមហៅថា input lag) ប្រហែលជាមិនអាចកត់សម្គាល់បាន នៅពេលដែលលេងតាមរយៈអ៊ីនធឺណិត វាបង្កើតអារម្មណ៍ "រអិលលើទឹកកក" នៅពេលគ្រប់គ្រងតួអក្សរ។ បញ្ហានេះមានភាពពាក់ព័ន្ធទ្វេដងសម្រាប់បណ្តាញទូរស័ព្ទចល័ត ដែលករណីនៅពេលដែល ping របស់អ្នកលេងគឺ 200 ms នៅតែត្រូវបានចាត់ទុកថាជាការតភ្ជាប់ដ៏ល្អ។ ជាញឹកញាប់ ping អាចមាន 350, 500, ឬ 1000 ms ។ បន្ទាប់មកវាស្ទើរតែមិនអាចទៅរួចទេក្នុងការលេងឧបករណ៍បាញ់រហ័សជាមួយនឹងភាពយឺតយ៉ាវនៃការបញ្ចូល។
ដំណោះស្រាយចំពោះបញ្ហានេះគឺការទស្សន៍ទាយការក្លែងធ្វើផ្នែកខាងអតិថិជន។ នៅទីនេះ អតិថិជនខ្លួនវាអនុវត្តការបញ្ចូលទៅតួអក្សរអ្នកលេង ដោយមិនរង់ចាំការឆ្លើយតបពីម៉ាស៊ីនមេ។ ហើយនៅពេលដែលចម្លើយត្រូវបានទទួល វាគ្រាន់តែប្រៀបធៀបលទ្ធផល និងធ្វើបច្ចុប្បន្នភាពទីតាំងរបស់គូប្រជែង។ ការពន្យាពេលរវាងការចុចគ្រាប់ចុច និងការបង្ហាញលទ្ធផលនៅលើអេក្រង់ក្នុងករណីនេះគឺតិចតួចបំផុត។
វាមានសារៈសំខាន់ណាស់ក្នុងការយល់ដឹងអំពីភាពខុសប្លែកគ្នានៅទីនេះ៖ ម៉ាស៊ីនភ្ញៀវតែងតែទាញខ្លួនវាទៅតាមការបញ្ចូលចុងក្រោយរបស់វា និងសត្រូវ - ដោយមានការពន្យាពេលបណ្តាញ យោងទៅតាមស្ថានភាពមុនពីទិន្នន័យពីម៉ាស៊ីនមេ។ នោះគឺនៅពេលដែលបាញ់ទៅលើសត្រូវ អ្នកលេងមើលឃើញគាត់កាលពីអតីតកាលទាក់ទងនឹងខ្លួនគាត់។ បន្ថែមទៀតអំពីការព្យាករណ៍របស់អតិថិជន
ដូច្នេះ ការទស្សន៍ទាយរបស់អតិថិជនដោះស្រាយបញ្ហាមួយ ប៉ុន្តែបង្កើតមួយទៀត៖ ប្រសិនបើអ្នកលេងបាញ់នៅចំណុចដែលសត្រូវកាលពីអតីតកាល នៅលើម៉ាស៊ីនមេ នៅពេលបាញ់នៅចំណុចដូចគ្នា សត្រូវអាចនឹងលែងនៅកន្លែងនោះ។ សំណងភាពយឺតយ៉ាវរបស់ម៉ាស៊ីនមេព្យាយាមដោះស្រាយបញ្ហានេះ។ នៅពេលដែលអាវុធត្រូវបានបាញ់ នោះម៉ាស៊ីនមេនឹងស្ដារស្ថានភាពហ្គេមដែលអ្នកលេងបានឃើញនៅក្នុងមូលដ្ឋាននៅពេលបាញ់ ហើយពិនិត្យមើលថាតើគាត់ពិតជាអាចវាយប្រហារសត្រូវឬអត់។ ប្រសិនបើចម្លើយគឺ “បាទ/ចាស” ការវាយត្រូវបានរាប់ បើទោះបីជាសត្រូវលែងនៅលើម៉ាស៊ីនមេនៅពេលនេះក៏ដោយ។
ប្រដាប់ដោយចំណេះដឹងនេះ យើងបានចាប់ផ្តើមអនុវត្តសំណងលើការយឺតយ៉ាវរបស់ម៉ាស៊ីនមេនៅក្នុងក្រុម Dino ។ ជាដំបូងយើងត្រូវយល់ពីរបៀប Restore នៅលើ Server នូវអ្វីដែលអតិថិជនបានឃើញ? ហើយត្រូវស្ដារអ្វីឲ្យប្រាកដ? នៅក្នុងហ្គេមរបស់យើង ការវាយលុកពីអាវុធ និងសមត្ថភាពត្រូវបានគណនាតាមរយៈការបាញ់កាំរស្មី និងការត្រួតលើគ្នា ពោលគឺតាមរយៈអន្តរកម្មជាមួយនឹងការប៉ះទង្គិចគ្នារវាងសត្រូវ។ ដូច្នោះហើយ យើងត្រូវបង្កើតទីតាំងនៃការប៉ះទង្គិចទាំងនេះឡើងវិញ ដែលអ្នកលេង "បានឃើញ" នៅក្នុងមូលដ្ឋាននៅលើម៉ាស៊ីនមេ។ នៅពេលនោះយើងកំពុងប្រើ Unity កំណែ 2018.x ។ API រូបវិទ្យានៅទីនោះគឺឋិតិវន្ត ពិភពរូបវន្តមាននៅក្នុងច្បាប់ចម្លងតែមួយ។ មិនមានវិធីដើម្បីរក្សាទុកស្ថានភាពរបស់វាហើយបន្ទាប់មកស្ដារវាពីប្រអប់នោះទេ។ ដូច្នេះតើត្រូវធ្វើអ្វី?
ដំណោះស្រាយគឺស្ថិតនៅលើផ្ទៃ ធាតុទាំងអស់របស់វាត្រូវបានយើងប្រើរួចហើយដើម្បីដោះស្រាយបញ្ហាផ្សេងទៀត៖
- សម្រាប់អតិថិជនម្នាក់ៗ យើងត្រូវដឹងថានៅពេលណាដែលគាត់ឃើញគូប្រជែងនៅពេលគាត់ចុចគ្រាប់ចុច។ យើងបានសរសេរព័ត៌មាននេះទៅក្នុងកញ្ចប់បញ្ចូលរួចហើយ ហើយបានប្រើវាដើម្បីកែតម្រូវការព្យាករណ៍របស់អតិថិជន។
- យើងត្រូវតែអាចរក្សាទុកប្រវត្តិនៃរដ្ឋហ្គេម។ វាគឺនៅក្នុងវាដែលយើងនឹងកាន់តំណែងរបស់គូប្រជែងរបស់យើង (ហើយដូច្នេះការប៉ះទង្គិចរបស់ពួកគេ) ។ យើងមានប្រវត្តិរដ្ឋរួចហើយនៅលើម៉ាស៊ីនមេ យើងបានប្រើវាដើម្បីបង្កើត
ដីសណ្ត . ដោយដឹងពីពេលវេលាត្រឹមត្រូវ យើងអាចស្វែងរកស្ថានភាពត្រឹមត្រូវក្នុងប្រវត្តិសាស្ត្របានយ៉ាងងាយស្រួល។ - ឥឡូវនេះយើងមានស្ថានភាពហ្គេមពីប្រវត្តិសាស្ត្រនៅក្នុងដៃ យើងត្រូវមានលទ្ធភាពធ្វើសមកាលកម្មទិន្នន័យរបស់អ្នកលេងជាមួយនឹងស្ថានភាពនៃពិភពរូបវន្ត។ ការប៉ះទង្គិចដែលមានស្រាប់ - ផ្លាស់ទី, បាត់ - បង្កើត, មិនចាំបាច់ - បំផ្លាញ។ តក្កវិជ្ជានេះក៏ត្រូវបានសរសេររួចហើយ និងមានប្រព័ន្ធ ECS ជាច្រើន។ យើងបានប្រើវាដើម្បីរៀបចំបន្ទប់ហ្គេមជាច្រើននៅក្នុងដំណើរការ Unity មួយ។ ហើយចាប់តាំងពីពិភពរូបវន្តគឺមួយក្នុងដំណើរការមួយ វាត្រូវតែប្រើឡើងវិញរវាងបន្ទប់។ មុនពេលគូសនីមួយៗនៃការពិសោធន៏ យើង "កំណត់" ស្ថានភាពនៃពិភពរូបវន្ត និងចាប់ផ្តើមវាឡើងវិញជាមួយនឹងទិន្នន័យសម្រាប់បន្ទប់បច្ចុប្បន្ន ដោយព្យាយាមប្រើវត្ថុហ្គេម 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! អាវុធភាគច្រើននៅក្នុងហ្គេមបង្កើតជាគ្រាប់កាំភ្លើង - គ្រាប់កាំភ្លើងដែលមានអាយុកាលយូរដែលហោះហើរសម្រាប់ឆ្កពិសោធជាច្រើន (ក្នុងករណីខ្លះមានឆ្ករាប់សិប) ។ តើត្រូវធ្វើអ្វីជាមួយពួកគេ តើពួកគេគួរហោះហើរម៉ោងប៉ុន្មាន?
В
យើងមិនមានជម្រើសនេះទេ៖ អាវុធដែលមានមូលដ្ឋានលើគ្រាប់កាំភ្លើងគឺជាលក្ខណៈសំខាន់នៃការរចនាហ្គេម។ ដូច្នេះយើងត្រូវតែមករកអ្វីមួយ។ បន្ទាប់ពីការបំផុសគំនិតបន្តិច យើងបានបង្កើតជម្រើសពីរដែលហាក់ដូចជាដំណើរការ៖
1. យើងចងកាំជ្រួចទៅនឹងពេលវេលារបស់អ្នកលេងដែលបានបង្កើតវា។ រាល់សញ្ញាធីកនៃការក្លែងធ្វើម៉ាស៊ីនមេ សម្រាប់រាល់ចំណុចនៃអ្នកលេងទាំងអស់ យើងបង្វិលពិភពរូបវន្តទៅកាន់ស្ថានភាពអតិថិជន ហើយធ្វើការគណនាចាំបាច់។ វិធីសាស្រ្តនេះបានធ្វើឱ្យវាអាចធ្វើទៅបានដើម្បីឱ្យមានការចែកចាយបន្ទុកនៅលើម៉ាស៊ីនមេ និងពេលវេលាហោះហើរដែលអាចព្យាករណ៍បាននៃគ្រាប់។ ការទស្សន៍ទាយមានសារៈសំខាន់ជាពិសេសសម្រាប់យើង ដោយសារយើងមានគ្រាប់ផ្លោងទាំងអស់ រួមទាំងគ្រាប់ផ្លោងរបស់សត្រូវ ដែលបានព្យាករណ៍លើម៉ាស៊ីនភ្ញៀវ។
នៅក្នុងរូបភាព អ្នកលេងនៅសញ្ញាធីក 30 បាញ់កាំជ្រួចដោយស្មានទុកជាមុន៖ គាត់មើលឃើញថាសត្រូវកំពុងរត់ក្នុងទិសដៅណា ហើយដឹងពីល្បឿនប្រហាក់ប្រហែលនៃកាំជ្រួច។ ក្នុងមូលដ្ឋានគាត់មើលឃើញថាគាត់បានវាយចំគោលដៅនៅសញ្ញាទី ៣៣។ សូមអរគុណចំពោះសំណងយឺតយ៉ាវ វាក៏នឹងបង្ហាញនៅលើម៉ាស៊ីនមេផងដែរ។
2. យើងធ្វើអ្វីគ្រប់យ៉ាងដូចគ្នានឹងជម្រើសទីមួយដែរ ប៉ុន្តែដោយបានរាប់សញ្ញាធីកមួយនៃការក្លែងធ្វើគ្រាប់កាំភ្លើង យើងមិនឈប់ទេ ប៉ុន្តែបន្តក្លែងធ្វើការហោះហើររបស់វានៅក្នុងម៉ាស៊ីនមេដូចគ្នា រាល់ពេលដែលនាំពេលវេលារបស់វាខិតទៅជិតម៉ាស៊ីនមេ។ ម្តងមួយៗគូស និងធ្វើបច្ចុប្បន្នភាពទីតាំងបុក។ យើងធ្វើបែបនេះរហូតដល់រឿងមួយក្នុងចំណោមរឿងពីរកើតឡើង៖
- គ្រាប់កាំភ្លើងបានផុតកំណត់ហើយ។ មានន័យថាការគណនាចប់ហើយយើងអាចរាប់បានមួយនឹកឬបុក។ ហើយនេះគឺជាសញ្ញាធីកដូចគ្នាដែលការបាញ់ត្រូវបានបាញ់! សម្រាប់ពួកយើង នេះគឺទាំងបូក និងដក។ បូកមួយ - ដោយសារតែសម្រាប់អ្នកលេងបាញ់នេះកាត់បន្ថយការពន្យាពេលរវាងការវាយនិងការថយចុះយ៉ាងខ្លាំងនៃសុខភាពរបស់សត្រូវ។ គុណវិបត្តិគឺថាឥទ្ធិពលដូចគ្នាត្រូវបានគេសង្កេតឃើញនៅពេលដែលគូប្រជែងបានបាញ់ទៅលើអ្នកលេង: សត្រូវ វាហាក់ដូចជាគ្រាន់តែបាញ់រ៉ុក្កែតយឺត ហើយការខូចខាតត្រូវបានរាប់រួចហើយ។
- គ្រាប់កាំភ្លើងបានដល់ម៉ោងម៉ាស៊ីនមេ។ ក្នុងករណីនេះ ការក្លែងធ្វើរបស់វានឹងបន្តនៅក្នុងម៉ាស៊ីនមេបន្ទាប់ ដោយមិនមានសំណងយឺតយ៉ាវណាមួយឡើយ។ សម្រាប់ការបាញ់យឺត វាអាចកាត់បន្ថយតាមទ្រឹស្ដីចំនួននៃការវិលត្រឡប់ខាងរូបវិទ្យា បើធៀបនឹងជម្រើសដំបូង។ ក្នុងពេលជាមួយគ្នានោះ ការផ្ទុកមិនស្មើគ្នាលើការក្លែងធ្វើបានកើនឡើង៖ ម៉ាស៊ីនមេនៅទំនេរ ឬនៅក្នុងម៉ាស៊ីនមេមួយ ធីកវាកំពុងគណនាសញ្ញាក្លែងធ្វើរាប់សិបសម្រាប់គ្រាប់ជាច្រើន។
សេណារីយ៉ូដូចគ្នានឹងរូបភាពមុនដែរ ប៉ុន្តែគណនាតាមគ្រោងការណ៍ទីពីរ។ កាំជ្រួច "ចាប់ឡើង" ជាមួយនឹងម៉ោងម៉ាស៊ីនមេនៅសញ្ញាធីកដូចគ្នាដែលការបាញ់បានកើតឡើង ហើយការវាយលុកអាចត្រូវបានរាប់នៅដើមឆ្នាំបន្ទាប់។ នៅសញ្ញាទី 31 ក្នុងករណីនេះ សំណងភាពយឺតយ៉ាវមិនត្រូវបានអនុវត្តទៀតទេ
នៅក្នុងការអនុវត្តរបស់យើង វិធីសាស្រ្តទាំងពីរនេះខុសគ្នាត្រឹមតែពីរបីបន្ទាត់នៃកូដ ដូច្នេះយើងបានបង្កើតទាំងពីរ ហើយសម្រាប់រយៈពេលដ៏យូរមួយដែលពួកគេមានស្របគ្នា។ អាស្រ័យលើមេកានិចនៃអាវុធ និងល្បឿននៃគ្រាប់កាំភ្លើង យើងបានជ្រើសរើសជម្រើសមួយ ឬមួយផ្សេងទៀតសម្រាប់ដាយណូស័រនីមួយៗ។ ចំណុចរបត់នៅទីនេះគឺរូបរាងនៅក្នុងហ្គេមមេកានិកដូចជា "ប្រសិនបើអ្នកវាយសត្រូវច្រើនដងក្នុងពេលវេលាបែបនេះ នឹងទទួលបានប្រាក់រង្វាន់បែបនេះ" ។ មេកានិកណាមួយដែលពេលវេលាដែលអ្នកលេងវាយសត្រូវដើរតួយ៉ាងសំខាន់បដិសេធមិនធ្វើការជាមួយវិធីសាស្រ្តទីពីរ។ ដូច្នេះ យើងបានបញ្ចប់ជាមួយនឹងជម្រើសទីមួយ ហើយឥឡូវនេះវាអនុវត្តចំពោះអាវុធទាំងអស់ និងសមត្ថភាពសកម្មទាំងអស់នៅក្នុងហ្គេម។
ដោយឡែកវាមានតម្លៃលើកឡើងពីបញ្ហានៃការអនុវត្ត។ ប្រសិនបើអ្នកគិតថាអ្វីៗទាំងអស់នេះនឹងថយចុះ ខ្ញុំឆ្លើយថា វាគឺ។ ការរួបរួមគឺមានភាពយឺតយ៉ាវក្នុងការរំកិលការប៉ះទង្គិចគ្នា ហើយបើក និងបិទពួកវា។ នៅក្នុងក្រុម Dino ក្នុងសេណារីយ៉ូ "អាក្រក់បំផុត" វាអាចមានកាំជ្រួចរាប់រយគ្រាប់ដែលមានស្រាប់ក្នុងពេលដំណាលគ្នាក្នុងការប្រយុទ្ធ។ ការរំកិលឧបករណ៍បុកដើម្បីរាប់កាំជ្រួចនីមួយៗជាលក្ខណៈប្រណីតមិនអាចកាត់ថ្លៃបាន។ ដូច្នេះ វាពិតជាចាំបាច់សម្រាប់យើងក្នុងការកាត់បន្ថយចំនួនរូបវិទ្យា “វិលថយក្រោយ”។ ដើម្បីធ្វើដូចនេះយើងបានបង្កើតសមាសភាគដាច់ដោយឡែកមួយនៅក្នុង ECS ដែលយើងកត់ត្រាពេលវេលារបស់អ្នកលេង។ យើងបានបន្ថែមវាទៅអង្គភាពទាំងអស់ដែលទាមទារសំណងយឺតយ៉ាវ (projectiles សមត្ថភាព។ល។)។ មុនពេលយើងចាប់ផ្តើមដំណើរការអង្គធាតុបែបនេះ យើងដាក់ចង្កោមពួកវាដោយពេលនេះ ហើយដំណើរការពួកវាជាមួយគ្នា ដោយរំកិលពិភពរូបវន្តម្តងសម្រាប់ចង្កោមនីមួយៗ។
នៅដំណាក់កាលនេះយើងមានប្រព័ន្ធការងារជាទូទៅ។ កូដរបស់វាក្នុងទម្រង់សាមញ្ញបន្តិច៖
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 ហឺត)។ នេះអនុញ្ញាតឱ្យអ្នកលេងវាយគូប្រកួតសូម្បីតែនៅ ping ខ្ពស់ខ្លាំងណាស់។
2. កំណត់ថាតើវត្ថុណាអាចផ្លាស់ទីបានទាន់ពេល ហើយវត្ថុណាដែលមិនអាចផ្លាស់ទីបាន។
ជាការពិតណាស់ យើងកំពុងផ្លាស់ប្តូរគូប្រជែងរបស់យើង។ ប៉ុន្តែឧទាហរណ៍ខែលការពារថាមពលដែលអាចដំឡើងបានគឺមិនមែនទេ។ យើងបានសម្រេចចិត្តថា វាជាការប្រសើរជាងក្នុងការផ្តល់អាទិភាពដល់សមត្ថភាពការពារ ដូចដែលតែងតែធ្វើឡើងនៅក្នុងអ្នកបាញ់ប្រហារតាមអ៊ីនធឺណិត។ ប្រសិនបើអ្នកលេងបានដាក់ខែលរួចហើយនៅក្នុងពេលបច្ចុប្បន្ន គ្រាប់កាំភ្លើងដែលផ្តល់សំណងពីអតីតកាលមិនគួរហោះកាត់វាទេ។
3. សម្រេចចិត្តថាតើវាចាំបាច់ដើម្បីទូទាត់សងសម្រាប់សមត្ថភាពរបស់ដាយណូស័រ៖ ខាំ កន្ទុយ ជាដើម។ យើងបានសម្រេចចិត្តនូវអ្វីដែលចាំបាច់ ហើយដំណើរការវាដោយយោងទៅតាមច្បាប់ដូចគ្នានឹងគ្រាប់កាំភ្លើង។
4. កំណត់អ្វីដែលត្រូវធ្វើជាមួយការប៉ះទង្គិចគ្នារបស់អ្នកលេង ដែលសំណងយឺតយ៉ាវកំពុងត្រូវបានអនុវត្ត។ តាមរបៀបដ៏ល្អ ទីតាំងរបស់ពួកគេមិនគួរផ្លាស់ប្តូរទៅអតីតកាលទេ៖ អ្នកលេងគួរតែឃើញខ្លួនឯងក្នុងពេលជាមួយគ្នាដែលឥឡូវនេះគាត់នៅលើម៉ាស៊ីនមេ។ ទោះយ៉ាងណាក៏ដោយ យើងក៏រមៀលថយក្រោយការប៉ះទង្គិចរបស់អ្នកលេងបាញ់ដែរ ហើយមានហេតុផលជាច្រើនសម្រាប់រឿងនេះ។
ទីមួយ វាធ្វើអោយប្រសើរឡើងនូវការចងក្រង៖ យើងអាចប្រើស្ថានភាពរូបវន្តដូចគ្នាសម្រាប់អ្នកលេងទាំងអស់ដែលមាន pings ជិតស្និទ្ធ។
ទីពីរ នៅក្នុងការផ្សាយ និងការត្រួតគ្នាទាំងអស់ យើងតែងតែមិនរាប់បញ្ចូលការប៉ះទង្គិចគ្នារបស់អ្នកលេងដែលជាម្ចាស់សមត្ថភាព ឬ projectiles ។ នៅក្នុងក្រុម Dino អ្នកលេងគ្រប់គ្រងដាយណូស័រដែលមានធរណីមាត្រមិនស្តង់ដារតាមស្តង់ដារអ្នកបាញ់។ ទោះបីជាអ្នកលេងបាញ់នៅមុំមិនធម្មតា ហើយគន្លងរបស់គ្រាប់កាំភ្លើងឆ្លងកាត់ការបុកដាយណូស័ររបស់អ្នកលេងក៏ដោយ គ្រាប់កាំភ្លើងនឹងមិនអើពើឡើយ។
ទីបី យើងគណនាទីតាំងនៃអាវុធរបស់ដាយណូស័រ ឬចំណុចនៃការអនុវត្តសមត្ថភាពដោយប្រើទិន្នន័យពី ECS សូម្បីតែមុនពេលចាប់ផ្តើមនៃសំណងយឺតយ៉ាវក៏ដោយ។
ជាលទ្ធផល ទីតាំងពិតប្រាកដនៃការបុកគ្នារបស់អ្នកលេងដែលផ្តល់សំណងយឺតយ៉ាវគឺមិនសំខាន់សម្រាប់យើង ដូច្នេះហើយយើងបានយកផ្លូវដែលមានផលិតភាពជាងមុន និងក្នុងពេលតែមួយកាន់តែងាយស្រួល។
ភាពយឺតនៃបណ្តាញមិនអាចត្រូវបានដកចេញដោយសាមញ្ញទេ វាអាចត្រូវបានបិទបាំងតែប៉ុណ្ណោះ។ ដូចវិធីសាស្រ្តផ្សេងទៀតនៃការក្លែងបន្លំ សំណងភាពយឺតយ៉ាវរបស់ម៉ាស៊ីនមេមានការដោះដូររបស់វា។ វាធ្វើអោយប្រសើរឡើងនូវបទពិសោធន៍លេងហ្គេមរបស់អ្នកលេងដែលកំពុងបាញ់ដោយចំណាយរបស់អ្នកលេងដែលត្រូវបាញ់។ ទោះយ៉ាងណាក៏ដោយ សម្រាប់ក្រុម Dino ជម្រើសនៅទីនេះគឺជាក់ស្តែង។
ជាការពិតណាស់ អ្វីៗទាំងអស់នេះក៏ត្រូវចំណាយផងដែរ ដោយសារការកើនឡើងនៃភាពស្មុគស្មាញនៃកូដម៉ាស៊ីនមេទាំងមូល - ទាំងសម្រាប់អ្នកសរសេរកម្មវិធី និងអ្នករចនាហ្គេម។ ប្រសិនបើការក្លែងធ្វើមុននេះ គឺជាការហៅតាមលំដាប់លំដោយសាមញ្ញនៃប្រព័ន្ធ នោះជាមួយនឹងសំណងយឺតយ៉ាវ រង្វិលជុំ និងមែកធាងដែលបានដាក់នៅក្នុងនោះ។ យើងក៏បានចំណាយការខិតខំយ៉ាងច្រើនដើម្បីធ្វើឱ្យវាងាយស្រួលក្នុងការធ្វើការជាមួយ។
នៅក្នុងកំណែ 2019 (ហើយប្រហែលជាមុននេះបន្តិច) Unity បានបន្ថែមការគាំទ្រពេញលេញសម្រាប់ឈុតរាងកាយឯករាជ្យ។ យើងបានអនុវត្តពួកវានៅលើម៉ាស៊ីនមេស្ទើរតែភ្លាមៗបន្ទាប់ពីការអាប់ដេត ដោយសារតែយើងចង់កម្ចាត់ពិភពរូបវន្តទូទៅសម្រាប់បន្ទប់ទាំងអស់យ៉ាងឆាប់រហ័ស។
យើងបានផ្តល់ឱ្យបន្ទប់ហ្គេមនីមួយៗនូវទិដ្ឋភាពជាក់ស្តែងរបស់វា ហើយដូច្នេះបានលុបចោលនូវតម្រូវការដើម្បី "ជម្រះ" កន្លែងកើតហេតុពីទិន្នន័យនៃបន្ទប់ជិតខាង មុនពេលគណនាការក្លែងធ្វើ។ ជាដំបូង វាបានផ្តល់នូវការកើនឡើងគួរឱ្យកត់សម្គាល់នៅក្នុងផលិតភាព។ ទីពីរ វាធ្វើឱ្យវាអាចធ្វើទៅបានដើម្បីកម្ចាត់នូវប្រភេទទាំងមូលនៃកំហុសដែលកើតឡើងប្រសិនបើអ្នកសរសេរកម្មវិធីបង្កើតកំហុសនៅក្នុងកូដសម្អាតកន្លែងកើតហេតុនៅពេលបន្ថែមធាតុហ្គេមថ្មី។ កំហុសបែបនេះពិបាកនឹងកែកំហុស ហើយជារឿយៗវាបណ្តាលឱ្យស្ថានភាពនៃវត្ថុក្នុងបន្ទប់មួយ "ហូរ" ចូលទៅក្នុងបន្ទប់មួយទៀត។
លើសពីនេះ យើងបានធ្វើការស្រាវជ្រាវមួយចំនួនថាតើឈុតឆាករូបវន្តអាចត្រូវបានគេប្រើប្រាស់ដើម្បីរក្សាទុកប្រវត្តិសាស្រ្តនៃពិភពរូបវន្ត។ នោះតាមលក្ខខណ្ឌ មិនត្រូវបែងចែកឈុតមួយទៅបន្ទប់នីមួយៗទេ ប៉ុន្តែមាន 30 ឈុត ហើយបង្កើតជាសតិបណ្ដោះអាសន្នចេញពីពួកវា ដើម្បីរក្សាទុកសាច់រឿង។ ជាទូទៅ ជម្រើសបានប្រែទៅជាដំណើរការ ប៉ុន្តែយើងមិនបានអនុវត្តវាទេ៖ វាមិនបង្ហាញពីការកើនឡើងនូវផលិតភាពឆ្កួតៗនោះទេ ប៉ុន្តែទាមទារឱ្យមានការផ្លាស់ប្តូរប្រកបដោយហានិភ័យ។ វាពិបាកក្នុងការទស្សន៍ទាយពីរបៀបដែលម៉ាស៊ីនមេនឹងមានឥរិយាបទនៅពេលធ្វើការរយៈពេលយូរជាមួយនឹងឈុតជាច្រើន។ ដូច្នេះហើយ យើងធ្វើតាមច្បាប់៖ប្រសិនបើវាមិនបែកទេកុំជួសជុលវា"។
ប្រភព: www.habr.com