UnityСтатьиПрограммирование

Создание веревки в Unity на базовых SpringJoint.

Автор:

В этой статье я расскажу к какому способу создания веревок (тросов, цепей) я смог прийти в ходе разработки игры для конкурса Платформеров на GameDev.ru. Пример будет разобран на 2Д проекте, но думаю нет никаких сложностей адаптировать его для 3Д проекта.

Создаем пустую сцену.

+ Показать

Далее хотелось бы поиметь два объекта-конца. Они могут быть как подвижные, так и неподвижные. Главное, что они должны иметь RigidBody2D компонент. В данном примере я зафиксировал концы в пространстве через Freeze Position.

+ Показать

Затем нам понадобится префаб объекта-звена, из которого будет состоять веревка. Для использования сил и гравитации звено должно иметь компонент RigidBody2D, а для связей два модуля SpringJoint2D – по одному на левую и правую связь.

+ Показать

Теперь нам нужен скрипт, который мы повесим на один из концов, например, на левый. Данный скрипт должен обладать публичными GameObject целевого объекта и образца веревки. Поместим в указанные поля, подготовленные объекты.

+ Показать

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

+ Показать

Теперь напишем скрипт инициализации создания первого звена (это скрипт для объекта-конца).

public class RopeExampleScript : MonoBehaviour
{
    public GameObject target, samplerope;
    private float step = 0.2f; //шаг веревки

    // Start is called before the first frame update
    void Start()
    {
        // определяем вектор нашей цепи
        Vector3 tarvec = target.transform.position - transform.position;
        // создаем образец звена и помещаем в нужную позицию сдвигаясь на один шаг
        GameObject newrope = Instantiate(samplerope, transform.position + 
            tarvec.normalized * step, Quaternion.identity);
        // получаем доступ к параметрам скрипта звена
        RopeNodeExampleScript newrope_rnes = newrope.GetComponent<RopeNodeExampleScript>();
        // указываем левую связь
        newrope_rnes.lbond = gameObject;
        // указываем объект-цель
        newrope_rnes.target = target;

        // добавляем на объект-источник пружинную связь
        SpringJoint2D source_sj = gameObject.AddComponent<SpringJoint2D>();
        // эти параметры подбираются экспериментально по вкусу для своей игры
        source_sj.frequency = 25;
        source_sj.dampingRatio = 1;
        // присоединяем к этой связи наше новое звено
        source_sj.connectedBody = newrope.GetComponent<Rigidbody2D>();
    }
}

Теперь напишем скрипт для звена цепи.

public class RopeNodeExampleScript : MonoBehaviour
{
    public GameObject target, ropesample, lbond, rbond;

    private float step = 0.2f; //шаг веревки 
    private SpringJoint2D[] sj; //все компоненты пружины

    // Start is called before the first frame update
    void Start()
    {
        // Получаем все компоненты пружины
        sj = GetComponents<SpringJoint2D>();
        // Выключаем их (это нужно, чтобы корректно настроить связи).
        // Можно изначально держать их выключеными.
        sj[0].enabled = false;
        sj[1].enabled = false;

        // определяем вектор нашей цепи
        Vector3 tarvec = target.transform.position - transform.position;
        // проверяем, если дистанция до целевого объекта больше шага, то создаем звено
        if (tarvec.magnitude > step)
        {
            // создаем звено
            GameObject newrope = Instantiate(ropesample, transform.position +
                tarvec.normalized * step, Quaternion.identity);
            // получаем доступ к скрипту нового звена
            RopeNodeExampleScript newrope_rope = newrope.GetComponent<RopeNodeExampleScript>();
            // устанавливаем левую связь для нового звена
            newrope_rope.lbond = gameObject;
            // устанавливаем объект-цель для нового звена
            newrope_rope.target = target;
            // устанавливаем правую связь для текущего звена
            rbond = newrope;

        }
        else // если дистанция до целевого объекта меньше шага, то замыкаем цепь на нем
        {
            //замыкаем правую связь на объекте-цели
            rbond = target;
            //добавляем пружинную связь на объект цель
            SpringJoint2D ropeknot_sj = target.AddComponent<SpringJoint2D>();
            //эти параметры подбираются экспериментально по вкусу для своей игры
            ropeknot_sj.frequency = 25;
            ropeknot_sj.dampingRatio = 1;
            //присоединяем к этой связи наше звено
            ropeknot_sj.connectedBody = GetComponent<Rigidbody2D>();
        }
        
        //присоединяем к пружинам левое и правое тело
        sj[0].connectedBody = lbond.GetComponent<Rigidbody2D>();
        sj[1].connectedBody = rbond.GetComponent<Rigidbody2D>();
        //активируем пружинные модули
        sj[0].enabled = true;
        sj[1].enabled = true;
    }
}

Настраиваем пружинные связи для нашего префаба-звена.

6 | Создание веревки в Unity на базовых SpringJoint.

Запускаем и радуемся.

7 | Создание веревки в Unity на базовых SpringJoint.

Дальнейшие трансформации делайте на свой вкус и цвет. Надеюсь, этот материал будет полезен кому-либо.

Тема конкурса Платформеров:
https://gamedev.ru/projects/forum/?id=263782

#физика, #SpringJoint, #Unity

24 декабря 2021