Files
aibis-dream/Assets/Scripts/FixSystem/Line/PhysicLineSegment.cs
T
2025-02-19 17:25:37 +08:00

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;
}
}