no-img
سامنتا

آموزش ساخت بازی دو بعدی (جلسه ی چهارم)


سامنتا
دانلودهای ویژه
اطلاعیه های سایت

ادامه مطلب

آموزش ساخت بازی دو بعدی (جلسه ی چهارم)
zip
آبان ۱, ۱۳۹۵

آموزش ساخت بازی دو بعدی (جلسه ی چهارم)


برای دیدن جزئیات تمام جلسه های این دوره اینجا کلیک کنید .

پیاده سازی شلیک (قسمت دوم)

اگر آموزش های قبلی این سری را مطالعه کرده باشید شما باید هم اکنون یک کشتی شناور در آسمان بعنوان کاراکتر اصلی بازی که قابلیت شلیک و حرکت دارد داشته باشید.

در آموزش قبلی ما رفتار کاراکتر اصلی را تغییر دادیم و باعث شدیم که به سمت دشمن شلیک بکند 

در این آموزش قصد داریم رفتارهای کاراکتر اصلی را گسترش دهیم و آنرا بهبود بخشیم 

پیاده سازی گلوله ی شلیک از طرف دشمن به سوی کاراکتر اصلی 

حالا توسط تصویر زیر باید یه sprite جدید درست کنیم 

shot_poulpiاگر میخواهید در زمان شما صرفه جویی شود از prefab که قبلا ساختیم و نامش PlayerShot هست یک کپی بسازید و نام آنرا به EnemyShot1 تغییر دهید و در نهایت اسپرایت آنرا به تصویر بالا تغییر دهید .

برای ساختن یک کپی از prefab آنرا به درون صحنه بکشید و نام شی که ساخته شده را تغییر دهید و در نهایت آن شی را بعنوان یک prefab جدید بسازید . (به پوشه ی prefab درگ کنید تا prefab جدیدی از شی جدید ساخته شود) یا میتوانید یک کپی از prefab بسازید و به سادگی نام و مشخصات آنرا تغییر دهید (برای درک بهتر این قسمت حتما آموزش ویدیوئی را دریافت و مشاهده کنید)

مقدار scale باید (0.35, 0.35, 1) باشد . و در نهایت کار شما باید مشابه تصویر زیر باشد 

shot_config2

 

اگر شما دکمه ی play یونیتی را کلیک کنید گلوله به سمت دشمن رفته و آنرا نابود خواهد کرد . این بخاطر اسکریپتی هست که از قبل روی این گلوله وجود دارد اسکریپت ShotScript که قبلا برای گلوله ی قبلی ساخته بودیم و چون prefab یک کپی هست تمام خصوصیات را هم با خود به ارث برده است 

نیازی به تغییر آن نیست . اگر اسکریپت WeaponScript را از درس های قبلی در خاطر داشته باشید مقادیر آن را نیز به درستی تنظیم خواهیم کرد 

ما یک  prefab به نام EnemyShot1 داریم . نسخه ی روی صحنه ی آنرا پاک کنید 

شلیک 

همانطور که برای player انجام دادیم ، ما باید یک اسلحه برای کاراکتر دشمن درست کنیم و متد Attack() را برایش فراخوانی کنیم 

اسکریپت جدید و دستورالعمل ها :

  • WeaponScript را به دشمن اضافه کنید
  • EnemyShot1 را درگ کنید و به مقدار Shot Prefab اختصاص دهید (اگر متوجه نشدید حتما ویدئو آموزشی را ببینید)
  • اسکریپت جدید بسازید و نام آنرا EnemyScript قرار دهید . در این اسکریپت قرار هست یک کد اتوماتیک جهت شلیک خودکار کاراکتر دشمن بنویسیم 
using UnityEngine;
/// <summary>
/// Enemy generic behavior
/// </summary>
public class EnemyScript : MonoBehaviour
{ private WeaponScript weapon; void Awake() { // Retrieve the weapon only once weapon = GetComponent<WeaponScript>(); } void Update() { // Auto-fire if (weapon != null && weapon.CanAttack) { weapon.Attack(true); } }
}

این اسکریپت را به کاراکتر دشمن اختصاص دهید . 

شما باید inspector کاراکتر دشمن را به این شکل داشته باشید 

enemy_configفقط مقدار shooting rate را به ۰٫۷۵ تغییر بدهید 

توجه کنید  : اگر روی صحنه با prefab ها کار میکنید و هر تغییراتی که روی آنها میدهد حتما در آخر کار دکمه ی Apply را از بالای inspector بزنید در غیر این صورت تغییرات فقط روی شی روی صحنه اعمال میشود و در صورت ساخته شدن شی جدید از prefab  تغییرات شما روی آن اعمال نخواهد شد .

حالا دکمه ی play را بزنید و نتیجه را مشاهده کنید : 

shoot_right

بسیار خب ، به نظر میرسه یه مشکلی هست و دشمن به سمت راست شلیک میکنه در حالی که کاراکتر player در سمت چپ اون هست . 

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

%da%a9%d8%a7%d8%b1%d8%a7%da%a9%d8%aa%d8%b1-%d8%af%d8%b4%d9%85%d9%86-%d8%af%d8%b1-%d8%a8%d8%a7%d8%b2%db%8c-%d8%b3%d8%a7%d8%b2%db%8c-%d8%af%d9%88-%d8%a8%d8%b9%d8%af%db%8c-%db%8c%d9%88%d9%86%db%8c%d8%aaهمونطور که در تصویر بالا هم مشاهده میکنید کار جالب نیست پس موضوع زیر رو ادامه بدید تا این مشکل رو کاملا حل کنیم (حتما از آموزش ویدیوئی فارسی این قسمت دیدن کنید)

شلیک در همه ی جهت ها 

اسکریپت WeaponScript به شیوه ی خاصی ساخته شده است ، شما میتوانید سمت شلیک گلوله را با چرخاندن کاراکتر اصلی تغییر دهید همانطوری که مشاهده کردیم 

تکنیک که استفاده خواهیم کرد به این صورت است ، یک game object خالی درست کنید و به عنوان فرزندی کاراکتر دشمن قرار دهید . حتما apply را بزنید تا به prefab اعمال شود . 

کارهایی که نیاز هست انجام دهید : 

  1. یک game object خالی درست کنید و نام آنرا به Weapon تغییر دهید 
  2. اسکریپت WeaponScript را که به کاراکتر دشمن اضافه شده است را پاک کنید 
  3. اسکریپت WeaponScript را به شی که جدید ساختیم به نام Weapon اضافه کنید و prefab شلیک را تنظیم کنید همانطور که قبلا انجام دادیم (اگر درک این قسمت ها مشکل هست پیشنهاد میکنیم آموزش ویدیوئی این قسمت را دریافت و استفاده کنید تا همه چیز را بصورت کامل درک کنید)
  4. شی Weapon را بچرخانید تا مقدار چرخش  (0,0,180) داشته باشد .

اگر تمام عملیات شما انجام شد وتمام شد حتما گزینه ی apply را از بالای inspector برای تک تک اشیا بزنید تا عملیات روی prefab های شما اعمال شود . 

در نهایت یونیتی شما باید به این شکل باشد : 

%d8%a2%d9%85%d9%88%d8%b2%d8%b4-%d8%a8%d8%a7%d8%b2%db%8c-%d8%b3%d8%a7%d8%b2%db%8c-%d8%af%d9%88-%d8%a8%d8%b9%d8%af%db%8c-%d8%af%d8%b1-%db%8c%d9%88%d9%86%db%8c%d8%aa%db%8c-%d9%85%d8%ad%db%8c%d8%b7

ما تغییرات کمی را برای EnemyScript داشتیم 

در حالت فعلی EnemyScript در فراخونی  GetComponent<WeaponScript>() مقدار null را برمیگرداند ، در واقع از این به بعد WeaponScript به یک شی واحد اختصاص داده نشده است . 

خوشبختانه یونیتی امکانی را فراهم کرده است که ما میتوانیم به کامپوننت ها و مقادیر اشیای زیرین یا اشیای فرزند هم دسترسی داشته باشیم و این کار توسط متدی به نام GetComponentInChildren<Type>() انجام خواهد شد 

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

نگاهی به اسکریپت EnemyScript بیاندازید : 

using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// Enemy generic behavior
/// </summary>
public class EnemyScript : MonoBehaviour
{ private WeaponScript[] weapons; void Awake() { // Retrieve the weapon only once weapons = GetComponentsInChildren<WeaponScript>(); } void Update() { foreach (WeaponScript weapon in weapons) { // Auto-fire if (weapon != null && weapon.CanAttack) { weapon.Attack(true); } } }
}

 

در نهایت ، shoot speed کاراکتر enemyShot1 که یک prefab هست را تغییر دهید توججه کنید که این پارامتر درون اسکریپت MoveScript میباشد . این کار باعث خواهد شد که کاراکتر دشمن با سرعت بالاتری حرکت بکند .

آموزش بازی سازی دو بعدی در یونیتی - افزایش سرعت کاراکتر دشمن

بسیار عالی ، ما یک دشمن خطرناک ساختیم 🙂

جایزه : شلیک کردن در دو سمت مختلف 

ایجاد شلیک در دو سوی مختلف با انجام چند کلیک و یک کپی سازی درون inspector انجام میگیرد . شامل هیچ اسکریپتی نمیشود : 

  1. یک weapon  دیگر به دشمن اضافه کنید (با duplicate کردن weapon اولی (کپی کردن))
  2. rotation دومی که کپی کرده اید را (منظور همان Weapon) تغییر دهید 

کاراکتر دشمن هم اکنون باید در دو سوی مختلف شلیک بکند 

آموزش بازی سازی دو بعدی در یونیتی شلیک در دو سوی مختلف توسط دشمن

این مثال خیلی خوبی هست برای استفاده ی درست از یونیتی : ساخت یک اسکریپت عمومی با ساخت پارامترهای ورودی از نوع Public ، شما میتوانید در زمان و زحمت خود صرفه جویی کنید و کدنویسی کمتری داشته باشید . همیشه هم به یاد داشته باشید کدنویسی کمتر = خطای کمتر .

صدمه زدن به player

تا کنون ، گلوله هایی که دشمن شلیک میکند صدمه زننده هستند ولی خود کاراکتر دشمن هیچ صدمه ای به player وارد نمیکند 

یک اسکریپت HealthScript به player اضافه کنید و مطمئن شوید که تیک is enemy را برداشته اید مثل زیر :

آموزش بازی سازی دو بعدی در یونیتی اسکریپت سلامت بازیکن 

بازی را اجرا کنید و نتیجه را مشاهده کنید : 

آموزش بازی سازی دو بعدی در یونیتی - صدمه و کشتن کاراکتر بازی  

جایزه

ما قصد داریم نکات بیشتری را در رابطه با شلیک به شما یاد بدهیم ، البته این قسمت ها اختیاری هستند و میتوانید آنها را نخوانید . 

برخورد  کاراکتر player و کاراکتر دشمن 

بیایید کمی روی برخورد کاراکتر دشمن با کاراکتر پلایر کار کنیم 

Collision زمانی اتفاق میوفتد که دو شی( این اشیا حتما باید Collider 2D از نوع غیر Trigger باشند که قبلا توضیح دادیم  ) با هم برخورد یا هم دیگر را لمس بکنند.

به سادگی ما نیاز داریم متد OnCollisionEnter2D  را درون PlayerScript کنترل کنیم :

//PlayerScript.cs
//....
void OnCollisionEnter2D(Collision2D collision) { bool damagePlayer = false; // Collision with enemy EnemyScript enemy = collision.gameObject.GetComponent<EnemyScript>(); if (enemy != null) { // Kill the enemy HealthScript enemyHealth = enemy.GetComponent<HealthScript>(); if (enemyHealth != null) enemyHealth.Damage(enemyHealth.hp); damagePlayer = true; } // Damage the player if (damagePlayer) { HealthScript playerHealth = this.GetComponent<HealthScript>(); if (playerHealth != null) playerHealth.Damage(1); } }

زمان برخورد (on Collision) ، ما هم به کاراکتر پلایر و هم به کاراکتر دشمن صدمه وارد میکنیم این کار هم توسط اسکریپت HealthScript باید انجام بگیرد . در حقیقت تمام کارهای سلامتی و صدمه باید توسط این اسکریپت انجام گیرد 

خسته نباشید

در این درس نحوه ی ساختن دشمن کامل به همراه شلیک ، بهبود اسکریپت نویسی عمومی جهت استفاده های مجدد ، همچنین shooter را کامل کردیم 

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

با تشکر 

عباس نیکزاد 



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

ما سایت سامنتا را با هدف انتقال دانش و تجربیات خود از بهترین متدهای آموزشی دنیا راه اندازی کردیم . محتویات این سایت از ابتدا براساس سلیقه ، نظرات و پیشنهادهای کاربران ساخته شده است . به امید روزی که سیستم آموزشی ایران متحول و از شیوه های نوین آموزشی استفاده کنند

تیم آموزشی سامنتا 70 نوشته در سامنتا دارد . مشاهده تمام نوشته های

دیدگاه ها


پاسخ دهید

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