From 7b8c648f66503d8dc79a9480741a8e6b66bab25e Mon Sep 17 00:00:00 2001 From: bottlefish <781230111@qq.com> Date: Sat, 17 May 2025 03:43:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=BF=9B=E5=BA=A6=E6=8C=87?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FixSystemNew/BodyModule/GearFollower.cs | 100 +++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/Assets/Scripts/FixSystemNew/BodyModule/GearFollower.cs b/Assets/Scripts/FixSystemNew/BodyModule/GearFollower.cs index 66875f694..494fa6518 100644 --- a/Assets/Scripts/FixSystemNew/BodyModule/GearFollower.cs +++ b/Assets/Scripts/FixSystemNew/BodyModule/GearFollower.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using UnityEngine; public class GearFollower : MonoBehaviour @@ -10,6 +9,15 @@ public class GearFollower : MonoBehaviour public float detachDistance = 1.0f; public float tractionSpeed = 2f; + [Header("切割效果参数")] + public float cutEdgeExpandDuration = 0.5f; // 卷边展开时间 + public float cutEdgeCoolDuration = 3f; // 冷却时间 + public float cutEdgeMaxOffset = 0.05f; // 卷边最大偏移量 + + public Gradient cutEdgeColorGradient; // 颜色渐变(从高温到冷却) + + public Material cutEdgeMaterial; // 用于绘制卷边的材质 + private List edgePoints; private int currentEdgeIndex = 0; private int tractionDirection = 1; @@ -19,6 +27,15 @@ public class GearFollower : MonoBehaviour private Camera mainCamera; + // 记录切割的边段及其动画状态 + private class CutSegment + { + public int startIndex; + public float timeElapsed; // 0~卷边展开+冷却总时长 + public LineRenderer lineRenderer; + } + private List cutSegments = new List(); + void Start() { mainCamera = Camera.main; @@ -43,6 +60,8 @@ public class GearFollower : MonoBehaviour UpdateTractionState(mouseWorldPos); break; } + + UpdateCutSegments(); } private void LoadEdgePointsFromSprite() @@ -177,6 +196,9 @@ public class GearFollower : MonoBehaviour // 如果到达段末,前进一段 if (Vector2.Distance(targetPoint, to) < 0.01f) { + // 记录切割痕迹 + AddCutSegment(currentEdgeIndex); + currentEdgeIndex = nextIndex; } } @@ -186,6 +208,82 @@ public class GearFollower : MonoBehaviour } } + // 添加一个切割段,生成卷边视觉效果 + private void AddCutSegment(int startIndex) + { + // 防止重复添加同一段(可选) + foreach (var seg in cutSegments) + { + if (seg.startIndex == startIndex) + return; + } + + GameObject go = new GameObject($"CutSegment_{startIndex}"); + go.transform.parent = transform.parent; // 放在GearFollower同级方便管理 + + LineRenderer lr = go.AddComponent(); + lr.positionCount = 4; // 画一个四点的矩形条表示卷边 + lr.material = cutEdgeMaterial != null ? cutEdgeMaterial : new Material(Shader.Find("Sprites/Default")); + lr.widthCurve = AnimationCurve.Constant(0, 1, 0.05f); + lr.numCapVertices = 4; + lr.useWorldSpace = true; + + CutSegment newSeg = new CutSegment + { + startIndex = startIndex, + timeElapsed = 0f, + lineRenderer = lr + }; + + cutSegments.Add(newSeg); + } + + // 每帧更新所有切割段动画 + private void UpdateCutSegments() + { + for (int i = cutSegments.Count - 1; i >= 0; i--) + { + var seg = cutSegments[i]; + seg.timeElapsed += Time.deltaTime; + + float expandT = Mathf.Clamp01(seg.timeElapsed / cutEdgeExpandDuration); + float coolT = Mathf.Clamp01((seg.timeElapsed - cutEdgeExpandDuration) / cutEdgeCoolDuration); + + // 获取该段两个端点 + int nextIndex = WrapIndex(seg.startIndex + 1); + Vector2 p1 = edgePoints[seg.startIndex]; + Vector2 p2 = edgePoints[nextIndex]; + + Vector2 segmentDir = (p2 - p1).normalized; + Vector2 normal = new Vector2(-segmentDir.y, segmentDir.x); + + float offset = cutEdgeMaxOffset * expandT; + + // 四个点形成的卷边矩形 + Vector3[] positions = new Vector3[4]; + // 主边 + positions[0] = p1; + positions[1] = p2; + // 卷边偏移边(沿法线方向偏移offset) + positions[2] = p2 + normal * offset; + positions[3] = p1 + normal * offset; + + seg.lineRenderer.positionCount = 4; + seg.lineRenderer.SetPositions(positions); + + // 颜色渐变 + Color color = cutEdgeColorGradient.Evaluate(1f - coolT); + seg.lineRenderer.startColor = color; + seg.lineRenderer.endColor = color; + + // 冷却结束删除该段 + if (seg.timeElapsed > cutEdgeExpandDuration + cutEdgeCoolDuration) + { + Destroy(seg.lineRenderer.gameObject); + cutSegments.RemoveAt(i); + } + } + } private int FindNearestEdgePointIndex(Vector2 pos, out float minDist) {