Создание объектов

Некоторые игры имеют постоянное количество объектов на сцене, однако обычно персонажи, пули, сокровища и другие объекты создаются и удаляются во время игры. В Unity, игровой объект (GameObject) может быть создан через функцию Instantiate, которая делает копию существующего объекта. Объект, который мы будем клонировать, должен быть prefab’ом и сохранен в папке Resources.

Сейчас ты напишешь пару скриптов, с помощью которых можно научиться создавать (spawn’инть) игровые объекты, например, для того, чтобы реализовать механику вот такой ловушки:

Ловушка
Ловушка

Подготовка

Тебе понадобятся четыре игровых объекта и скрипт, с которым ты уже знаком:

  1. Камень, несколько копий которого мы будем сбрасывать на Игрока — Stone.
  2. Объект, который соответствует еще не сработавшей ловушке — TrapOn.
  3. Объект, который соответствует уже сработавшей ловушке — TrapOff.
  4. Объект, который будет запускать ловушку — TrapSwitch.
  5. Скрипт OnTriggerSceneLoader.7z — он будет перезагружать уровень, когда Stone упадет (коснется) Игрока.
Два состояния ловушки: TrapOn и TrapOff
Два состояния ловушки: TrapOn и TrapOff. Они размещены в одном месте, только TrapOff выключен в Инспекторе.
Башня Spawner и TrapSwitch (коллайдер)
Башня Spawner и TrapSwitch (коллайдер)

Stone

По нашему плану нам понадобятся камни, которые будут создаваться над головой Игрока. Выбери 3D-модель, которая тебе понравилась, добавь ей компоненты Rigidbody и два коллайдера: Capsule и Box. Box коллайдер должен быть чуть больше, чем Capsule, а также иметь включенным свойство Trigger.

После этого добавь этому игровому объекту скрипт OnTriggerSceneLoader и укажи в его свойствах название текущей сцены (а еще не забудь добавить ее в Build Settings).

Stone и его компоненты
Stone и его компоненты

Не забудь сохранить объект Stone, как prefab, в папке Resources!

Программирование

Тебе понадобятся два новых скрипта, чтобы все работало как нужно: Spawner.cs и TrapSwitch.cs

Spawner

Как мы уже говорили, в Unity есть функция Instantiate, которая делает копию существующего объекта:

//spawnObject - объект, который мы клонируем.
//transform.position - координаты, в которых необходимо создать клон объекта.
//transform.rotation - угол поворота объекта.

Instantiate(spawnObject, transform.position, transform.rotation);

В нашем случаем наш объект будет физическим, так что ты можешь сразу объявить Rigidbody, также понадобится переменная, в которой ты будешь указывать необходимое количество клонов:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Spawner : MonoBehaviour {

    public Rigidbody spawnObject;
    public int amount;
}

Теперь нужно написать публичный метод, который ты будешь вызывать скриптом TrapSwitch.cs, стандартные методы Update() и Start() нам не понадобятся, так что их можно удалить:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Spawner : MonoBehaviour {

    public Rigidbody spawnObject;
    public int amount;


    public void Spawn()
    {
    //Здесь будет твой код.
    }
}

Чтобы выполнить функцию Instantiate несколько раз, используй цикл, например, do while:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Spawner : MonoBehaviour {

    public Rigidbody spawnObject;
    public int amount;


    public void Spawn()
    {
        float i = 0;
        
        do
        {
            Instantiate(spawnObject, transform.position, transform.rotation);
            i++;
        } while (i!=amount);
    }
}

Технически, скрипт готов, но, если оставить все как есть, то во время выполнения метода Spawn(), практически, одновременно в одной точке появятся все amount (число) клоны. Из-за того, что наши клоны содержат в себе компоненты Rigidbody и коллайдер, клоны просто разлетятся в разные стороны, что выглядит не очень. При этом, шанс, что хотя бы один клон-камень попадет в Игрока будет очень низок. Поэтому добавь немного рандома и сделай так, чтобы каждый следующий камень создавался выше предыдущего на i:

Instantiate(spawnObject, transform.position + new Vector3 (0f, i, 0f), new Quaternion (Random.Range(-10,10), Random.Range(-10, 10), Random.Range(-10, 10), Random.Range(-10, 10)));

Теперь все работает как нужно. Продолжим.

TrapSwitch

TrapSwitch будет размещен на объекте с триггером, когда Игрок будет его касаться, TrapSwitch будет запускать метод Spawn() у объекта Spawner. Напомним про коллайдеры и триггеры:

Триггер — это зона срабатывания определенных действий, когда объект входит в эту зону, находится в ней или выходит за ее пределы.

Сейчас тебе понадобиться метод OnTriggerEnter. Он выполняется, когда объект только вошел в зону триггера один раз. Создай такой скрипт:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TrapSwitch : MonoBehaviour {

    void OnTriggerEnter(Collider other)
    {
        //Здесь будет твой код.
    }
}

Ты собираешься взаимодействовать с двумя игровыми объектами и объектом Spawner. Их нужно объявить:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TrapSwitch : MonoBehaviour {

    public Spawner spawner;
    public GameObject trapOn, trapOff;

    void OnTriggerEnter(Collider other)
    {
        //Здесь будет твой код.
    }
}

Теперь необходимо убедиться, что объект, который войдет в триггер является Игроком. Это можно сделать, используя тег, как в OnTriggerSceneLoader:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TrapSwitch : MonoBehaviour {

    public Spawner spawner;
    public GameObject trapOn, trapOff;

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
           //Здесь будет твой код.
        }
    }
}

Теперь последовательно напиши все необходимые команды внутрь условия: удаление (уничтожение) объекта TrapOn, включение объекта TrapOff, выполнение метода Spawn() и удаление (уничтожения) себя.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TrapSwitch : MonoBehaviour {

    public Spawner spawner;
    public GameObject trapOn, trapOff;

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.tag == "Player")
        {
            Destroy(trapOn);
            trapOff.SetActive(true);
            spawner.Spawn();
            Destroy(gameObject);
        }
    }
}

Все скрипты написаны. Поздравляем! Осталось правильно разместить все объекты на сцене и не забыть указать им друг на друга.