آشنایی با UI System یونیتی

image

رابط کاربری (به انگلیسی User Interface) که به اختصار UI نامیده می‌شود از بنیادی‌ترین بخش‌های یک نرم‌افزار بوده که وظیفه‌ی تعامل بین کاربر و نرم‌افزار را از طریق اجزایش فراهم می‌کند. این اجزا می‌توانند شامل دکمه‌ها، نوارهای آبشاری، لغزنده‌ها و یا حتی متن ساده باشند که پل ارتباطی کاربر نهایی با محیط درون نرم‌افزار می‌باشند.

مثل هر نرم‌افزار دیگری بازی‌هایی که ساخته می‌شوند نیز نیاز به رابط کاربری دارند؛ از دکمه‌هایی برای pause و reset کردن مراحل بازی گرفته تا لغزنده‌هایی برای کنترل صدای بازی و میزان روشنایی تصویر.

توسعه‌ی رابط کاربری مستقل از جریان اصلی توسعه و الگوریتم‌های آن صورت می‌پذیرد و ارتباطی با کدهای نوشته شده و کارکرد اصلی صحنه ندارد. به همین علت معمولاً طراحی رابط کاربری برای یک صحنه پس از اتمام گیم دیزاین آن صحنه و در آخرین مرحله صورت می‌پذیرد. این عمل حتی می‌تواند توسط فرد دیگری به جز طراح بازی صورت بگیرد که به این فرد UI designer گفته می‌شود. بدیهی است که به دلیل استقلال رابط کاربری از مرحله‌ی طراحی شده مشکلی در این باره پیش نخواهد آمد.

طراح رابط کاربری نیازی ندارد که طرز کار اجزای درون صحنه را بداند.

تا قبل از نسخه‌ی 5 یونیتی، برای طراحی رابط کاربری در بازی‌های یونیتی از گیم‌آبجکت‌های GUI موجود در یونیتی و یا assetهای موجود در asset store استفاده می‌شد که همگی عملکرد ضعیفی داشتند؛ تا این که در این ورژن یکی از مهم‌ترین قابلیت‌های یونیتی به ادیتور اضافه شد: UI system یونیتی.

UI system یونیتی چیست؟

UI system ابزاری است که امکان ایجاد پیچیده و پرجزئیات‌ترین رابط‌های کاربری را برای بازی‌هایی که با یونیتی ساخته شده‌اند فراهم می‌کند. این ابزار در عین قدرت زیادی که در ایجاد رابط‌های کاربری دارد، به آسانی قابل استفاده است و در صورت یادگیری صحیح نحوه‌ی استفاده از آن (علیرغم نظر عده‌ای) به هیچ عنوان گیج‌کننده نیست.

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

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

شروع کار با UI system یونیتی

همانطور که گفته شد، رابط کاربری در واقع مجموعه‌ای از اجزایی است که با کاربر تعامل دارند. هر کدام از این اجزا در UI system یونیتی در قالب نوع خاصی از گیم آبجکت (به نام UI Game Object) تعریف شده‌اند که همگی در منوی Create پنجره‌ی Hierarchy و در قسمت UI قرار دارند:

image

برای شروع کار با UI system منوی Create را گشوده و از قسمت UI یک گزینه‌ی دلخواه (مثلاً Text) را انتخاب کنید.

با ایجاد اولین UI Game Object در صحنه، دو گیم آبجکت به صورت اتوماتیک به Hierarchy اضافه می‌شوند:

  • Canvas

  • Event System

همچنین UI Game Object ایجاد شده زیرمجموعه‌ی گیم آبجکت Canvas قرار می‌گیرد.

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

گیم آبجکت Canvas

یک UI Game Object به تنهایی قابلیت رندر شدن نداشته و برای این کار به یک گیم آبجکت Canvas احتیاج دارد. Canvas که در لغت به معنای بوم نقاشی است یک محدوده‌ی فرضی مستطیلی بوده که UI Game Objectهای زیرمجموعه‌ی گیم آبجکتِ Canvas بسته به اندازه و نسبت طول به عرض Canvas در قسمت‌های مناسب آن محدوده رندر می‌شوند. این محدوده در ساده‌ترین حالت خود می‌تواند مستطیل صفحه نمایش کاربر باشد و یا در حالات پیچیده‌تر محدوده‌ای که یک دوربین خاص در دید خود دارد و یا حتی صفحه‌ای که توسط طراح بازی ایجاد شده و در جهان بازی قرار دارد.

تنها پس از مشخص شدن این محدوده است که امکان محاسبه‌ی اندازه و مکان UI Game Objectها وجود خواهد داشت.

برای مثال فرض کنید در یک صحنه محدوده‌ی Canvas بر روی صفحه نمایش کاربر تنظیم شده است. این بازی اگر بر روی یک گوشی با صفحه نمایش کوچک اجرا شود اندازه‌ی Canvas برابر با رزولوشن گوشی در نظر گرفته شده و محاسبه‌ی اندازه و مکان UI Game Objectها برای آن صفحه انجام می‌شود. حال اگر همان بازی بر روی یک تبلت بزرگ اجرا شود این بار Canvas برابر با رزولوشن تبلت در نظر گرفته شده و در محاسبات مکان و اندازه‌ی UI Game Objectها نتیجه‌ی متفاوتی را نسبت به گوشی موبایل شاهد خواهیم بود:

image

اجزای رابط کاربری بسته به اندازه و نسبت تصویر صفحه نمایش کاربر اندازه و مکان خود را تطبیق می‌دهند؛ این عمل تا پیش از اضافه شدن قابلیت UI system به یونیتی بسیار دشوار و نیازمند کدنویسی نسبتا سنگینی بوده است.

پس گیم آبجکت Canvas وظیفه‌ی رندر UI Game Objectهای زیرمجموعه‌ی خود را (مستقل از گیم آبجکت‌های عادی) بر عهده دارد. در واقع علت انعطاف و تطبیق‌پذیری اجزای رابط کاربری وجود این گیم آبجکت است.

گیم آبجکت Canvas تعیین می‌کند که UI Game Objectهای زیرمجموعه‌اش در چه مکان و با چه اندازه‌ای رندر شوند.

در واقع Canvas (همانطور که از اسمش پیداست) یک بوم نقاشی است که «پس از مشخص شدن محدوده‌اش» اقدام به محاسبه‌ی مکان و اندازه‌ی مناسب برای UI Game Objectهای زیرمجموعه‌اش و چینش (رندر) آن‌ها در چارچوب و محدوده‌ی خود می‌کند (به همین دلیل است که اگر UI Game Object زیرمجموعه‌ی یک Canvas نباشد رندر نخواهد شد).

این گیم آبجکت از سه کامپوننت تشکیل شده است (به جز کامپوننت Rect Transform که معادل کامپوننت Transform در گیم آبجکت‌های UI است و جداگانه بررسی خواهد شد). کامپوننت‌های فوق عبارتند از:

کامپوننت Canvas

این کامپوننت محدوده‌ی Canvas را تعیین می‌کند. محدوده‌ی Canvas مکان رندر UI Game Objectهای زیرمجموعه را تعیین می‌کند.

کامپوننت Canvas دارای یک پراپرتی به نام Render Mode بوده که بسته به گزینه‌ی انتخاب شده در این قسمت سایر پراپرتی‌های کامپوننت تغییر می‌کنند.

  • حالت اول => Render Mode: Screen Space – Overlay

    image

    در این حالت محدوده‌ی Canvas (کاملاً مستقل از جهان بازی) بر روی صفحه‌ی نمایش بازیکن منطبق می‌شود.

  • حالت دوم => Render Mode: Screen Space – Camera

    image

    در این حالت محدوده‌ی Canvas بر روی محدوه‌ای که یک دوربین رندر می‌کند منطبق می‌شود. این دوربین از طریق پراپرتی Render Camera به کامپوننت معرفی می‌شود.

نکته

اگر در صحنه تنها از Main Camera استفاده می‌کنید این حالت چندان تفاوتی با حالت اول نخواهد داشت؛ البته در این حالت پراپرتی Plane Distance فاصله‌ی صفحه‌ی فرضی که Canvas بر روی آن رندر شده است را با دوربین تعیین می‌کند.

  • حالت سوم => Render Mode: World Space

    image

    در این حالت برخلاف دو حالت قبل صفحه‌ی فرضی رندر Canvas منطبق بر صفحه نمایش نبوده و می‌تواند در جهان بازی رندر شود.

کامپوننت Canvas Scaler

image

این کامپوننت اندازه‌ی UI Game Objectهای زیرمجموعه‌ی Canvas را تعیین می‌کند. کامپوننت فوق دارای سه حالت است که از طریق پراپرتی UI Scale Mode قابلیت انتخاب دارند.

  • حالت اول => UI Scale Mode: Constant Pixel Size

    در این حالت اجزای Canvas بدون توجه به اندازه‌ی صفحه نمایش کاربر با اندازه‌ی ثابتی (در واحد پیکسل) رندر می‌شوند. استفاده از این حالت توصیه نمی‌شود.

  • حالت دوم => UI Scale Mode: Scale With Screen Size

    در این حالت اندازه‌ی UI Game Objectها متناسب با اندازه‌ی صفحه نمایش کاربر تغییر اندازه می‌دهند.

نکته

در صورتی که قصد دارید UI Game Objectها بر مختصات جهان بازی منطبق باشند و مانند سایر گیم آبجکت‌ها رفتار کنند ابتدا UI Scale Mode را در این حالت قرار داده و سپس پراپرتی Screen Match Mode را بر روی Match Width Or Height تنظیم کرده و در نهایت مقدار پراپرتی Match را برابر 1 قرار دهید (نقاط لنگری UI گیم آبجکت‌های مذکور در کامپوننت Rect Transform باید در مرکز Canvas باشند).

  • حالت سوم => UI Scale Mode: Constant Physical Size

    این حالت مشابه حالت اول است؛ با این تفاوت که در آن تراکم پیکسلی در نظر گرفته نمی‌شوند و می‌توان از واحدهایی مانند میلی‌متر، سانتی‌متر و… استفاده نمود.

کامپوننت Graphic Raycaster

این کامپوننت وظیفه‌ی تشخیص برخورد raycast با canvas را بر عهده دارد.

گیم آبجکت EventSystem

گیم آبجکت EventSystem وظیفه‌ی مدیریت ورودی‌هایی که در حین بازی توسط کاربر به رابط کاربری منتقل می‌شود را بر عهده دارد. معمولاً احتیاجی به دستکاری کامپوننت‌های این گیم آبجکت نداریم؛ اما توجه داشته باشید که حذف شدن این گیم آبجکت موجب از بین رفتن امکان تعامل با رابط کاربری از طریق ورودی‌هایی مانند تاچ، کلیک، کیبورد و… می‌شود.

فلسفه‌ی کامپوننت Rect Transform

image

اگر به گیم آبجکت Canvas و سایر UI Game Objectهای زیرمجموعه‌ی آن دقت کنید، متوجه خواهید شد که این گیم آبجکت‌ها برخلاف گیم آبجکت‌های معمولی یونیتی، به جای کامپوننت Transform دارای کامپوننتی به نام Rect Transform می‌باشند. دلیل آن هم این است که این گیم‌آبجکت‌ها در مختصات جهان بازی قرار نمی‌گیرند و مکان رندر آن‌ها پویا است و توسط Canvas والدشان محاسبه می‌شود.

این کامپوننت تنها در صورتی فعال و تاثیرگذار است که گیم آبجکت آن زیرمجموعه‌ی یک Canvas باشد. چرا که Canvas وظیفه‌ی محاسبه‌ی اندازه و مکان پویای UI Game Objectها را بر عهده دارد.

نکته

راه سریع تشخیص یک UI Game Object از گیم آبجکت معمولی چک کردن کامپوننت‌های آن است؛ در صورتی که گیم آبجکت دارای کامپوننت Transform بود یک گیم آبجکت معمولی و در صورتی که دارای کامپوننت Rect Transform بود یک UI Game Object است.

نکته

به منظور تبدیل یک گیم آبجکت معمولی به UI Game Object کافی است به آن کامپوننت Rect Transform را به صورت دستی اضافه کرده (که جایگزین کامپوننت Transform می‌شود) و سپس در پنل Hierarchy آن را زیرمجموعه‌ی Canvas مدنظر کنیم. برای تبدیل یک UI Game Object به گیم آبجکت معمولی نیز کافی است کامپوننت Rect Transform آن را حذف کرده تا کامپوننت Transform ظاهر شود.