ساخت یک بازی آنلاین فقط به حرکت دادن دو بازیکن در یک صحنه مشترک محدود نمیشود. اتصال پایدار، تعیین مالکیت اشیا، همگامسازی وضعیت بازی، مدیریت قطع ارتباط و جلوگیری از تقلب، همگی بخشی از معماری یک محصول چندنفره واقعی هستند. Unity 6 مجموعهای از ابزارهای مرتبط را ارائه میکند که Netcode for GameObjects یکی از مهمترین اجزای آن است.
این فریمورک برای پروژههای مبتنی بر GameObject و MonoBehaviour طراحی شده و به تیم اجازه میدهد مفاهیم شبکه را در ساختاری نزدیک به روند معمول برنامهنویسی یونیتی پیادهسازی کند. بااینحال، نصب پکیج بهتنهایی یک بازی آنلاین مقیاسپذیر نمیسازد و انتخاب معماری باید بر اساس سبک بازی، تعداد کاربران و حساسیت رقابت انجام شود.
Unity 6 Multiplayer و Netcode for GameObjects چیست؟
عبارت Unity 6 Multiplayer به مجموعه ابزارها و سرویسهایی اشاره دارد که بخشهایی مانند ارتباط شبکه، Lobby، Relay، Matchmaker، احراز هویت و میزبانی مسابقه را پوشش میدهند. Netcode for GameObjects یا NGO لایهای سطح بالا برای انتقال وضعیت GameObjectها میان سرور و کلاینتها است و میتواند در مدل Host، Client-Server یا Dedicated Server استفاده شود.
در این ساختار معمولاً یک NetworkManager چرخه اتصال را کنترل میکند. اشیایی که باید در شبکه شناخته شوند NetworkObject دارند و رفتارهای شبکهای داخل NetworkBehaviour نوشته میشوند. این اجزا مشخص میکنند چه شیئی روی شبکه ایجاد شود، مالک آن کدام بازیکن باشد و تغییرات مهم با چه روشی به سایر کاربران برسد.
اجزای اصلی NGO
- NetworkManager برای شروع Host، Server یا Client و مدیریت نشست شبکه
- NetworkObject برای اختصاص شناسه شبکه و کنترل مالکیت اشیا
- NetworkBehaviour برای نوشتن منطق قابل اجرا در محیط چندنفره
- NetworkVariable برای نگهداری وضعیت همگامشونده مانند امتیاز یا سلامت
- RPC برای ارسال درخواست یا رویداد میان کلاینت و سرور
- NetworkTransform برای همگامسازی موقعیت، چرخش و مقیاس اشیا
ساخت نمونه اولیه اتصال
در اولین Prototype بهتر است یک صحنه ساده شامل NetworkManager، رابط ورود و یک Prefab بازیکن ساخته شود. Prefab باید NetworkObject داشته باشد و در فهرست Prefabهای شبکه ثبت شود. سپس برنامه در حالت Host روی یک دستگاه و Client روی دستگاه دیگر آزمایش میشود. این مرحله فقط صحت اتصال پایه را ثابت میکند و هنوز معادل معماری نهایی نیست.
برای آزمایش محلی میتوان از Unity Transport استفاده کرد. در نسخه قابل انتشار، آدرس سرور، روش احراز هویت و سیاست بازیابی اتصال باید مشخص باشد. قرار دادن آدرسها یا اطلاعات حساس در کلاینت مناسب نیست و تنظیمات محیط توسعه، آزمایش و تولید باید از یکدیگر جدا شوند.
NetworkVariable یا RPC؛ کدام مناسب است؟
NetworkVariable برای وضعیتی مناسب است که باید مقدار فعلی آن در اختیار بازیکنان مجاز قرار بگیرد. سلامت شخصیت، وضعیت آماده بودن کاربر و امتیاز نمونههای رایج هستند. مزیت مهم آن این است که کاربری که دیرتر وارد مسابقه میشود میتواند مقدار فعلی را دریافت کند، بدون آنکه تمام رویدادهای قبلی دوباره اجرا شوند.
RPC بیشتر برای اعلام یک عمل یا درخواست استفاده میشود؛ برای مثال بازیکن درخواست شلیک میفرستد و سرور پس از اعتبارسنجی نتیجه را اعلام میکند. ارسال دائمی موقعیت یا دادههای حجیم با RPC میتواند ترافیک و پیچیدگی را افزایش دهد. انتخاب درست باید بر اساس ماهیت داده، نرخ تغییر و نیاز بازیکنان تازهوارد انجام شود.
معماری Server Authoritative
در بازی رقابتی نباید نتیجه حساس صرفاً توسط کلاینت تعیین شود. کلاینت میتواند ورودی حرکت یا شلیک را ارسال کند، اما سرور باید سرعت، فاصله، مهمات، برخورد و نتیجه را اعتبارسنجی کند. این مدل احتمال دستکاری را کاهش میدهد و یک مرجع واحد برای وضعیت مسابقه ایجاد میکند.
Server Authoritative هزینه پردازش و توسعه بیشتری دارد و برای حفظ حس پاسخگویی ممکن است به Prediction، Interpolation و Reconciliation نیاز باشد. در بازی نوبتی اجرای آن سادهتر است، زیرا نرخ پیام پایینتر است. برای بازی اکشن سریع، طراحی Tick Rate، جبران تأخیر و بافر ورودی اهمیت بیشتری پیدا میکند.
Relay، Lobby و Matchmaker
Netcode مسئول منطق انتقال وضعیت است، اما بسیاری از محصولات به سرویسهای تکمیلی نیاز دارند. Lobby بازیکنان را پیش از مسابقه کنار هم قرار میدهد، Matchmaker کاربران مناسب را انتخاب میکند و Relay بدون افشای مستقیم نشانی شبکه کاربران، ارتباط را عبور میدهد. Dedicated Server نیز میتواند مسابقه را روی یک نمونه مستقل اجرا کند.
استفاده همزمان از تمام سرویسها همیشه ضروری نیست. یک بازی دونفره دوستانه ممکن است با Lobby و Relay راهاندازی شود، درحالیکه بازی رقابتی با اقتصاد داخلی به احراز هویت، بکاند، سرور اختصاصی و ذخیره نتایج نیاز دارد. معماری باید متناسب با ریسک و مدل درآمدی محصول باشد.
بهینهسازی پهنای باند
ارسال هر تغییر در هر فریم اشتباه رایجی است. نرخ ارسال باید از نرخ رندر جدا باشد و فقط داده لازم منتقل شود. فشردهسازی مقادیر، Quantization، Delta Compression، تعیین محدوده علاقه بازیکن و غیرفعال کردن همگامسازی اشیای دور، مصرف پهنای باند و توان سرور را کاهش میدهد.
NetworkTransform آماده شروع است، اما برای همه سبکها بهترین نتیجه را نمیدهد. در پروژه جدی ممکن است همگامسازی اختصاصی برای شخصیت، وسیله نقلیه یا توپ نوشته شود. ابتدا باید شاخصهایی مانند حجم پیام، پیام در ثانیه، تأخیر و درصد Packet Loss اندازهگیری شوند و سپس بهینهسازی بر اساس داده واقعی انجام شود.
تستهایی که باید انجام شوند
- اتصال چند کلاینت روی شبکه محلی و اینترنت واقعی
- شبیهسازی تأخیر، نوسان شبکه و از دست رفتن بستهها
- قطع ناگهانی اینترنت و ورود مجدد بازیکن
- ورود همزمان تعداد زیادی کاربر به Lobby و مسابقه
- تلاش برای ارسال فرمان نامعتبر یا دستکاری نتیجه
- بررسی مصرف CPU، حافظه و پهنای باند سرور
زمان و هزینه پیادهسازی
یک نمونه دونفره ساده ممکن است طی چند هفته آماده شود، اما محصول تجاری دارای حساب کاربری، Matchmaking، رتبهبندی، بازیابی نشست و پنل مدیریت معمولاً به چند ماه توسعه نیاز دارد. تعداد بازیکنان، سرعت گیمپلی، سطح امنیت، پلتفرمها و زیرساخت میزبانی بیشترین اثر را بر هزینه دارند.
در JPGames ابتدا یک Prototype شبکهای ساخته میشود تا ریسک معماری، کیفیت اتصال و رفتار بازی بررسی شود. پس از تأیید، سیستمهای حساب کاربری، لابی، مسابقه و مانیتورینگ بهصورت مرحلهای توسعه پیدا میکنند. برای برآورد دقیق Unity 6 Multiplayer بهتر است GDD، تعداد کاربران هدف و پلتفرمهای انتشار مشخص باشند.