Своя Tower Defense на Unity 5. Часть 2.

Своя Tower Defense на Unity 5. Часть 2.

Создание Tower Defense на игровом движке Unity 5.

В прошлой части урока мы начали заниматься разработкой своей Tower Defense на Unity5. Подготовили игровую сцену и научили двигаться наших ботов по точкам. В этой части мы добавим в проект башни и заставим их уничтожать противника.

Первым делом необходимо добавить модель самой башни в проект, это может быть любая ваша модель, ну а я добавил вот такую (ее можно скачать здесь).

standardturreticon

После добавления в проект перенесем ее на нашу сцену. Модель башни должна примерно подходить под размеры площадки, созданной на прошлом уроке.

turret

Наша башня состоит из двух частей это башня с пушкой и стойка, на которой башня закреплена, наша задача сделать так, чтобы башня с пушкой вращались отдельно от стойки. Нажимаем на модель и создаем пустой объект, расположен он, должен быть в середине модели в месте соприкосновения стойки с площадкой, немного подымим его по оси Y так, что бы он находился в месте, где башня установлена на стойку. Повернем его по оси Y на -90 градусов так, что бы синяя стрелка была параллельно пушки (для корректного поворота) и делаем объект башни с пушкой дочерним этой пустышки.

turretpust

Теперь можем проверить, поворачивая пустышку (назовем ее turret_pivot) по оси Y. Как видим, башня крутится, а стойка остается на месте.

turretpivot

Сохраняем нашу модель башни в префаб и удаляем со сцены.

В папке scripts создадим скрипт turret и перенесем его на префаб башни. Откроем скрипт и напишем такие строки кода:
public class turret : MonoBehaviour {

private Transform target;
public float range = 15f;
public string enemyTag = "Enemy";
public Transform partToRotate;
public float turnSpeed = 10f;

void Start () {
 InvokeRepeating ("UpdateTarget", 0f, 0.5f);
}
void UpdateTarget(){
 GameObject[] enemies = GameObject.FindGameObjectsWithTag (enemyTag);
 float shortestDistance = Mathf.Infinity;
 GameObject nearestEnemy = null;
 foreach (GameObject enemy in enemies) {
 float distanceToEnemy = Vector3.Distance (transform.position, enemy.transform.position);
 if (distanceToEnemy < shortestDistance) {
 shortestDistance = distanceToEnemy;
 nearestEnemy = enemy;
  }
 }
 if (nearestEnemy != null && shortestDistance <= range) {
 target = nearestEnemy.transform;
  } else {
   target = null;
  }
 }

 void Update () {
 if (target == null)
 return;

 Vector3 dir = target.position - transform.position;
 Quaternion lookRotation = Quaternion.LookRotation(dir);
 Vector3 rotation = Quaternion.Lerp(partToRotate.rotation,lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
 partToRotate.rotation = Quaternion.Euler (0f, rotation.y, 0f);
  }
 void OnDrawGizmosSelected(){
 Gizmos.color = Color.red;
 Gizmos.DrawWireSphere (transform.position, range);
  }
 }

В префабе turret укажем в поле part to rotate нашу пустышку turret_pivot и разместим несколько префабов нашей башни на сцене (копировать ctrl+d, перемещать через ctrl). Сохраним сцену и запустим проект

turettrotate

Как видим наши башни следят за направлением противника.

turettprefabtoscene

Реализация стрельбы.

Добавим на сцену сферу, это будет наш патрон, назовем его bullet и подгоним размеры под ствол пушки.

bullet

Добавим на него материал и сохраним в префаб.

Изменим префаб нашей пушки, к компоненту turret_pivot добавим пустышку (bulletfire) и разместим ее на конце пушки – из этого объекта будут вылетать наши патроны.

bulletfire

Откроем тот же скрипт turret и продолжим…добавим еще несколько функций, которые будут отвечать за стрельбу. Общий скрипт turret будет выглядеть вот так:

using UnityEngine;
using System.Collections;
 
public class turret : MonoBehaviour {

private Transform target;
public float range = 15f; // радиус атаки пушки
public string enemyTag = "Enemy"; // тэг для атаки
public Transform partToRotate; //объект поворота
public float turnSpeed = 10f; // скорость поворота башни
public float fireRate= 1f;
private float fireCountdown = 0f;
public GameObject bulletprefab; // объект пули
public Transform firePoint; // объект из которого будет вылетать пуля


 void Start () {
  InvokeRepeating ("UpdateTarget", 0f, 0.5f);
 }
 void UpdateTarget(){
 GameObject[] enemies = GameObject.FindGameObjectsWithTag (enemyTag); // определяем тэг для нашего противника
 float shortestDistance = Mathf.Infinity;
 GameObject nearestEnemy = null;
 foreach (GameObject enemy in enemies) {
 float distanceToEnemy = Vector3.Distance (transform.position, enemy.transform.position);
 if (distanceToEnemy < shortestDistance) {
 shortestDistance = distanceToEnemy;
 nearestEnemy = enemy;
 }
}
 if (nearestEnemy != null && shortestDistance <= range) {
 target = nearestEnemy.transform;
 } else {
 target = null;
  }
 }

void Update () {
 if (target == null)
 return;
// делаем повороты башни в соответствии с позицией противника
 Vector3 dir = target.position - transform.position;
 Quaternion lookRotation = Quaternion.LookRotation(dir);
 Vector3 rotation = Quaternion.Lerp(partToRotate.rotation,lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
 partToRotate.rotation = Quaternion.Euler (0f, rotation.y, 0f);

 if (fireCountdown <= 0f) { // функция стрельбы по истечению времени
  Shoot ();
  fireCountdown = 1f / fireRate;
  }
  fireCountdown -= Time.deltaTime;
 }

 void Shoot(){ // создаем компонент Bullet в точке стрельбы
 GameObject bulletGo = (GameObject)Instantiate (bulletprefab, firePoint.position, firePoint.rotation);
 Bullet bullet = bulletGo.GetComponent<Bullet> ();

 if (bullet != null)
 bullet.Seek (target);
 }
void OnDrawGizmosSelected(){
 Gizmos.color = Color.red;
 Gizmos.DrawWireSphere (transform.position, range);
 }
}

Создадим еще один скрипт Bullet и поместим его на наш патрон, откроем его и напишем код:

using UnityEngine;
using System.Collections;

 public class Bullet : MonoBehaviour {
 private Transform target;
 public float speed = 70f; // скорость полета пули
 public GameObject bulletEffect; // эффект разрушения

 public void Seek (Transform _target) {
 target = _target;
 }

 void Update () {
  if (target == null) {
  Destroy (gameObject);
  return;
 }
 Vector3 dir = target.position - transform.position; // направляем нашу пулю в сторону противника
 float distanceThisFrame = speed * Time.deltaTime;
 if (dir.magnitude <= distanceThisFrame) {
 HitTarget ();
 return;
 }
 transform.Translate (dir.normalized * distanceThisFrame, Space.World);
 }
 void HitTarget (){ // добавляем эффект разрушения в место столкновения и удаляем все три объекта со сцены
 GameObject effectIns= (GameObject) Instantiate(bulletEffect, transform.position, transform. rotation);
 Destroy(effectIns, 2f);
 Destroy(target.gameObject);
 Destroy(gameObject);
  }
 }

Добавим на сцену систему частиц, это будит эффект при попадании  нашего патрона в противника. Настроим его примерно вот так:

bulleteffect1

bulleteffect2

Для это системы частиц создайте новый материал и примените его в Render — material, так же переименуйте его в bulleteffect и сохраните в префаб. Укажите этот префаб в скрипте bullet на префабе bullet.

Для нашего противника создадим новый тэг «Enemy» и присвоим этот тэг ему.

enemytag

На префабе башни в bulletprefab перенесем префаб патрона и в fire point перенесем компонент bulletfire (объект из которого будет выходить наш патрон).

turretscript

Не забывайте сохранять сцену. Проверим что мы тут наработали, запустим игровую сцену.

game

Видим что при попадании нашего патрона в противника предмет исчезает и появляется наша системы частиц (эффект разрушения), так же башни естественно двигаются за нашими противниками. Урок получился немного сложноватым и могут показаться некоторые моменты не понятными, мы рады будем ответить на ваши вопросы, оставляйте их в комментариях.

На этом вторая часть урока окончена. Желаем удачных проектов!

            На главную

Обсудить на форуме


Оставить Комментарий