Руководство по динамическому изменению сцен в Unity

Как только вы создадите красивую сцену в Unity, вскоре возникнет необходимость сделать ее динамичной, реагируя на взаимодействия игроков или состояния NPC. Например, ролевая игра, в которой необходимо добавить эффекты частиц для произнесения заклинаний, или мобильная игра, в которой на экране добавляются элементы, которые игрок может собирать.

Цель: я расскажу, как подготовить игровой объект к созданию экземпляра во время выполнения, а также как уничтожить игровые объекты. Это руководство по основам Unity, что означает, что оно не будет охватывать пулы объектов и другие шаблоны/практики, которые будут использоваться в полной игре. Однако я планирую рассказать об этом в следующей статье.

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

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

Во-первых, нам нужно создать сам лазерный игровой объект и добавить необходимые нам компоненты. Затем нам нужен скрипт Player, который будет ссылаться на префаб лазера, чтобы он знал, какой экземпляр создавать. Наконец, мы настроим начальную огневую позицию относительно игрока и удалим игровой объект лазера, как только он покинет экран.

Определение префаба

Давайте сначала определим, что такое префаб (сокращение от prefabrication) в контексте Unity. Если вы знакомы с Unreal Engine или Godot, представьте себе префаб как Blueprint или Scene.

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

Создание префаба Laser

Я создам новый игровой объект-капсулу с именем Laser, щелкнув правой кнопкой мыши в окне иерархии и выбрав 3D-объект -> Капсула. Размер по умолчанию слишком велик для нашего использования, поэтому я уменьшу его в инспекторе до 0,2.

Чтобы придать ему цвет, я также создам новый лазерный материал и изменю цвет альбедо. Капсульный игровой объект по умолчанию предоставляет все, что нам нужно на данный момент; сетчатый фильтр и рендерер, а также капсульный коллайдер.

Я создал папку «Prefabs» для хранения префабов, которые мы будем использовать в игре. Чтобы создать префаб, просто перетащите объект Laser Game из окна «Иерархия» в новую папку «Префабы» в окне «Проект». Синий значок указывает, что теперь это сборный актив.

Создание экземпляров префабов

Когда игрок нажимает пробел, мы хотим создать экземпляр префаба Laser. Давайте добавим поле, которое нам понадобится для установки ссылки на префаб.

using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] private GameObject laserPrefab;
    
    // ...
}

Не забудьте назначить префаб Laser из инспектора. Мы все устали видеть в консоли нулевые сообщения об ошибках.

В методе Update мы закодируем проверку ввода и создадим экземпляр префаба в текущей позиции игрока и повороте идентификатора. Посмотрим на результат работы на данный момент.

private void Update()
{   
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Instantiate(laserPrefab, transform.position, Quaternion.identity);
    }
}

Что ж, сейчас мы создаем экземпляры лазеров, и это здорово. Однако пока все, что мы можем с ними делать, — это рисовать текст и изображения, потому что они не двигаются! Давайте исправим это с помощью нового сценария Laser, который перемещается по вектору вверх.

using UnityEngine;

public class Laser : MonoBehaviour
{
    [SerializeField] private float speed = 8.0f; 
    
    void Update()
    {
        transform.Translate(Time.deltaTime * speed * Vector3.up);
    }
}

Еще одно небольшое изменение, которое я внесу в сценарий Player, — это добавить вектор смещения к позиции, в которой создаются экземпляры лазера, чтобы они начинались около вершины куба игрока, а не из центра (поскольку в настоящее время мы используем transform.position игрока).

private void Update()
{
    CalculateMovement();
      
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Instantiate(laserPrefab, transform.position + new Vector3(0, 0.8f), Quaternion.identity);
    }
}

Уничтожение префабов

У нас есть еще одна проблема, которую вы, возможно, уже заметили. Если мы посмотрим на окно «Иерархия» в режиме игры, вы увидите, что экземпляры клонов Laser накапливаются с течением времени.

Эти лазерные экземпляры постоянно рассчитывают свое движение по оси Y, и мы больше никогда их не увидим. Я добавлю следующий код в метод Update сценария Laser, чтобы уничтожить игровой объект, когда он окажется за кадром.

Для этого прототипа с соотношением сторон 16:9 лазер выйдет за пределы экрана с положением Y около 8. Вы можете закодировать его таким образом, что, вероятно, подойдет для быстрого прототипирования.

void Update()
{
    // ...

    if (transform.position.y >= 8.0f)
    {
        Destroy(gameObject);
    }
}

Краткое содержание

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

Берегите себя.
Оставайтесь такими замечательными.