Back to Top
 
 
 

بلاگ

پشتیبانی از game maker در آپادانا

مدتی پیش پس از انتشار پستی در راستای معرفی آپادانا توسط دوستان ما در شرکت فن افزار شریف که کمال تشکر را از آن ها داریم، درخواست هایی در راستای پشتیبانی از Game Maker دریافت کردیم. در این پست بررسی فنی ابتدایی در این زمینه و میزان پشتیبانی فعلی را شرح می دهیم.

اکنون آپادانا به دو شکل قابل استفاده است. روش اول استفاده از SDK مخصوص Unity می باشد که از WebSocket برای ارسال و دریافت همه پیام ها (با استفاده از protocolی خاص و بسیار کوچک) استفاده می کند، می باشد و روش دوم استفاده از WebAPI هایی است که برای برخی ویژگی های آپادانا موجود هستند و با استفاده از JSON کار می کنند. هم اکنون این روش توسط یکی از مهمترین مشتریان آپادانا مورد استفاده قرار می گیرد. برنامه ما در باره اضافه کردن روش های دیگر بستگی به درخواست های مشتری های جدی و پروژه های آن ها دارد زیرا ما تیم بسیار کوچکی هستیم و منابع محدودی داریم. فعلا برنامه بعدی ما پشتیبانی از RUDP برای ساخت بازی های real-time در یونیتی بدون استفاده از WebSocket می باشد که برای انواعی از بازی بسیار سریع مثل Racing و FPS مناسب نیست و اولویت این قابلیت هم به پروژه های مشتریان و اولویت هایشان وابسته است. در صورت وجود مشتری جدی برای ویژگی های real-time در Game Maker پشتیبانی به شکل زیر قابل پیاده سازی خواهد بود.

استفاده از توابع شبکه GML برای ارسال و دریافت buffer هایی که از protocol ما پیروی می کنند ، پیاده سازی این ویژگی مستلزم کار بسیار می باشد و باید پروژه هایی جدی قصد استفاده از آپادانا در بازی های real-time در Game Maker را داشته باشند تا توجیه پیدا کند.

راه دیگر برای استفاده از آپادانا در Game Maker استفاده از WebAPI ما می باشد که توانایی کارهای real-time را ندارد ولی تمام توابع دیگر می توانند به آن اضافه شوند. لطفا در صورت نیاز به قابلیتی که در WebAPI وجود ندارد، به ما ایمیل بزنید تا قابلیت مورد نظر را به سرعت به WebAPI اضافه کنیم. امکان ساخت plugin برای راحتتر شدن کار با WebAPI هم وجود دارد ولی ما ترجیح می دهیم در صورت ساخت پلاگین، آن را با استفاده از TCP و binary protocol خودمان بسازیم مگر دلیل خاصی برای تغییر این تصمیم وجود داشته باشد و اولویت هایمان تغییر کند.  همچنین خوب است بدانید ما قصد پشتیبانی از GML به عنوان زبان اسکریپت نویسی در سرور آپادانا را نداریم زیرا استفاده از آن به عنوان زبانی مجزا بیرون از GameMaker نیاز به نوشتن کامپایلر GML دارد.

اولین ابزاری که خود من برای ساخت بازی با آن کار کردم Game Maker 6 بود و به دلیل میزان کاربران پشتیبانی از آن می تواند مفید باشد و میزان پشتیبانی فعلی ما برای بسیاری کار ها مثل LeaderBoard, cloud save, login, IAP verification و ... کافی می باشد. تنها مساله پارس کردن داده JSON در پروژه می باشد. تصمیم ما در این باره قطعی نیست و علاقه داریم با کاربران Game Maker در این باره گفت و گو کنیم. شما می توانید با استفاده از ایمیل یا گروه پرسش و پاسخ ما در تلگرام با ما در ارتباط باشید و یا با تلفن با ما تماس بگیرید.

لطفا این پست را به کاربران GameMaker که به استفاده از آپادانا علاقه دارند ارسال کنید تا نظرات خود را به ما اعلام کنند.

روش های optimize کردن بازی در unity

در این پست نکاتی راجع به بهینه سازی یا همان optimize کردن بازی در Unity را شرح می دهم. در صورت مفید بودن پست و استقبال مناسب مطالب بیشتری نیز در این باره پست خواهم کرد.

به طور کلی بهینه سازی یا Optimization به تغییر دادن برنامه در راستای اجرای سریعتر و استفاده بهتر از منابع گفته می شود. بازی سازی از کارهایی است که نیاز دارد برنامه نویس همواره هنگام نوشتن کد این مساله را مد نظر قرار دهد. بهینه سازی به دو دسته macro optimization و Micro optimization تقسیم می شود. دسته اول استفاده از الگوریتم ها و ساختار داده های مناسب برای حل مساله را شامل می شود و دسته دوم به تغییر توابع و عملگر ها و خط های کوچکی از کد و تغییر محاسبات کوچک به شکل بهینه گفته می شود. مثلا استفاده از ساختار آرایه به جای درخت برای استفاده بهتر از cache پردازنده و استفاده از Dictionary در صورت نیاز به یافتن مقادیر مختلف با سرعت بالا به جای آرایه و لیست از نوع macro optimizaiton و انجام تقسیم با استفاده از ضرب و یا استفاده از اعداد صحیح به جای اعداد اعشاری و انجام shift به جای اعمال ریاضی micro optimizaiton هستند.


هدف شما از بهینه سازی در Unity معمولا بالا بردن FPS و قابل اجرا کردن یک الگوریتم و پایین آوردن زمان انتظار کاربر می باشد. همچنین ممکن است برای اجرای بازی روی دستگاه های ضعیفتر نیز به این کار نیاز داشته باشید. اگر بازی را برای اجرا روی سرور بنویسید هم برای مصرف بهتر منابع سرور نیاز به Optimization دارید. برای داشتن یک بازی بهینه باید اولا هنگام نوشتن برنامه با آگاهی از میزان کار انجام شده و مصرف منابع هر عملیات کدی بهینه بنویسید و دوما هنگام مشاهده مشکل با استفاده از ابزار های اندازه گیری مثل profiler ها گلوگاه های سیستم یا همان bottle neck ها را پیدا کنید و آن ها را بهینه کنید. گلوگاه به بخش هایی گفته می شود که تغییر آن ها و سرعت بخشیدن به آن ها تاثیر زیادی بر روی بهینه شدن کل سیستم می گذارد و در حال حاضر منابع زیادی را به شکل غیر بهینه مصرف می کنند. ابتدا مواردی که باید بدانید تا کد بهینه بنویسید را بررسی می کنیم و سپس به روش های اندازه گیری و بهینه سازی می پردازیم.

 

توابع کند در یونیتی
توابعی در Unity وجود دارند که ممکن است در برخی موارد کار را ساده کنند ولی کندتر از توابع دیگر اجرا می شوند و شما باید تا حد ممکن از استفاده از آن ها خود داری نمایید. SendMessage و به خصوص BroadCastMessage و دیگر توابع این خانواده که برای صدا زدن متدی در یک GameObject دیگر و یا Component دیگر مورد استفاده قرار می گیرند بسیار از صدا زدن متد به شکل مستقیم کندتر هستند. این متد ها از reflection برای یافتن متد مورد نظر برای صدا زدن استفاده می کنند و لازم است بین GameObject ها و بچه هایشان در hierarchy و component های هر GameObject عملیات search انجام دهند. سیستم messaging جدید یونیتی بسیار سریعتر از SendMessage عمل می کند ولی تا جای ممکن خودتان متد های مورد نظر را با رفرنس (reference) دادن به GameObject های دیگر و component هایشان صدا بزنید.

GameObject.Find و GameObject.FindObjectWithTag بسیار کند هستند و لازم است کل گراف scene را برای یافتن GameObject مورد نظر جست و جو کنند. البته نسخه ای که دنبال Tag می گردد سریعتر از نسخه ای است که دنبال اسم می گردد.

GetComponent استفاده از این تابع اجتناب ناپذیر است ولی باید بدانید نسخه ای که string اسم component را به عنوان پارامتر دریافت می کند بسیار کندتر از نسخه ی generic و نسخه ای است که type دریافت می کند. همچنین GetComponentInChildren و GetComponentInParent به دلیل انجام جست و جو های بیشتر کندتر از خود Getcomponent هستند و سعی کنید از این توابع درون حلقه ها و کد هایی که زیاد اجرا می شوند (مثل Update و FixedUpdate) استفاده نکنید و مقادیر مورد نیاز را تا حد ممکن کش کنید و در متغیری ذخیره کنید و از مقدار ذخیره شده استفاده کنید.

RayCast و SphereCast و ... به طور کلی cast کردن کار کندی است ولی ray از همه اشکال دیگر بسیار سریعتر است و باید سعی کنید با حد اقل تعداد cast و محدود کردن فاصله و layer های مورد cast آن را بهینه کنید.
Instantiate و Destroy نیز مثل خیلی از موارد بالا باید استفاده شوند ولی هم اجرایشان به دلیل کپی کردن کل داده های یک GameObject کند است و هم باعث ورود و خروج داده های زیادی بین RAM و disk می شوند که کار کندی است. به همین دلیل در صورت داشتن مشکل با این موضوع بهتر است از object pool استفاده کنید که در manual خود یونیتی توضیح داده شده. برای این کار به جای از بین بردن و ساختن GameObject ها شما در ابتدا لیستی از مثلا 100 GameObject را می سازید و همه آنها را با استفاده از GameObject.SetActive غیر فعال می کنید و به جای ساخت GameObject یک آبجکت از لیست pool خود گرفته و فعال می کنید و به جای از بین بردن آبجکت را غیر فعال کرده و به pool برمی گردانید.

به طوری کلی توابعی که با رشته ها ، دیسک و یا شبکه سر و کار دارند و یا باید عملیات جست و جو انجام دهند و یا روی داد های زیادی در حافظه کار کنند کندتر از توابع دیگر هستند.

حلقه ها و تعریف Hot path
به بخش هایی از کد که بارها اجرا می شوند و تغییرات کوچکی در آن ها سرعت برنامه را بسیار کم و زیاد می کند، hot path گفته می شود. مثلا حلقه های تو در تو و یا حلقه های بسیار طولانی (با تعداد گردش بالا) که هر فریم اجرا می شوند و به طور کلی کد های درون Update, LateUpdate و FixedUpdate معمولا در hot path قرار دارند مگر این که کد درون این ساختار ها فقط در شرایط خیلی خاصی اجرا شوند و واقعا همیشه در حال اجرا نباشند. بهینه کردن کد های درون hot path ها مهمترین کار شما هنگام بهینه سازی است.

ساختار داده ها
داده های شما باید با استفاده از ساختمان داده های مناسب برای الگوی استفاده در بازی تعریف شوند. توضیح این مبحث بسیار طولانی بوده و مبحث درس ساختمان داده ها در دانشگاه می باشد. هنگام انتخاب یک ساختمان داده مثل آرایه ، لیست، صف و پشته (array, queue , stack) باید توجه کنید که مرتبه زمانی عملیات هایی که زیاد روی داده انجام می دهید چیست. مثلا اضافه کردن یک المان به یک لیست مرتب sortedList کندتر از اضافه کردن المان به لیست معمولی است ولی در عوض اگر شما به داده های مرتب داشته باشید، لیست مرتب داده ها را همواره به شکل مرتب به شما می دهد.
همچنین برخی ساختمان های داده با مدل حافظه و معماری سیستم بهتر کار می کنند. کلا ساختمان داده های خطی که المان های مربوط به هم به شکل خطی پشت هم قرار گرفته اند باعث استفاده بهتر از کش CPU شده و در بسیاری موارد مناسبتر از انواع دیگر داده هستند. توضیح مفاهیم مربوط به این مطلب نیز بسیار طولانی هستند و به پست های مخصوص به خود نیاز دارد.

رشته ها
به طور کلی استفاده از رشته ها (string) کند می باشد و باید سعی کنید تا جای ممکن به جای رشته از ساختار های دیگر برای چیزهایی مثل id و ... که واقعا رشته نیستند استفاده کنید. رشته ها در .NET از نوع immutable هستند یعنی هر تغییر در رشته در واقع باعث ساخته شدن رشته ای جدید در حافظه می شود که مصرف حافظه را بسیار بالا می برد. توابعی مثل string.split و ... تعداد زیادی رشته روی حافظه می سازند.

garbage collector
در این باره نیز باید پست کاملی نوشته شود ولی به طور کلی حافظه ای که برنامه شما با تعریف متغیر به خود تخصیص می دهد توسط سیستمی در محیط اجرایی .NET به نام garbage collector یا همان GC از برنامه بازپس گرفته می شود. پس از این که یک بخش از حافظه از دسترسی برنامه شما خارج شد و GC می توانست قطعا بگوید این حافظه مورد استفاده نیست، حافظه به سیستم باز می گردد تا برای کارهای دیگر به برنامه خودتان یا برنامه های دیگر داده شود. معمولا باید سعی کنید object هایی که می سازید یا سریع از بین بروند یا مدت بسیار زیادی در حافظه بمانند. کلا بهتر است تا حد ممکن آبجکت جدیدی نسازید. منظور از آبجکت یک کلاس در .NET است و نه GameObject در Unity هر چند ساخت یک GameObject نیز به دلیل ساخت تعداد زیادی آبجکت .NET از همین قانون پیروی می کند.
حافظه ای که برنامه شما می گیرد بر دو نوع است. حافظه heap که GC آن را مدیریت می کند و حافظه stack که بسیار سریعتر است و به سادگی مدیریت می شود و اصلا نیاز به جست و جو روی همه آبجکت ها توسط GC ندارد. داده های پایه .NET و struct ها روی stack تخصیص داده شده و class ها روی heap تخصیص داده می شوند. برای آبجکت های کوچک (از نظر سایز) که زود از بین می روند از struct ها استفاده کنید و همچنین رفرنس آبجکت ها را در متغیر های static قرار ندهید و اگر هم دادید پس از پایان نیاز به آن ها از درون متغیر پاک کنید (متغیر را به null ست کنید) تا GC بتواند حافظه را از برنامه پس بگیرد، زیرا تا وقتی که حتی یک رفرنس به یک بخش از حافظه در برنامه وجود داشته باشد ، حافظه پس گرفته نخواهد شد.

 

مصرف حافظه خود یونیتی
همه GameObject هایی که به شکل مستقیم یا غیر مستقیم از درون scene به آن ها رفرنسی وجود داشته باشد در حافظه لود می شوند. برای جلوگیری از لود شدن آبجکت هایی که نمی خواهید، آن ها را در scene رفرنس ندهید. برای جلوگیری از این مشکل ، اگر مثلا دو نوع از هر asset با اندازه های مختلف برای دستگاه های قدیمی و جدید دارید باید یا آن ها را در resources folder بگذارید و یا از asset bundle ها استفاده کنید.

فیزیک
به طور کلی هر چه تعداد collider ها بیشتر شود و هر چه تعداد rigidbody ها بیشتر شود ، فیزیک بخش بیشتر از وقت Unity را مصرف خواهد کرد. از collider های پیچیده در آبجکت های متحرک کمتر استفاده کنید و از mesh collider برای GameObject های متحرکت تا حد امکان استفاده نکنید.

اندازه گیری ها و profiler
حتی با رعایت موارد بالا و بسیاری موارد دیگر، شما باز هم نیاز خواهید داشت سیستم های نوشته شده را بهینه کنید. برای این کار به جای حدس زدن باید با تستفاده از profiler میزان مصرف حافظه و CPU را با profiler اهندازه بگیرید. برای این کار از منوی Window ادیتور Unity گزینه Profiler را انتخاب کنید. این ابزار به شما میزان مصرف حافظه، CPU و حتی شبکه و GPU را نشان می دهد. محاسبات فیزیک و صدا نیز در این پنجره نمایش داده می شوند و شما می توانید هم در editor و هم بازی های build شده در حال اجرا روی PC یا mobile را profile کنید. برای profile کردن build ها که جواب های دقیقتری هم به شما می دهد (به خصوص در mobile که محیط اجرا کاملا فرق دارد) باید هنگام build کردن تیک development build را بگذارید و ترجیحا autoconnect to profielr را هم انتخاب کنید. سپس در بخش بالای پنجره profiler آن برنامه در حال اجرا را به جای editor برای profile کردن انتخاب نمایید.

دقت کنید که چیز هایی که همیشه منابع زیادی را استفاده می کنند و درصد خوبی از حافظه و یا CPU را به خود اختصاص می دهند را بهینه کنید و وقت خود را برای بهینه  سازی کدی که از دوران پارینه سنگی تا کنون 4 بار و نیم اجرا شده است طلف نکنید مگر این که این کد باعث انتظار طولانی و یا پر شدن حافظه و کرش کردن دستگاه می شود.

همیشه سعی کنید دو بار اندازه گیری کنید و یک بار تغییر دهید. وقتی تغییری می دهید، دوباره profile کنید و نتیجه آن را چک کنید و اگر مشکل را حل نکرد آن را به حالت قبل برگردانید و تغییرات لازم دیگر را انجام دهید.

این پست نگاهی کلی بود به موارد مورد نیاز برای بهینه سازی، در صورت نیاز به دانستن بخشی خاص آن را در کامنت ها با ما در میان گذارید.

چگونه بى دردسر اكانت دولپرى گوگل و اپل بسازيم

در اين پست قصد دارم یک استارت آپ رو بهتون معرفى كنم که در اين چندسالي که باهاشون فعاليت ميكنيم سابقه خوبى داشتن و هميشه استرس هاى انتقال پول و خريدهاى خارجي رو برای ما كم كردن.

اسم اين استارت آپ پيمنت٢٤ هستش ، من چند تا از خدماتى كه ميتونه براى جامعه بازى سازى مفيد باشه رو براتون ليست ميكنم.

  • ساخت اكانت دولوپرى گوگل
  • ساخت اكانت دولوپري اپل
  • ساخت اكانت انترپرايز اپل
  • نقد كردن درآمدهاى ارزى
  • خريد از فروشگاههای مانند Asset Store - Unity
  • باز كردن حساب PayPall, WebMoney, Payoneer

براى اطلاعات بيشتر ميتونين به وبسايت www.payment24.ir مراجعه كنين.

اميدوارم كه اين پست براى شما مفيد باشه.

چگونه سرور بازی آنلاین بنویسیم

در پست قبلی انواع معماری ساخت بازی آنلاین از نظر شبکه را بررسی کردیم. در این پست با این تصور که ما قصد داریم از مدل کلاینت سروری برای ساخت بازی آنلاین استفاده کنیم، روش های مختلف ساخت بازی آنلاین را بررسی می کنیم. در همه این روش ها می توان بخشی از منطق بازی را روی سرور اجرا کرد و یا کل منطق را در سرور اجرا کرد و نتیجه را به کلاینت ها ارسال کرد. برای داشتن دیدی مناسب ابتدا باید انواع بازی را از نظر شبکه بررسی کنیم و بعد به روش های ساخت بپردازیم.

بازی ها از نظر شبکه به دو گروه پر ترافیک و کم ترافیک تقسیم می شوند. تعداد کاربران هم زمان، میزان داده ای که باید از هر بازی کن به سرور ارسال شود، میزان داده ای که سرور باید به هر بازی کن ارسال کند و تعداد دفعات مورد نیاز برای ارسال داده ها این موضوع را مشخص می کنند. بعضی بازی ها مثل بازی های MMO تحت وب شبیه تراویان میزان داده بسیار کمی را در فواصل زمانی طولانی بین کلاینت و سرور جا به جا می کنند و بعضی مثل Call of duty باید در ثانیه حدود 40 بار بخشی از داده های هر کلاینت را به سرور ارسال کنند و وضعیت فعلی دنیای بازی را نیز از سرور بگیرند. همچنین از نظر زمان پاسخ گویی، بعضی بازی ها طوری هستند که پاسخ می تواند چند صد میلی ثانیه بعد از سرور به کلاینت برگردد و در برخی بازی ها بیش از چند ده میلی ثانیه فاجعه محسوب می شود.

بازی هایی مثل clash royale که در وسط دو گروه بسیار سریع و بسیار کند قرار می گیرند و ارتباط realtime نسبتا سریع برای آن ها لازم است ولی اگر مثلا یک پیام 200 میلی ثانیه دیر برسد هم در کلاینت می توان جلوی بروز مشکل و متوجه شدن کاربر را گرفت. در مقابل برای بازی های FPS و Racing سرور حتما باید سریع باشد و همه چیز را با بالاترین سرعت ممکن بین کلاینت ها جا به جا کند و تصمیمات خود را نیز بگیرد. در بازی هایی مثل Clash of clans حتی یکی دو ثانیه هم قابل تحمل است و فشار شدیدی روی سرور نیست زیرا بازی کلا به شکل async می باشد و اصلا ارتباط real time بین کاربران برقرار نمی شود.

در نتیجه صحبت های بالا بازی ها را به سه گروه تقسیم می کنیم. گروه اول بازی هایی که تحمل دیر رسیدن پیام را تا حد زیادی دارند و در آن ها یا کاربران به طور مستقیم در ارتباط نیستند و یا اگر هستند طول کشیدن زمان حد اقل اگر متداول نباشد قابل پذیرش است. همه بازی های MMO تحت مرورگر وب و async multiplayer که بازی کنان لزوما هم زمان در بازی شرکت نمی کنند از این دسته هستند. شاید بتوان بازی هایی مثلا تخته نرد، انواع بازی با ورق و منچ و ... را نیز از این دسته دانست، هر چند گاهی شرکت ها و یا کاربران توقع ندارند سرور این بازی ها نیز چندان کند عمل کند. گروه دوم بازی هایی مثل Clash Royale هستند که کاربران با هم ارتباط real time دارند ولی دیر رسیدن پیام تا چند صد میلی ثانیه در گاهی اوقات قابل پذیرش است. گروه سوم بازی های بسیار سریع معمولا جنگی و یا مسابقه ای بسیار سریع هستند و نیاز است که اطلاعات زیادی در چند ده میلی ثانیه بین کاربران جا به جا شود و سرور نیز تصمیمات را بسیار سریع بگیرد. نوع دیگری از بازی ها هستند که از تعداد کاربران بسیار بالا پشتیبانی می کنند که MMO های معمول مثل World of Warcraft هستند که همان طور که در پست قبل گفته شد آن ها را بعدا بررسی خواهیم کرد.

 

روش های ساخت

برای ساخت بازی ها گروه اول امکان استفاده از تکنولوژی های معمول ساخت نرم افزار های تحت وب و Web API ها وجود دارد و می توان آن ها را به شکل stateless و با تکنولوژی هایی مثل ASP.NET Web API و PHP پیاده سازی کرد. ممکن است به دلایل مختلف شما این کار را ترجیح ندهید اما از نظر توانایی ساخت شما می توانید هر بازی و state فعلی آن را کاملا در database خود مدل کنید و با صدا زدن WebA API های مختلف آن را به روز کنید و یا وضعیت آخر بازی را از سرور بگیرید. مهمترین مزیت این کار سادگی پیاده سازی و آشنا بودن بسیاری از افراد با این تکنولوژی ها می باشد. در صورتی که خواستید از چنین تکنولوژی هایی برای ساخت بازی خود استفاده کنید، دقت کنید که از یک تکنولوژی مناسب ترجیحا با قابلیت های پردازش نامتقارن asynchronous استفاده کنید و databaseی را برگزینید که توانایی داشتن performance بالا هنگام نوشتن حجم زیادی از داده را داشته باشد.

نکته قابل توجه این است که شما می توانید این بازی ها را به شکل stateful و با تکنولوژی های مورد نیاز برای ساخت بازی های آنلاین گروه دو و سه نیز پیاده کنید و نسبت به منطق بازی ممکن است این کار را ترجیح هم بدهید. قبل از توضیح دادن روش ساخت بازی های گروه دو و سه مفاهیم مهم مربوط را بررسی می کنیم.

 

مفاهیم مربوط به ساخت سرور های بازی real time

اولین مفهوم مهم Stateless و یا Stateful بودن سرور است. یک سرور Stateless هیچ داده ای در باره وضعیت فعلی برنامه را در حافظه نگه نمی دارد و همه توابع کل داده ها را روی پایگاه داده ذخیره کرده و بعد نیز هنگام نیاز از روی پایگاه داده می خوانند. این روش در گذشته با تعداد کمتر کاربران و توقع کمتر برای زمان پاسخ گویی باعث می شد مشکل scale شدن برنامه به تعداد کاربر بالا کاملا حل شود و بتوان به راحتی web server های جدید را برای پاسخ گویی بیشتر به سیستم اضافه کرد. در این سیستم وقتی میزان کاربران از حد تحمل پایگاه داده بیشتر شود درخواست ها شروع به کند شدن و یا حتی timeout شدن می کنند. برای جلوگیری از این مشکل می توان یه cache میان web server ها و database قرار داد اما Cache هم توانایی محدودی در پاسخ گویی دارد و مشکل قدیمی شدن داره را دارد که باید داده هایش را با Database به روز کند.

برنامه های Stateful برنامه هایی هسند که داده مورد نیاز برای دانستند وضعیت فعلی برنامه را در حافظه نگه می دارند و با سرعت از آن برای انجام عملیات استفاده می کنند. البته این برنامه ها هم باید برای جلوگیری از ، از دست رفتن داده ها و پر نشدن حافظه داده ها را هر چند وقت یک بار در Database ذخیره کنند. زمان ذخیره سازی و نرخ آن بسته به نوع برنامه و داده ها دارد. مثلا تراکنش های مالی و دیگر داده های مهم باید حتما هنگام تغییر در Database نوشته شوند و فقط در این صورت تغییراتشان پذیرفته شود اما داده های مربوط به طول جلسه کاربری بازی کنان را می توان هر چند دقیقه یک بار برای مقاوم شدن سیستم در برابر خطا ذخیره کرد.

تحمل خطا یا Fault tolerance به توانایی پذیرش خطا هایی نرم افزاری و یا سخت افزاری توسط سرور گفته می شود. مثلا این توانایی که سروری که بر روی 5 ماشین کار می کند، با قطع شدن یکی از آن ها از شبکه و یا Crash کردنش نه از کار بیفتد و تا حد ممکن داده کمی از دست بدهد.

مقیاس پذیری یا Scalability به این توانایی گفته می شود که با زیاد شدن منابع سیستم بتواند به درخواست های بیشتری و با سرعت بالاتری پاسخ بدهد. این توانایی به دو مدل عمودی و عفقی تقسیم می شود. Horizontal Scalability یا همان روش افقی به توانایی مقیاس پذیر بودن روی چند ماشین گفته می شود، یعنی با زیاد کردن تعداد ماشین های سرور سیستم قدرت پاسخ گویی بیشتری پیدا می کند. Vertical Scalability یا همان روش عمودی به توانایی زیاد شدن قدرت پاسخ گویی با زیاد شدن منابع روی ماشین های فعلی مثل CPU و RAM گفته می شود.

 

مدل برنامه نویسی بازی های Real Time در سرور

برای پاسخ گویی به درخواست های کاربران به شکل سریع و داشتن ارتباط چند نفره معمولا بهتر است از یک socket دو طرفه مثلا ساکت (سوکت) TCP و یا UDP و یا پروتکل هایی بر روی این ها استفاده کرد و استفاده از درخواست های HTTP باعث زیاد شدن زمان پاسخ گویی می شود. همچنین باید از پروتکل های دودویی (Binary) برای ارسال و دریافت پیام ها استفاده کرد زیرا پردازش روش های متنی ارسال و دریافت داده و serialize کردن آن ها مثل JSON باعث کندی سیستم و مصرف بالای حافظه و پهنای باند می شوند. همچنین معمولا به دلیل نیاز به پاسخ گویی سریع این سیستم ها به شکل Stateful نوشته شده و تعداد درخواست های مختلف IO از جمله Database و یا File System به حد اقل می رسد.

برای پیاده سازی منطق بازی ممکن است از کتابخانه های معمولی برنامه نویسی و یا Game Engine ها استفاده شود. معمولا در بازی هایی که به فیزیک و Path Finding و ... برای اجرای سرور نیاز دارند یا از خود Game Engine و یا از کتابخانه های مورد استفاده در آن در پیاده سازی منطق بازی در سور نیز استفاده می شود. همچنین بعضی از انواع بازی Real Time به سادگی Scale شده و هر جلسه بازی کوتاه و بین چند نفر انجام می شود و برخی دیگر نیاز به تکنیک های خاص برای Scale شدن دارند. چون همیشه داده های کل عملیات ها در Database ذخیره نمی شود برای بالا بردن تحمل خطا نیز از تکنیک های خاصی استفاده می شود که در آینده بررسی خواهیم کرد.

پروتکل های شبکه و serialization داده ها و همچنین Scalability و Fault teolrance هر یک خود مطالب بسیار بزگری هستند که توضیح زیادشان این پست را طولانی می کند و در آینده به تفصیل به آن ها خواهیم پرداخت.

اگر بخواهیم چند تکنولوژی مناسب برای ساخت سرور بازی های Real Time را نام ببریم، استفاده از کتابخانه شبکه خود Game  Engine ها مثل Unity و UE4 روشی ساده برای پیاده سازی منطق اصلی بازی به شکل ساده می باشد و تکنولوژی هایی مثل Microsoft Orleans (که ما برای آپادانا از آن استفاده می کنیم)، Erlang، Akka و C++ به همراه کتابخانه های شبکه مناسب برای ساخت بخش های دیگر سیستم و گاهی خود منطق بازی مناسب هستند. بعضی ها اکنون به NodeJs فکر می کنند که چرا اسمی از آن و سیستم هایی مثل Parse نیاوردیم که در پستی به طور خاص به زودی درباره آن سخن خواهیم گفت. بای این که گفتن این جمله بدون توضیحات خطر کشته شدن توسط سیلی از برنامه نویسان را به سراغ من می آورد ولی NodeJs اصلا تکنولوژی مناسبی برای پیاده سازی سرور های قدرتمند بازی ها، به خصوص بازی های پر کاربر نیست.

انواع معماری ساخت بازی آنلاین از نظر شبکه

انواع مختلفی از بازی ها وجود دارند که از طریق شبکه اینترنت یا شبکه داخلی بین بازی کنان ارتباط برقرار می کنند. ما به مجموعه این بازی ها، بازی های آنلاین (online games) یا بازی های چند نفره (multiplayer games) می گوییم. اگر این بازی ها تعداد بسیار زیادی بازی کن را در دنیای مشترکی گرد هم آورند به آن ها بازی های MMO (Massively multiplayer online) می گوییم که در این پست راجع به آن ها صحبت نمی کنیم ولی در آینده راجع به آن ها نیز خواهم گفت. من در ساخت یک بازی MMO شرکت داشته ام و این کار بسیار جالب و هیجان انگیز است.

بازی های آنلاین معمول را به روش های مختلفی می توان پیاده سازی کرد و این روش ها بستگی به نوع بازی و میزان تقلب قابل تحمل دارند. مساله اول معماری کلی می باشد که می تواند peer to peer و یا client server باشد. در مدل p2p بازی کنان به شکل مستقیم به یک دیگر وصل می شوند و یکی از آن ها به عنوان کلاینت اصلی master client در نظر گرفته می شود که مشخص می کند چه اتفاقی در بازی افتاده و اگر میان نتیجه عملی و یا وضعیت یک متغیر بین کلاینت ها اختلافی باشد، مقداری که در کلاینت اصلی وجود دارد به عنوان حقیقت در نظر گرفته می شود. بسیاری از بازی های کنسول ها با این مدل کار می کنند. اگر معماری بر پایه کلاینت و سرور باشد یک برنامه به عنوان سرور بین همه کلاینت ها ارتباط برقرار می کند و همه کلاینت ها فقط به سرور متصل می شوند و سرور پیام ها را بین آن ها رد و بدل می کند. در این مدل منطق بازی می تواند server authoritative باشد و یا نباشد. در صورت server authoritative بودن ، سرور به کلاینت ها می گوید که متغیر های بازی در چه وضعیتی قرار دارند و به طور کلی دنیای بازی در چه وضعی است. در غیر این صورت سرور فقط داده ها را بین کلاینت ها رد و بدل کرده و مثل مدل p2p یک master client مسول نشان دادن وضعیت دنیای بازی به بقیه است. آپادانا تا به حال فقط از سرور none-authoritative پشتیبانی می کرد. با افزودن scripting مدل server authoritative نیز پوشش داده خواهد شد.

فرق مدل p2p با none-authoritative server این است که کلاینت ها همواره می توانند به سرور متصل شوند و مشکلات معمول در اتصال بین کلاینت ها رخ نخواهند داد. چون کلاینت ها بیشتر مواقع پشت firewall قرار دارند وصل کردن آن ها یه یک دیگر همواره به سادگی امکان پذیر نیست و در واقع بیشتر بازی های تجاری p2p دارای سرور none-authoritative هستند که هنگام رخ دادن مشکل در اتصال کلاینت ها از ان استفاده می کنند. به سروری که فقط داده ها را بین کلاینت ها جا به جا می کند، relay server نیز گفته می شود.

ساخت بازی ها در مدل p2p به شکلی که قابلیت انتشار داشته باشند کار بسیار پیچیده ایست و کتابخانه های آماده زیادی نیز برای آن وجود ندارد اما اگر شما این کار را بکنید هزین های سرور را از دوش خود برداشته اید. در مقابل در صورت p2p بودن بازی یا استفاده از سرور none-authoritative بازی کنان کاملا امکان تقلب دارند و می توانند وضعیت بازی را به نام خود تغییر دهند. مکانیزم هایی برای جلوگیری از این کار وجود دارد ولی در نهایت اگر سرور معین کننده وضعیت نهایی دنیای بازی نباشد، کلاینت ها توانایی تقلب را خواهند داشت. به این دلیل ها بسیاری از بازی ها از authoritative server ها استفاده می کنند. البته چون چک کردن همه چیز در سرور هزینه به همراه دارد معمولا یک مدل نیمه authoritative انتخاب می شود که موارد مهم در سرور چک می شوند.

مثلا اگر شما بخواهید یک بازی آنلاین FPS بسازید احتمال زیاد همه شلیک های کاربران در سرور چک می شوند و میزان آسیب به وجود آمده به کلاینت ها اطلاع داده خواهند شد اما جهت دوربین هر کاربر را لازم نیست با سرور چک کنید و حتی اگر کاربران سر کاراکترشان را خیلی سریع بچرخانند تقلب شدیدی نمی توانند بکنند، حتی اگر هم بخواهید چک کنید، یک چک حدودی برای نپذیرفتن تغییرات شدید ناگهانی کافی است. در بازی های MMO حتی گاهی برخورد کاراکتر با اشیای کوچک نیز در سرور چک نمی شود و فقط برخورد با دیوار ها و اجزای بزرگ دنیا چک می شود زیرا این بازی ها باید هزاران کاربر را به شکل هم زمان در یک دنیا پشتیبانی کنند و هزینه تشخیص برخورد بسیار بالا می باشد.

با افزوده شدن قابلیت Scripting به آپادانا شما به زودی قادر خواهید بود منطق بازی خود را در سرور اجرا کنید و برای زمان مصرف شده نیز پولی به ما پرداخت نخواهید کرد.

صفحه4 از6

تمامی حقوق مادی و معنوی این سایت متعلق به گروه آپادانا می باشد.
 info@apadana-platform.ir