Skip to content

Instantly share code, notes, and snippets.

@koster
Last active February 25, 2025 18:57
Show Gist options
  • Save koster/1b69577d94eb58cbaedd0c8182cc17f6 to your computer and use it in GitHub Desktop.
Save koster/1b69577d94eb58cbaedd0c8182cc17f6 to your computer and use it in GitHub Desktop.
ChatGPT verlet rope
using UnityEngine;
public class VerletRope : MonoBehaviour
{
public Transform startPoint; // Начальная точка верёвки
public Transform endPoint; // Конечная точка верёвки
public int segmentCount = 10; // Количество сегментов верёвки
public float segmentLength = 0.2f; // Длина каждого сегмента
public int simulationIterations = 5; // Количество итераций симуляции
public float gravity = -9.8f; // Гравитация
private Vector3[] positions;
private Vector3[] oldPositions;
private LineRenderer lineRenderer;
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.positionCount = segmentCount;
positions = new Vector3[segmentCount];
oldPositions = new Vector3[segmentCount];
// Инициализация точек верёвки
Vector3 ropeDirection = (endPoint.position - startPoint.position).normalized;
for (int i = 0; i < segmentCount; i++)
{
positions[i] = startPoint.position + ropeDirection * segmentLength * i;
oldPositions[i] = positions[i];
}
}
void Update()
{
SimulateVerlet();
ApplyConstraints();
UpdateLineRenderer();
}
private void SimulateVerlet()
{
for (int i = 1; i < segmentCount; i++) // Не трогаем первую точку
{
Vector3 currentPos = positions[i];
Vector3 velocity = currentPos - oldPositions[i];
oldPositions[i] = currentPos;
positions[i] += velocity + new Vector3(0, gravity * Time.deltaTime, 0) * Time.deltaTime;
}
}
private void ApplyConstraints()
{
// Первая и последняя точки прикреплены к объектам
positions[0] = startPoint.position;
positions[segmentCount - 1] = endPoint.position;
// Обработка всех сегментов
for (int k = 0; k < simulationIterations; k++)
{
for (int i = 0; i < segmentCount - 1; i++)
{
Vector3 segmentVector = positions[i + 1] - positions[i];
float currentLength = segmentVector.magnitude;
float error = (currentLength - segmentLength) / currentLength;
Vector3 correction = segmentVector * 0.5f * error;
// Перемещаем точки
if (i > 0)
{
positions[i] += correction;
}
if (i + 1 < segmentCount - 1)
{
positions[i + 1] -= correction;
}
}
}
}
private void UpdateLineRenderer()
{
lineRenderer.SetPositions(positions);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment