Как сделать 2D стрельбу в Unity 5 с пулом объектов

В сегодняшнем уроке мы разберем как сделать стрельбу в Unity 2D с использованием пула объектов (Object pool) для реализации этого менее затратно. Для начала имеем: проект с объектом, который будет стрелять, картинку пули. Картинку пули мы вынесем в игру, добавим на неё BoxCollider2D и поставим галочку около Is Trigger для того, чтоб он задевал все объекты, но не останавливался, а так же сохраним её как префаб в папку Resources\Prefub. Для этого нужно из Hierarchy выделить нашу пулю и перенести её в нужную папку, тогда наша пуля будет выделена синим. Если как-то её поменять после этого, то префаб это не изменит. Нужно будет нажать на кнопку Apply под именем пули. Теперь необходимо реализовать скрипт для полета пули. Создадим скрипт BulletShot в который напишем:

public class BulletShot : MonoBehaviour {

    //Скорость нашей пули
    public float Speed;
    //Время, через которое наша пуля
    //уйдет в пул объектов
    public float TimeToDisable;
    //Каждый раз, когда наша пуля активируется
	void OnEnable () {
        //Мы будем запускать таймер для того
        //Чтоб выключить её
        StartCoroutine(SetDisabled(TimeToDisable));

    }
    IEnumerator SetDisabled(float TimeToDisable)
    {
        //Данный скрип приостановит свое исполнение на 
        //TimeToDisable секунд, а потом продолжит работу
        yield return new WaitForSeconds(TimeToDisable);
        //Выключаем объект, он у нас останется в пуле объектов
        //до следующего использования
        gameObject.SetActive(false);
    }
	void Update () {
        //Теперь пуля будет лететь вперед до того, пока объект не будет выключен
        //Так как наша пуля уже повернута в нужную сторону, а в 2D пространстве
        //Вперед это направо, то нашей пуле надо просто лететь направо 
        //отностительно своего мирового пространства
        transform.position = transform.position+transform.right * Speed * Time.deltaTime;
	}
    private void OnTriggerEnter2D(Collider2D collision)
    {
        //Тут должна быть ваша обработка попадания
        //Вместо этого условия необходимо ваше, которое определит, что
        //в Collision находится именно тот объект, который вам нужен
        if (collision==null)
        {
            //Выключаем ожидание выключения чтоб в случае чего не создавать
            //несколько копий ожиданий
            StopCoroutine("SetDisabled");
            //Выключаем объект
            gameObject.SetActive(false);
            //Дальше весь тот код, который нужнен для вашей игры
            
        }
    }
}

Теперь пули должны лететь в нужную сторону, а через некоторое количество секунд отключаться(не забудте выставить секунды и скорость в инспекторе). Но перед тем, как подвести итоги необходимо разобраться с теми частями кода, которые вы не понимаете. Например, IEnumerator, в обычном c# он используется для циклического обращения к элементам коллекции, но в Unity его можно использовать и подругому. Если реализовать метод возвращающий этот интерфейс напрямую в классе, то его можно вызвать как корутину. Это уже специальная вещь сделанная в Unity для того чтоб код выполнялся не слошным потоком, а иногда останавливался. Корутину используют всегда, где необходимо что-то ждать. Например при анимации каста заклинания, или при перезарядке оружия. Теперь вернемся к проекту. Мы подготовили класс BulletShot для запуска его совместно с пулом объектов, но пул объектов еще не готов, как и создание пули. Для этого нам необходимо в класс нашего персонажа (PlayerController), который будет стрелять написать:

public class PlayerController : MonoBehaviour {
    //Наш пул объектов, который помогает 
    //сохранить память при его использовании
    //Ведь активировать объект гораздо проще, 
    //чем его опять создавать
    public List ObjectPool;
    private void Start()
    {
        //Создаем новый список, так как List - 
        //ссылка на динамический массив
        ObjectPool = new List();
    }
	void Update () {
        //Выстрел будет производится при клике мышкой
        if (Input.GetMouseButtonUp(0) == true)
        {
            //diff - будет смещением нашего нажатия от объекта
            Vector3 diff = Camera.main.ScreenToWorldPoint(Input.mousePosition) - transform.position;
            //номализация приводит каждое значение в промежуток
            //от -1 до 1
            diff.Normalize();
            //по нормализованному виду мы находим угол, так как в diff
            //находится вектор, который можно перенести на тригонометрическую окружность
            float rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
            //и приваиваем наш угол персонажу
            transform.rotation = Quaternion.Euler(0f, 0f, rot_z);
            //Показывает, нашли ли мы выключенный объект в нашем массиве
            bool freeBullet = false;
            //Теперь необходимо проверить, есть ли выключенный объект в нашем пуле
            for (int i = 0; i < ObjectPool.Count; i++)
            {
                //Смотрим, активен ли объект в игровом пространстве
                if (!ObjectPool[i].activeInHierarchy)
                {
                    //Если объект не активен
                    //То мы задаем ему все нужные параметры
                    //Позицию
                    ObjectPool[i].transform.position = transform.position;
                    //Поворот
                    ObjectPool[i].transform.rotation = transform.rotation;
                    //И опять его включаем
                    ObjectPool[i].SetActive(true);
                    //Ставим объект найденным, чтоб опять не создавать лишний
                    freeBullet = true;
                    break;
                }
            }
            //если свободный объект не был найден, то нужно создать еще один
            if (!freeBullet)
            {
                //Создаем объект с нужными значениями и заносим его в пул
                ObjectPool.Add(Instantiate(Resources.Load("Prefub/Bullet"),transform.position,transform.rotation));
            }
        }          
    }
}

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

Реализованная стрельба 2D персонажа в Unity 5

Итак, в итоге этого урока мы реализовали стрельбу для нашего персонажа в Unity 5 с пулом объектов.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (4 оценок, среднее: 5,00 из 5)
Adblock
detector