В этой статье я расскажу к какому способу создания веревок (тросов, цепей) я смог прийти в ходе разработки игры для конкурса Платформеров на GameDev.ru. Пример будет разобран на 2Д проекте, но думаю нет никаких сложностей адаптировать его для 3Д проекта.
Создаем пустую сцену.
+ Показать
− Скрыть
Далее хотелось бы поиметь два объекта-конца. Они могут быть как подвижные, так и неподвижные. Главное, что они должны иметь RigidBody2D компонент. В данном примере я зафиксировал концы в пространстве через Freeze Position.
+ Показать
− Скрыть
Затем нам понадобится префаб объекта-звена, из которого будет состоять веревка. Для использования сил и гравитации звено должно иметь компонент RigidBody2D, а для связей два модуля SpringJoint2D – по одному на левую и правую связь.
+ Показать
− Скрыть
Теперь нам нужен скрипт, который мы повесим на один из концов, например, на левый. Данный скрипт должен обладать публичными GameObject целевого объекта и образца веревки. Поместим в указанные поля, подготовленные объекты.
+ Показать
− Скрыть
Также нам потребуется скрипт для звена цепи, чтобы строить нашу цепь. Данный скрипт должен обладать публичными GameObject целевого объекта, объекта-источника и образца веревки.
+ Показать
− Скрыть
Теперь напишем скрипт инициализации создания первого звена (это скрипт для объекта-конца).
publicclass RopeExampleScript : MonoBehaviour
{
public GameObject target, samplerope;
privatefloat step = 0.2f; //шаг веревки// Start is called before the first frame updatevoid 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>();
}
}
Теперь напишем скрипт для звена цепи.
publicclass RopeNodeExampleScript : MonoBehaviour
{
public GameObject target, ropesample, lbond, rbond;
privatefloat step = 0.2f; //шаг веревки private SpringJoint2D[] sj; //все компоненты пружины// Start is called before the first frame updatevoid 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;
}
}
Настраиваем пружинные связи для нашего префаба-звена.
Запускаем и радуемся.
Дальнейшие трансформации делайте на свой вкус и цвет. Надеюсь, этот материал будет полезен кому-либо.