آموزش 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 آبجکت به صورت زیر میباشد:
اگر کیوب را انتخاب کنید، خطوط سبز رنگی را میبینید که اطراف آن را گرفته است. ولی اجازه دهید کمی کلیشهای جلو برویم تا چیزی را نشانتان دهم! بنابراین در 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 برای ساخت یک تشک پرتابگر ساده به صورت زیر عمل میکنیم:
void OnCollisionEnter(Collision collision) { if (collision.gameObject.name == "Cube1") { collision.rigidbody.AddForce(0, 400, 0); } }
نام آبجکت را با استفاده از 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 اجرا شود.
private bool isEnable = false; void Update () { if (isEnable) transform.Translate(0, 5 * Time.deltaTime, 0); } void OnTriggerExit(Collider collider) { if (collider.gameObject.name == "Cube2") { isEnable = true; } }
در داخل رویداد مربوط به خروج تریگر، بررسی کردهایم که اگر مکعب دوم وارد شده بود، ویژگی isEnable اسکریپتِ نوشته شده را برابر true قرار دهد. سپس داخل Update، جابهجایی را در صورت isEnable بودن انجام دادهایم. در واقع مکعب تریگری به عنوان فعالکنندهی Plane استفاده شده است.
ایجاد یک کلایدر در دو بعدی
تنها تفاوت موجود در اینجا برای حالت دوبعدی، استفاده از کلایدرهایی میباشد که آخر آنها 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 باشد.
سلام خسته نباشید
ببخشید من تازه اومدم تو دنیای بازی سازی با یونیتی
داخل یونیتی یک پروژه ایجاد کردم اما بعد از اون دیگه نمیتونم پروژه جدید ایجاد کنم اصلا وقتی رو نیو میزنم هیچ عملکردی نداره
ممنون میشم راهنمایی کنید
راستی مرسی از این اموزش خوبتون
سلام؛ اینترنت رو خاموش و یونیتی رو اجرا کنید شاید حل شه.
ورژن یونیتیتون چنده؟!
5.5
خیلی ممنون درست شد:)
سلام مطالب خیلی عالی بودند 🙂
اگه بخوایم موقع استفاده از کالیژن stayمکعب رنگ عوض کند(وخب چون در Updateهست رنگا مرتب عوض شن) اون چه کدی داره؟ مثلا هفت رنگ موقعی که مکعب روی سطح هست عوض شن
بازم ممنون مطالب عالی بودند
سلام دوست عزیزم. منظورتونو کامل متوجه نشدم!
شما میخواین زمانی که برخورد در وضعیت Stay قرار داره رنگ جایی رو تغییر بدین؟!
بله رنگ عوض کنه
کافیه در زمان برخورد متغیری رو true کنید و داخل update بررسی کنید که اگر true بود، رنگشو مجدد تغییر بده و وقتی خارج شد، اون متغیرو false کنید. به همین سادگی.
سلام من بهکاراکترمکاراکترکنترولر دادمهمه ی اکشن هاشو هم دادم تیز تریگل هم فعال نیست به پلن(زمین)همکلایدر دادم ولی وقتی بازی پلی میشه کاراکتر از توش ردد میشه کلا هر چیزی ازش ردد مبشه حتی یه کیوب ساده لطفا کمکم کنید
سلام. احتمالا Rigidbody اضافه نکردید.
سلام من در یونیتی وقتی زمین تموم می شه پلیر از لبه زمین به پایین سقوط می کنه وقتی که سقوط می کنه می خواستم بدونم چطوری می شه پلیر رو به زمین برگرداند.
سلام. یه اسکریپت بنویسید و ارتفاع رو بررسی کنید اگه از اون کمتر بود انتقالش بدید
سلام ببخشید من چه کُدی براش بنویسم؟
الآن که متاسفانه نمیتونم توی نظرات روش انتقال آبجکت و بررسی ارتفاع رو توضیح بدم؛ فقط راه حلشو گفتم خدمتتون. باید مطلب جدایی براش منتشر بشه.
داخل اسکریپت، مختصات Y رو توی آپدیت بررسی کنید اگه از یه حدی کمتر بود، آبجکت بازیکن رو انتقال بدید به مختصات دلخواه
توی اینترنت از این بهتر آموزش نبود.
خدا خیر نویسنده رو بده
خواهش میکنم نظر لطفتونه
دیگه الکی که دهکده رویایی نیستیم 😀
عالی بود دستتون درد نکنه
خواهش میکنم