تبلیغات

آموزش Collider ها در یونیتی – بررسی برخورد در یونیتی

آموزش Collider ها در یونیتی
بررسی برخورد در یونیتی


در فیزیک، زمانی که بخشی از دو جسم در یک محیط بخواهند وارد مختصات یکسانی شوند، برخورد رخ می‌دهد. برای مثال، جسم A و B رو به روی هم قرار دارند. حالا اگر A به سمت B  و B نیز به سمت A حرکت کند، اگر این حرکت تداوم داشته باشد، زمانی می‌رسد که جسم A و B قصد داشته باشند مختصات یکسانی از جهان را با یکدیگر شریک شوند! و در این حالت برخورد رخ خواهد داد.

برخورد در یونیتی

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

یونیتی برای تشخیص برخورد، کامپوننت‌های Collider (کلایدر) را در اختیار ما قرار می‌دهد! Collider که در لغت به معنای برخورد دهنده ([فیزیک]‌ شتاب‌دهنده‌ای که دو باریکۀ باردار را به‌طور شاخ‌به‌شاخ با هم برخورد می‌دهد) می‌باشد، با اضافه شدن به اشیاء درون بازی، برای آن‌ها قابلیت برخورد را تعریف می‌کند و هرجسمی که این قابلیت را داشته باشد، می‌تواند با اجسام دیگری که Collider دارند برخورد داشته باشد.

در لیست کامپوننت‌های یونیتی، اگر عبارت Collider را جستجو کنید، انواع کلایدرها را مشاهده خواهید کرد و آنهایی که مقابلشان عبارت 2D نوشته شده، در پروژه‌های دو بعدی و برای اسپرایت‌ها استفاده می‌شوند. و همچنین کامپوننت‌های دوبعدی مربوط به فیزیک از جمله کلایدرهای دو بعدی، در سربرگر Physics 2D قرار دارند.

ما در ادامه‌ی این توضیحات، روش ایجاد یک کلایدر را در پروژه‌ه‌ای سه بعدی آموزش داده و سپس روند پیاده‌سازی آن را به صورت خلاصه در حالت دوبعدی خواهیم گفت.

ایجاد یک کلایدر در سه بعدی

یک صحنه‌ جدید ایجاد کرده و از قسمت 3D Object، یک Plane روی صحنه بندازید. سپس دو Cube نیز به آن اضافه کنید.

در اینجا ما نام مکعب سمت چپی را Cube1 و سمت راستی را Cube2 قرار داده‌ایم.

Cube1 را انتخاب کرده و به Add Component بروید. سپس از قسمت Physics، گزینه‌ی Box Collider را انتخاب کنید. کاپوننتی به Cube اضافه خواهد شد که ویژگی‌های آن در Inspector آبجکت به صورت زیر می‌باشد:

در نسخه‌های جدید یونیتی، با اضافه کردن یک Cube به صفحه، خود یونیتی کامپوننت Box Colider را به صورت پیشفرض به آن اضافه می‌کند. همچین برای یک آبجکت امکان اضافه کردن چندین کلایدر وجود دارد که احتمالا علت آن را در حال حاظر ندانید ولی در آینده متوجه خواهید شد.

اگر کیوب را انتخاب کنید، خطوط سبز رنگی را می‌بینید که اطراف آن را گرفته است. ولی اجازه دهید کمی کلیشه‌ای جلو برویم تا چیزی را نشانتان دهم! بنابراین در Box Collider، روی Edit Collider کلیک کنید تا به حالت انتخاب شده و فعال در بیاید. در این لحظه در چهار وجه کیوب، نقاطی را مشاهده خواهید کرد:

این خطوط سبز رنگ در واقع محدوده‌ی برخورد را برای آبجکت کیوب مشخص کرده‌اند که در اینجا یک محدوده‌ی جعبه شکل می‌باشد! Box Collider در واقع به صورت اتوماتیک یک تشخیص دهنده‌ی برخورد جعبه‌ای (یعنی به شکل جعبه)، به آبجکت اضافه می‌کند (مهم نیست چه آبجکتی باشد). و این خطوط یک محدوده را در فضا و به صورتی فرضی مشخص می‌کند تا برخورد را تشخیص دهند و همچنین نقاطی که روی این خطوط قرار دارند، محل‌هایی هستند تا از طریق آن بتوان شکل کلایدر را تغییر داد.

برای درک بهتر آنچه که گفته شد، نشانگر ماوس را روی یکی از نقاط ببرید و با نگه داشتن کلیک چپ، نقطه را به جلو بیاورید:

ما در اینجا کمی از سمت چپ و کمی از سمت جلو جابه‌جایی وجه کلایدر را انجام داده‌ایم. و حالا اگر چیزی بخواهد از این دو سمت به مکعب برخورد کند، از آنجایی که وجه‌های کلایدر روی شکل حقیقی (Mesh) مکعب قرار ندارند، بنابراین برخورد کمی جلوتر از آبجکت تشخیص داده خواهد شد! برای درک این گفته اجازه دهید مثالی بزنم؛ احتمالا در برخی از بازی‌ها دیده‌اید که پای کاراکتر در زمین فرو می‌رود؟! یکی از دلایل این امر می‌تواند این باشد که کلایدر زمین پایین‌تر از سطح ترسیم شده برای آبجکت قرار دارد یا اینکه کلایدر پای کاراکتر بالاتر از کف پای او قرار دارد! بنابراین نتیجه می‌گیریم که کلایدر ربطی به شکل ترسیم شده نداشته و به صورت کاملا مجزا رفتار می‌کند.

حالا اگر به ویژگی‌های کامپوننت برگردیم، خواهیم دید که مقادیری تغییر یافته‌اند:

مقدارهای Center و Size تغییر کرده‌اند! حالا این ویژگی‌ها به چه چیزی اشاره داشتند؟!

  • ویژگی Center، موقعیت کلایدر را نسبت به مرکز آبجکت مشخص می‌کند.
  • ویژگی Size، اندازه‌ی کلایدر را در طول، عرض و ارتفاع مشخص می‌کند.

با تغییر دستی مقادیر این دو ویژگی، می‌توانید کاربرد آنها را بهتر متوجه شوید. البته کلایدرهای دیگر ممکن است مقادیر دیگری نیز داشته باشند! مثلا شعاع!


تا به اینجای کار، مفهوم کلایدر برایمان روشن شد؛ اما هنوز کار خاصی انجام نداده‌ایم. بنابراین اجازه دهید به Cube2 نیز یک باکس کلایدر اضافه کنیم. و بعد از آن، به هردو مکعب یک کامپیوننت Rigidbody اضافه می‌کنیم تا ویژگی‌های فیزیک مثل افتادن از ارتفاع را داشته باشند. و سرانجام در این حالت، با اجرای بازی خواهید دید که مکعب‌ها به سمت Plane سقوط می‌کنند و اگر Plane شما نیز شامل کلابدر باشد، مکعب‌ها روی آن قرار خواهند گرفت، و در غیر اینصورت، از آن رد خواهند شد.

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

حالا فرض کنید می‌خواهیم وقتی مکعب‌ها روی زمین افتادند، کدی اجرا شود و برای مثال رنگ مکعب‌ها به رنگی که مشخص کرده‌ایم تغییر پیدا کند! پس یک اسکریپت ایجاد می‌کنیم و برای مثال نام آن را CubeGroundColor قرار می‌دهیم. اما قبل از اینکه بخواهیم کد را بنویسیم، باید مشخص کنیم که این اسکریپت قرار است به مکعب اضافه شود یا به زمین؟!

البته که این به خود شما و منطق کد شما بستگی دارد و اگر ما میخواهیم از طرف Plane متوجه این شویم، آن را به Plane اضافه می‌کنیم و اگر بخواهیم از طرف مکعب متوجه شویم، آن را به مکعب اضافه می‌کنیم. که در اینجا با توجه به مثالی که زده‌ایم، بهتر است که برای Plane بنویسیم.

اما ما این مثال بالا را انجام نمدهیم و مثال ما به این صورت است که دو مکعب قرار است وقتی به Plane اثابت کردند، یکی از آنها به سمت بالا حل داده شود! و در واقع Plane  قرار است همانند یک تشک رفتار کند. همچنین در مثال ما، Plane  قرار است که فقط روی یکی از مکعب‌ها اثر کند! اما فعلا اجازه دهید قبل از نوشتن کد مربوط به این کار، رویدادهای Collider ها را توضیح دهم:

  • OnCollisionEnter(Collision collision)
    زمانی روی می‌دهد که کلایدر دیگری وارد کلایدر فعلی شود.
  • OnCollisionStay(Collision collision)
    زمانی روی می‌دهد که برخورد هنوز پابرجا باشد. (بنابراین این متد بارها و بارها ممکن است اجرا شود)
  • OnCollisionExit(Collision collision)
    زمانی روی می‌دهد که حالت برخورد به اتمام برسد! یعنی دیگر در محیط هم نباشند و از هم خارج شوند.

در تمامی این رویدادها، ورودی collision را مشاهده می‌کنید!  کلیژن که به معنای برخورد می‌باشد، شامل اطلاعاتی از چیزی که برخورد کرده می‌باشد. از جمله gameobject و …

حالا از رویداد OnCollisionEnter برای ساخت یک تشک پرتاب‌گر ساده به صورت زیر عمل می‌کنیم:

نام آبجکت را با استفاده از collision.gameObject.name بررسی کرده‌ایم تا اگر آن آبجکت اولی بود، پرتاب رخ دهد. و البته می‌توانیم با موارد دیگری از جمله تگ نیز عملیات بررسی را انجام دهیم. در ادامه و داخل شرط نوشته شده، با استفاده از rigidbody آبجکت مورد نظر که از طریق collision.rigidbody می‌توان به آن دسترسی داشت و نیازی به GetComponent از طریق gameObject نیست، نیرویی برابر با 400 در راستای محور Y به جسم وارد کرده‌ایم تا به سمت بالا پرتاب شود. طبیعتا این کد ساده‌ایست و برای ساخت یک تشک نمی‌توان به آن اکتفا کرد؛ چرا که پر از نقصیات می‌باشد؛ ولی این شروع ساخت یک تشک است! 😀

حالا اسکریپت را به Plane داده و کد خود را اجرا کنید. خواهید دید که مکعب اول چند بار بالا و پایین شده و ممکن است براساس تنظیمات rigidbody نیز از صحنه خارج شود.


مسئله‌ای به نام Trigger

تریگر در لغت به معنای ماشه بوده و در معنای فعل نیز به عنوان «راه انداختن، رها کردن، ماشه کشیدن» به کار برده می‌شود! تریگر یکی از ویژگی‌های کلایدرها است که می‌‌توان از Inspector آبجکت به آن دسترسی داشت و آن را برای کلایدر خود فعال و غیرفعال کرد! اما کاربرد آن چیست و به چه دردی می‌خورد؟!

تریگر باعث می‌شود تا کلایدری که به آن برخورد می‌کند، از آن رد شود! و شما در حالت عادی دیدید که مکعب‌ها روی Plane افتادند و از آن رد نشدند، اما اگر مکعب را تریگر تعریف کنیم، از Plane رد خواهد شد و اگر Plane را تریگر در نظر بگیریم، دوباره مکعب‌ها از آن رد خواهند شد! و با این وجود شاید بپرسید که پس تریگر چه فایده‌ای دارد اگر از آن بتوان رد شد؟! همان کلایدر را استفاده نکینم بهتر نیست؟! و جواب این است که در نبود کلایدر چگونه می‌توانیم برخورد را تشخیص دهیم؟! ولی تریگر قابلیتی را به ما می‌دهد تا برخورد را تشخیص دهیم و جسم را به گونه‌ای به روح تبدیل نماییم!

در مثال قبلی، Cube2 را به عنوان تریگر در نظر می‌گیریم! و به کد Cuber ( همان کدی که به Plane ربط داده بودیم) برمی‌گردیم. با این تفاوت که حالا در اینجا سه رویداد دیگر را توضیح می‌دهیم”

  • OnTriggerEnter(Collider collider)
  • OnTriggerStay(Collider collider)
  • OnTriggerExit(Collider collider)

هرسه همانند قبل است با این تفاوت که به جای Collision از Trigger استفاده شده است! اما چون در اینجا برخورد فیزیکی وجود نداشته و کلایدر از جسم رد می‌شود، بنابراین آبجکت کلیژن تولید نشده و به جای آن رویداد تریگر اجرا می‌شود! و همچنین این رویداد اطلاعات برخورد دهنده را در آبجکت کلایدر به ما تحویل می‌دهد.

حالا فرض کنید قصد داریم وقتی مکعب دوم از Plane رد شد، آبجکت Plane شروع به حرکت به سمت بالا کند! همانند یک آسانسور! لذا با توجه به فرض مثال خود، بهتر است کد را داخل OnTriggerExit بنویسیم تا در زمان رد شدن کامل مکعب از Plane اجرا شود.

در داخل رویداد مربوط به خروج تریگر، بررسی کرده‌ایم که اگر مکعب دوم وارد شده بود، ویژگی isEnable اسکریپتِ نوشته شده را برابر true قرار دهد. سپس داخل Update، جابه‌‌جایی را در صورت isEnable بودن انجام داده‌ایم. در واقع مکعب تریگری به عنوان فعال‌کننده‌ی Plane استفاده شده است.

می‌توان داخل یک آبجکت، از کلایدرهایی که بعضی از آن‌ها نیز تریگر هستند استفاده کرد! تریگرها اهمیت ویژه‌ای در ساخت بازی دارند! برای مثال دری ساخته‌اید که باید موقع رفتن کاربر به جلوی آن باز شود یا اینکه یک منطقه در بازی خود دارید که مربوط به دشمن بوده و می‌خواهید در زمان ورود کارکتر به این منطقه، آژیر به صدا دربیاید که می‌توانید در ورودی‌های منطقه، تریگر قرار دهید یا اینکه در خروجی‌های منطقه نیز تریگر جدایی برای بررسی خروج کاراکتر از منطقه قرار دهید. یا یک بازی که در آن برای اعظای مختلف بدن، کلایدرهای مختلفی را تعریف کرده‌ایم و برای مثال در جایی می‌خواهیم دست کاراکتر از یک چیزی رد شود و یا …
کلایدرهایی که تریگر نیستند را اگر درون هم در یونیتی قرار دهید، تازمانی که تحت تاثیر RigidBody نباشند، از هم خارج نخواهند شد چرا که فیزیک و نیرویی وجود ندارد.

ایجاد یک کلایدر در دو بعدی

تنها تفاوت موجود در این‌جا برای حالت دوبعدی، استفاده از کلایدرهایی می‌باشد که آخر آنها 2D نوشته شده است؛ برای مثال Box Collider 2D.

همچنین در انتهای نام تمامی رویدادها، عبارت 2D قرار دارد:

  • OnCollisionEnter2D(Collision2D collision)
  • OnCollisionStay2D(Collision2D collision)
  • OnCollisionExit2D(Collision2D collision)
  • OnTriggerEnter2D(Collider2D collider)
  • OnTriggerStay2D(Collider2D collider)
  • OnTriggerExit2D(Collider2D collider)

و البته فراموش نکنید که RigidBody نیز بایستی 2D باشد.


این مطلب در آینده ویرایش شده و موارد جدیدی نیز به آن اضافه می‌شود.
تبلیغات
8 نظر
کانال تلگرام فول کده
تبلیغات

درباره نویسنده

هادی اکبرزاده

[ مدیر فول کده ]

علاقه‌مند به اشتراک گذاری اطلاعات در هر زمینه‌ای / برنامه‌نویس و دانشجوی ارشد رشته شبیه‌ساز هوشمند - در حال نوشتن یه رمان (اگه خدا بخواد و تموم شه ?)

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

نظرات ثبت شده 8 دیدگاه

    1. parsa گفت:

      سلام خسته نباشید
      ببخشید من تازه اومدم تو دنیای بازی سازی با یونیتی
      داخل یونیتی یک پروژه ایجاد کردم اما بعد از اون دیگه نمیتونم پروژه جدید ایجاد کنم اصلا وقتی رو نیو میزنم هیچ عملکردی نداره
      ممنون میشم راهنمایی کنید
      راستی مرسی از این اموزش خوبتون

      1. هادی اکبرزاده گفت:

        سلام؛ اینترنت رو خاموش و یونیتی رو اجرا کنید شاید حل شه.
        ورژن یونیتیتون چنده؟!

        1. parsa گفت:

          خیلی ممنون درست شد:)

    2. Amin گفت:

      سلام مطالب خیلی عالی بودند 🙂
      اگه بخوایم موقع استفاده از کالیژن stayمکعب رنگ عوض کند(وخب چون در Updateهست رنگا مرتب عوض شن) اون چه کدی داره؟ مثلا هفت رنگ موقعی که مکعب روی سطح هست عوض شن
      بازم ممنون مطالب عالی بودند

      1. هادی اکبرزاده گفت:

        سلام دوست عزیزم. منظورتونو کامل متوجه نشدم!
        شما میخواین زمانی که برخورد در وضعیت Stay قرار داره رنگ جایی رو تغییر بدین؟!

        1. Amin گفت:

          بله رنگ عوض کنه

          1. هادی اکبرزاده گفت:

            کافیه در زمان برخورد متغیری رو true کنید و داخل update بررسی کنید که اگر true بود، رنگشو مجدد تغییر بده و وقتی خارج شد، اون متغیرو false کنید. به همین سادگی.