این سند، وظایف فنی مورد نیاز برای بازمهندسی یک پروژه موجود که با زیرساخت شبکه Mirror توسعه یافته را تشریح میکند. هدف اصلی، تفکیک پروژه به دو خروجی مجزا و کاملاً بهینهسازیشده است: یکی برای هدستهای واقعیت مجازی (VR) و دیگری برای پلتفرم WebGL.
یک الزام کلیدی این است که هر دو نسخه باید از یک زیرساخت سرور یکپارچه و مشترک پشتیبانی کنند و معماری شبکه باید به صورت Multi-Client باقی بماند. فرآیند تفکیک با هدف اصلی کاهش حجم نهایی بیلد (Build) و بهینهسازی مصرف حافظه برای هر پلتفرم به صورت جداگانه انجام میشود. برای مثال، پروژه نسخه WebGL نباید شامل هیچکدام از پکیجها یا داراییهای مرتبط با VR باشد و بالعکس.
متخصص مسئول این وظیفه باید دانش عمیقی در زمینه معماری شبکه Mirror، سیستم Addressables یونیتی و تکنیکهای پیشرفته بهینهسازی Build داشته باشد.
پیش از شروع، درک کامل مفاهیم زیر که از منابع فنی استخراج شدهاند، ضروری است.
پروژه بر پایه یک مدل کاملاً سرور-محور (Server-Authoritative) عمل میکند تا از تقلب (Cheating) جلوگیری کرده و پایداری وضعیت بازی (Game State) را تضمین نماید.
کنترل سرور: در Mirror، سرور به طور پیشفرض بر تمام آبجکتهای شبکه Authority دارد. تمام منطقهای حساس بازی، مانند کاهش سلامتی، تغییر امتیاز یا اعتبارسنجی حرکات، باید منحصراً روی سرور و از طریق متدهای [Command] اجرا شوند. کلاینتها تنها درخواست انجام یک عمل را به سرور ارسال میکنند.
همگامسازی وضعیت: وضعیت متغیرهای کلیدی از سرور به کلاینتها از طریق [SyncVar] همگامسازی میشود. سرور به صورت خودکار تغییرات SyncVar را به کلاینتهای مربوطه ارسال میکند.
Commands: از کلاینت به سرور ارسال میشوند. برای امنیت، به طور پیشفرض تنها از آبجکت بازیکن خود کلاینت قابل ارسال هستند.
ClientRpc Calls: از سرور به کلاینتها ارسال میشوند و برای اجرای افکتهای بصری یا صوتی روی کلاینتها کاربرد دارند.
تفکیک Authority از مجوزها: در معماریهای پیچیده، میتوان مدل Authority پیشفرض Mirror را نادیده گرفت و یک سیستم مجوزدهی سفارشی (Permission System) پیادهسازی کرد. در این مدل، سرور به جای بررسی Authority، درخواستهای کلاینت را بر اساس یک لیست کنترل دسترسی (ACL) سفارشی اعتبارسنجی میکند.
سیستم Addressables یونیتی، راهحل اصلی برای دستیابی به تفکیک و بهینهسازی داراییها در این پروژه است. این سیستم با حذف ارجاعات مستقیم (Direct References) و جایگزینی آنها با یک آدرس رشتهای، وابستگیها را از بین میبرد.
کاهش چشمگیر حجم Build و مصرف RAM: استفاده از Addressables به ما اجازه میدهد تا داراییهای پلتفرم-محور (مانند SDKهای VR) را از بیلد اصلی خارج کرده و تنها در صورت نیاز بارگذاری کنیم. تجربیات واقعی نشان داده که این روش میتواند حجم نصب یک پروژه VR را از چندین گیگابایت به کمتر از ۲۰۰ مگابایت و مصرف RAM را تا ۸۰٪ کاهش دهد.
الگوی Bootstrap Scene: از آنجایی که تمام صحنههای بازی به Addressable تبدیل میشوند، یک صحنه کوچک و غیر-Addressable به نام "Bootstrap" در بیلد اصلی قرار میگیرد. وظیفه این صحنه صرفاً مقداردهی اولیه سیستم و بارگذاری ناهمگون (Asynchronously) اولین صحنه Addressable متناسب با پلتفرم (VR یا WebGL) است.
حذف پکیجهای غیرضروری (Plugin Pruning): تمامی پکیجهای پیشفرض یونیتی که در پروژه استفاده نمیشوند (مانند AR, AI, Physics-های مختلف) باید غیرفعال شوند.
پوشه Resources: این پوشه باید به طور کامل خالی شود. یونیتی تمام داراییهای موجود در پوشه Resources را بدون توجه به اینکه آیا استفاده شدهاند یا نه، در بیلد نهایی قرار میدهد.
فشردهسازی داراییها: بافتها (Textures)، مدلهای سهبعدی (Meshes) و انیمیشنها باید با استفاده از فرمتهای فشرده و متناسب با پلتفرم هدف، بهینهسازی شوند.
حذف کدهای استفادهنشده (Code Stripping): این قابلیت یونیتی باید فعال باشد تا کدهای مدیریتشده (Managed Code) که در پروژه به آنها ارجاعی وجود ندارد، از بیلد حذف شوند.
تجمیع Shader ها: برای جلوگیری از تکرار Shader ها در بستههای مختلف، باید آنها را در یک AssetBundle مشترک و مرکزی تجمیع کرد تا هم حجم دیسک و هم فشار روی حافظه در زمان اجرا کاهش یابد.
ملاحظات پلتفرم-محور
پایپلاین رندر: برای هر دو پلتفرم WebGL و VR (هدستهای Untethered مانند Meta Quest)، استفاده از Universal Render Pipeline (URP) به عنوان بهترین گزینه (Best Practice) توصیه میشود. URP برای مقیاسپذیری در سختافزارهای مختلف، از جمله موبایل و وب، بهینهسازی شده است.
پشتیبانی از WebGL: زیرساختهای شبکه یونیتی (از جمله Transport مورد استفاده در Mirror) به طور کامل از پلتفرم WebGL پشتیبانی میکنند.
--------------------------------------------------------------------------------
الزامات فنی پروژه
تفکیک ساختار پروژه:
باید از یک پروژه یونیتی واحد برای مدیریت هر دو پلتفرم استفاده شود. تفکیک منطقی بین داراییها و کدها باید از طریق Assembly Definitions و Scripting Define Symbols (مانند UNITY_WEBGL و UNITY_XR) انجام شود.
پیادهسازی کامل سیستم Addressables:
تمامی داراییهای مختص هر پلتفرم باید به Addressable تبدیل شوند. این شامل SDKها، Prefabها، صحنهها، مدلها و بافتهای مخصوص VR یا WebGL میشود.
داراییها باید در گروههای (Groups) مجزا و معنادار سازماندهی شوند. برای مثال، یک گروه برای VR_Player_Assets و گروهی دیگر برای WebGL_UI_Assets.
وابستگیهای بین داراییها باید به دقت توسط سیستم Addressables مدیریت شود تا از تکرار داراییها در بستههای مختلف جلوگیری گردد.
بهینهسازی Build برای WebGL:
تمام پکیجهای مرتبط با VR (مانند XR Plugin Management, OpenXR, Oculus XR) باید به طور کامل از بیلد WebGL حذف شوند.
پروفایل Build سیستم Addressables باید به گونهای تنظیم شود که گروههای مرتبط با VR در بیلد WebGL گنجانده نشوند.
تنظیمات فشردهسازی بافت و مدل باید برای پلتفرم وب بهینهسازی شوند.
بهینهسازی Build برای VR:
پکیجها و اسکریپتهای مختص WebGL باید از بیلد VR حذف شوند.
پروفایل Build سیستم Addressables باید گروههای مختص WebGL را از خروجی نهایی حذف کند.
تنظیمات کیفیت و فشردهسازی باید متناسب با توان پردازشی هدستهای VR هدف تنظیم شوند.
معماری سرور یکپارچه:
یک بیلد سرور اختصاصی (Dedicated Server) باید ایجاد شود که کاملاً پلتفرم-آگنوستیک (Platform-Agnostic) باشد.
سرور باید قادر به پذیرش و مدیریت اتصالات از هر دو کلاینت VR و WebGL به صورت همزمان باشد.
تمام منطق بازی باید روی سرور اجرا شود و کلاینتها تنها به عنوان نمایشدهنده و ورودیگیرنده عمل کنند.
مدیریت حافظه و بارگذاری پویا:
یک اسکریپت Bootstrap Loader باید پیادهسازی شود تا در صحنه اولیه، پلتفرم اجرایی را تشخیص داده و محتوای Addressable مربوطه را بارگذاری کند.
مدیریت دقیق چرخهعمر داراییها (Asset Lifecycle) با استفاده از Release(handle) برای جلوگیری از نشت حافظه، یک الزام قطعی است.
--------------------------------------------------------------------------------
آزمون ارزیابی پیش از شروع
لطفاً به سوالات زیر پاسخ دهید تا اطمینان حاصل شود که تمام مفاهیم کلیدی برای اجرای موفقیتآمیز این وظیفه را درک کردهاید.
چرا استفاده از پوشه Resources برای بهینهسازی حجم Build یک پروژه مشکلساز است؟
سیستم Addressables چگونه به کاهش حجم اولیه (Initial) بیلد کمک میکند؟
الگوی "Bootstrap Scene" را هنگام استفاده از Addressables برای تمام صحنههای بازی شرح دهید.
در یک مدل سرور-محور با استفاده از Mirror، منطق حیاتی بازی (مانند کسر شدن جان بازیکن) باید در کجا اجرا شود و چرا؟
ریسک اصلی عدم فراخوانی متد Addressables.Release(handle) پس از اتمام کار با یک دارایی بارگذاریشده چیست؟
--------------------------------------------------------------------------------
کلید آزمون
زیرا یونیتی تمام داراییهای موجود در پوشه Resources را، صرفنظر از اینکه در بازی استفاده شدهاند یا خیر، به طور کامل در بیلد نهایی قرار میدهد. این امر کنترل بر روی داراییهای بستهبندیشده را از بین میبرد.
با جداسازی داراییها از بیلد اصلی و امکان بارگذاری آنها به صورت按 تقاضا (On-Demand) از حافظه محلی یا یک سرور راه دور. این باعث میشود بیلد اولیه بسیار کوچک و سبک باشد و محتوا تنها در زمان نیاز دانلود و بارگذاری شود.
یک صحنه بسیار کوچک و غیر-Addressable در بیلد اصلی گنجانده میشود. تنها وظیفه این صحنه، مقداردهی اولیه سیستمهای پایه و سپس بارگذاری ناهمگون (Asynchronously) اولین صحنه اصلی بازی است که خود یک دارایی Addressable است.
منطق حیاتی باید منحصراً روی سرور و درون یک متد با اتریبیوت [Command] اجرا شود. این کار برای جلوگیری از تقلب (Cheating) ضروری است، زیرا کلاینتها نمیتوانند به طور مستقیم وضعیت بازی را دستکاری کنند و تنها میتوانند درخواست اجرای یک عمل را به سرور ارسال کنند.
نشت حافظه (Memory Leak). با عدم فراخوانی این متد، شمارنده ارجاع (Reference Count) دارایی به صفر بازنمیگردد و سیستم Addressables تصور میکند که دارایی هنوز در حال استفاده است، بنابراین آن را برای همیشه در حافظه RAM نگه میدارد.
--------------------------------------------------------------------------------
واژهنامه اصطلاحات کلیدی
اصطلاح
تعریف
Addressable Asset
دارایی در یونیتی که به جای ارجاع مستقیم، از طریق یک آدرس رشتهای (String Address) شناسایی و بارگذاری میشود.
Server Authority
یک مدل معماری شبکه که در آن سرور تصمیمگیرنده نهایی در مورد وضعیت تمام آبجکتها و منطق بازی است.
Command (Mirror)
یک فراخوانی تابع از راه دور (RPC) که از کلاینت به سرور ارسال میشود تا یک عمل را روی سرور اجرا کند.
ClientRpc (Mirror)
یک فراخوانی تابع از راه دور (RPC) که از سرور به یک یا چند کلاینت ارسال میشود تا یک عمل را روی کلاینتها اجرا کند.
SyncVar (Mirror)
متغیری در یک NetworkBehaviour که مقدار آن به طور خودکار از سرور به تمام کلاینتها همگامسازی میشود.
Bootstrap Scene
یک صحنه حداقلی و غیر-Addressable که برای راهاندازی اولیه بازی و بارگذاری محتوای Addressable اصلی استفاده میشود.
URP
Universal Render Pipeline؛ یک Scriptable Render Pipeline در یونیتی که برای عملکرد مقیاسپذیر در طیف گستردهای از پلتفرمها طراحی شده است.
Plugin Pruning
عمل غیرفعال کردن یا حذف پلاگینهای استفادهنشده از موتور بازی برای کاهش حجم نهایی بیلد و پیچیدگی پروژه.