എന്റെ ഗെയിം എഞ്ചിനായി ഞാൻ കോറൂട്ടീനുകൾ (Coroutines) നിർമ്മിച്ചു, പക്ഷേ പിന്നീട് അവ ഉപയോഗിച്ചില്ല

എന്റെ ഗെയിം എഞ്ചിനായി ഞാൻ ഒരു ജനറേറ്റർ കോറൂട്ടീൻ സിസ്റ്റം (generator coroutine system) നിർമ്മിച്ചു. അതിൽ 122 വരി കോഡും 12 ടെസ്റ്റുകളും ഉണ്ടായിരുന്നു. ഇത് 'callback hell' എന്ന പ്രശ്നം പരിഹരിച്ചു. സ്ക്രിപ്റ്റുകൾ ലളിതമായ വരികൾ പോലെ തോന്നിപ്പിച്ചു.

എന്നാൽ എന്റെ ഗെയിം ലോജിക്കിനായി അത് ഉപയോഗിക്കണ്ട എന്ന് ഞാൻ തീരുമാനിച്ചു. പകരം ഞാൻ ഒരു ഫൈനൈറ്റ് സ്റ്റേറ്റ് മെഷീൻ (Finite State Machine - FSM) ആണ് ഉപയോഗിച്ചത്.

അതിന്റെ കാരണങ്ങൾ താഴെ പറയുന്നവയാണ്.

റിയൽ-ടൈം ഗെയിമുകളിൽ ജനറേറ്ററുകൾ ഉപയോഗിക്കുമ്പോൾ ഉണ്ടാകുന്ന രണ്ട് വലിയ പ്രശ്നങ്ങൾ മിക്ക ട്യൂട്ടോറിയലുകളും അവഗണിക്കുന്നു: മെമ്മറിയും (memory) സേവിംഗും (saving).

  1. മെമ്മറി പ്രഷർ (Memory Pressure) ഒരു ജനറേറ്ററിൽ നിങ്ങൾ ഓരോ തവണ .next() വിളിക്കുമ്പോഴും, ജാവാസ്ക്രിപ്റ്റ് എഞ്ചിൻ ഒരു പുതിയ ഒബ്‌ജക്റ്റ് നിർമ്മിക്കുന്നു. ഈ ഒബ്‌ജക്റ്റിൽ നിലവിലെ മൂല്യവും (current value) സ്റ്റാറ്റസും അടങ്ങിയിരിക്കുന്നു.

60 FPS-ൽ പ്രവർത്തിക്കുന്ന ഒരു ഗെയിം ലൂപ്പിൽ, ഇത് നിരന്തരമായ ഗാർബേജ് കളക്ഷൻ പ്രഷർ (garbage collection pressure) ഉണ്ടാക്കുന്നു. പെർഫോമൻസ് സ്ഥിരമായി നിലനിർത്താൻ എന്റെ എഞ്ചിൻ 'zero-allocation' നിയമം പിന്തുടരുന്നു. ജനറേറ്ററുകൾ ആ നിയമം ലംഘിക്കുന്നു. അവ ഓരോ ഫ്രെയിമിലും ചെറിയ ഒബ്‌ജക്റ്റുകളുടെ ഒരു നിര തന്നെ സൃഷ്ടിക്കുന്നു.

  1. സീരിയലൈസേഷൻ പ്രശ്നം (The Serialization Problem) ഒരു ഗെയിമിന് സേവ് ചെയ്യാനും ലോഡ് ചെയ്യാനും ആവശ്യമുണ്ട്. നിലവിലെ ഗെയിം സ്റ്റേറ്റിനെ ഡാറ്റയാക്കി മാറ്റാനും പിന്നീട് അത് തിരികെ കൊണ്ടുവരാനും നിങ്ങൾക്ക് സാധിക്കണം.

നിർത്തിയിട്ടിരിക്കുന്ന (paused) ഒരു ജനറേറ്ററിനെ നിങ്ങൾക്ക് സീരിയലൈസ് ചെയ്യാൻ കഴിയില്ല. അതിന്റെ സ്റ്റേറ്റ് എഞ്ചിന്റെ ആന്തരിക സ്ലോട്ടുകളിൽ (internal engine slots) ആണ് ഇരിക്കുന്നത്, നിങ്ങൾക്ക് അവ ആക്സസ് ചെയ്യാൻ കഴിയില്ല. നിങ്ങൾ അത് സേവ് ചെയ്യാൻ ശ്രമിച്ചാൽ, ഒരു ശൂന്യമായ ഒബ്‌ജക്റ്റോ അല്ലെങ്കിൽ ഒരു എററോ ആണ് ലഭിക്കുക.

ഒരു ഫൈനൈറ്റ് സ്റ്റേറ്റ് മെഷീൻ (FSM) വ്യത്യസ്തമാണ്. ഇതിൽ സ്റ്റേറ്റ് എന്നത് ഒരു കംപോണന്റിലെ വെറുമൊരു സ്ട്രിംഗ് (string) മാത്രമാണ്.

  • സേവ് ചെയ്യാൻ: ആ സ്ട്രിംഗ് ഡിസ്കിലേക്ക് എഴുതുക.
  • ലോഡ് ചെയ്യാൻ: സ്ട്രിംഗ് വായിച്ച്, അവിടെ നിന്ന് തുടങ്ങാൻ FSM-നോട് പറയുക.

ഒരു പ്രൊഫഷണൽ ഗെയിമിന് ഏറ്റവും പ്രധാനപ്പെട്ട രണ്ട് കാര്യങ്ങൾ—പെർഫോമൻസും പെർസിസ്റ്റൻസും (performance and persistence)—FSM കൈകാര്യം ചെയ്യുന്നതുകൊണ്ടാണ് അത് വിജയിച്ചത്.

എങ്ങനെ തിരഞ്ഞെടുക്കാം:

ലോജിക് മെയിൻ ഫ്രെയിം ലൂപ്പിനുള്ളിലാണോ?

  • അല്ല: ഒരു ജനറേറ്റർ കോറൂട്ടീൻ ഉപയോഗിക്കുക. അസറ്റുകൾ ലോഡ് ചെയ്യുന്നതോ ഓൺബോർഡിംഗോ പോലുള്ള ഒറ്റത്തവണ പ്രക്രിയകൾക്ക് അവ മികച്ചതാണ്.
  • അതേ: അടുത്ത ചോദ്യം ചോദിക്കുക.

സേവ് ചെയ്താലും സ്റ്റേറ്റ് നിലനിൽക്കേണ്ടതുണ്ടോ?

  • അതേ: ഒരു ഫൈനൈറ്റ് സ്റ്റേറ്റ് മെഷീൻ ഉപയോഗിക്കുക.
  • അല്ല: അടുത്ത ചോദ്യം ചോദിക്കുക.

ഒരേസമയം നിരവധി സീക്വൻസുകൾ പ്രവർത്തിപ്പിക്കുന്നുണ്ടോ?

  • അതേ: ഒരു ഫൈനൈറ്റ് സ്റ്റേറ്റ് മെഷീൻ ഉപയോഗിക്കുക.
  • അല്ല: ഒരു ജനറേറ്റർ കോറൂട്ടീൻ ഉപയോഗിക്കുക.

ജനറേറ്ററുകൾ ഒരു തെറ്റല്ല. അവ 'hot path'-ന് അനുയോജ്യമല്ലാത്ത ഉപകരണങ്ങൾ മാത്രമാണ്. അവയെ 'async glue' ആയി ഉപയോഗിക്കുക, എന്നാൽ ഗെയിം ലോജിക്കിനായി FSM-കൾ ഉപയോഗിക്കുക.

Source: https://dev.to/grzott/i-built-generator-coroutines-for-my-game-engine-then-didnt-use-them-o3g