151 lines
4.6 KiB
C#
151 lines
4.6 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using DG.Tweening;
|
|
|
|
[RequireComponent(typeof(LineRenderer))]
|
|
public class PhysicLineSegment : MonoBehaviour
|
|
{
|
|
public float segmentSpacing = 0.1f;
|
|
public int k = 30;
|
|
|
|
private Vector3 start;
|
|
private Vector3 end;
|
|
public List<VerletParticle> particles = new List<VerletParticle>();
|
|
private List<VerletStick> sticks = new List<VerletStick>();
|
|
[HideInInspector]
|
|
public LineRenderer lineRenderer;
|
|
private int segmentCount;
|
|
public float gravity = -9.8f;
|
|
|
|
private float originalLength;
|
|
private float targetLength;
|
|
|
|
public void Initialize(Vector3 start, Vector3 end)
|
|
{
|
|
particles.Clear();
|
|
sticks.Clear();
|
|
if (lineRenderer != null)
|
|
{
|
|
lineRenderer.positionCount = 0;
|
|
}
|
|
this.start = start;
|
|
this.end = end;
|
|
originalLength = Vector3.Distance(start, end);
|
|
targetLength = originalLength; // 初始化目标长度
|
|
|
|
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 SetTargetLength(float newLength, float duration)
|
|
{
|
|
DOTween.To(() => targetLength, x => targetLength = x, newLength, duration);
|
|
}
|
|
|
|
public void UpdateLineLength(float newLength)
|
|
{
|
|
// 计算新的段数
|
|
int newSegmentCount = Mathf.RoundToInt(newLength / segmentSpacing);
|
|
|
|
// 如果新的段数大于当前段数,增加粒子
|
|
if (newSegmentCount > segmentCount)
|
|
{
|
|
for (int i = segmentCount; i < newSegmentCount; i++)
|
|
{
|
|
var particle = new VerletParticle(Vector3.Lerp(start, end, i / (float)newSegmentCount));
|
|
particles.Add(particle);
|
|
if (i > 0)
|
|
{
|
|
sticks.Add(new VerletStick(particles[i - 1], particles[i], segmentSpacing));
|
|
}
|
|
}
|
|
}
|
|
// 如果新的段数小于当前段数,减少粒子
|
|
else if (newSegmentCount < segmentCount)
|
|
{
|
|
particles.RemoveRange(newSegmentCount, segmentCount - newSegmentCount);
|
|
sticks.RemoveRange(newSegmentCount - 1, segmentCount - newSegmentCount);
|
|
}
|
|
|
|
// 更新段数
|
|
segmentCount = newSegmentCount;
|
|
if(lineRenderer!=null)
|
|
{
|
|
lineRenderer.positionCount = segmentCount;
|
|
}
|
|
|
|
// 更新粒子位置
|
|
for (int i = 0; i < segmentCount; i++)
|
|
{
|
|
particles[i].position = Vector3.Lerp(start, end, i / (float)segmentCount);
|
|
}
|
|
}
|
|
|
|
public void UpdatePlug(Transform plug)
|
|
{
|
|
if (plug != null && particles.Count > 1)
|
|
{
|
|
Vector3 plugPosition = particles[particles.Count - 1].position;
|
|
float plugLength = plug.GetComponent<SpriteRenderer>().bounds.size.y;
|
|
Vector3 direction = particles[particles.Count - 1].position - particles[particles.Count - 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 UpdateEndPoint(Transform transform)
|
|
{
|
|
particles[particles.Count - 1].isLocked = true;
|
|
particles[particles.Count - 1].position = transform.position;
|
|
}
|
|
} |