104 lines
2.8 KiB
C#
104 lines
2.8 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
[RequireComponent(typeof(LineRenderer))]
|
|
public class PhysicLineSegment : MonoBehaviour
|
|
{
|
|
public float segmentSpacing = 0.1f;
|
|
public int k = 30;
|
|
|
|
public List<VerletParticle> particles = new();
|
|
private List<VerletStick> sticks = new();
|
|
[HideInInspector]
|
|
public LineRenderer lineRenderer;
|
|
private int segmentCount;
|
|
public float gravity = -9.8f;
|
|
|
|
private float originalLength;
|
|
|
|
public void Initialize(Vector3 start, Vector3 end)
|
|
{
|
|
particles.Clear();
|
|
sticks.Clear();
|
|
if (lineRenderer != null)
|
|
{
|
|
lineRenderer.positionCount = 0;
|
|
}
|
|
|
|
originalLength = Vector3.Distance(start, end);
|
|
|
|
segmentCount = Mathf.RoundToInt(originalLength / segmentSpacing);
|
|
lineRenderer = GetComponent<LineRenderer>();
|
|
|
|
// Initialize particles
|
|
for (int i = 0; i < segmentCount; i++)
|
|
{
|
|
var particle = new VerletParticle(Vector3.Lerp(start, end, i / (float)segmentCount));
|
|
particles.Add(particle);
|
|
}
|
|
|
|
// Initialize sticks
|
|
for (int i = 0; i < segmentCount - 1; i++)
|
|
{
|
|
sticks.Add(new VerletStick(particles[i], particles[i + 1], segmentSpacing));
|
|
}
|
|
|
|
// Lock the first particle
|
|
particles[0].isLocked = true;
|
|
|
|
lineRenderer.positionCount = segmentCount;
|
|
}
|
|
|
|
void FixedUpdate()
|
|
{
|
|
UpdateLine();
|
|
for (int i = 0; i < segmentCount; i++)
|
|
{
|
|
if (lineRenderer != null)
|
|
{
|
|
lineRenderer.SetPosition(i, particles[i].position);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateLine()
|
|
{
|
|
// Apply gravity to particles
|
|
for (int i = 1; i < particles.Count; i++)
|
|
{
|
|
particles[i].ApplyForce(Vector3.up * gravity * Time.deltaTime);
|
|
particles[i].UpdatePosition();
|
|
}
|
|
|
|
// Update sticks
|
|
for (int ik = 0; ik < k; ik++)
|
|
{
|
|
foreach (var stick in sticks)
|
|
{
|
|
stick.UpdateStick();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UpdatePlug(Transform plug)
|
|
{
|
|
if (plug && particles.Count > 1)
|
|
{
|
|
Vector3 plugPosition = particles[^1].position;
|
|
float plugLength = plug.GetComponent<SpriteRenderer>().bounds.size.y;
|
|
Vector3 direction = particles[^1].position - particles[^2].position;
|
|
float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
|
|
plug.rotation = Quaternion.Euler(0, 0, angle - 90f);
|
|
plug.position = plugPosition + direction.normalized * (plugLength / 2);
|
|
}
|
|
}
|
|
|
|
public void UpdateStart(Vector3 newStartPosition)
|
|
{
|
|
if (particles.Count > 0)
|
|
{
|
|
particles[0].position = newStartPosition;
|
|
}
|
|
}
|
|
}
|