From df307294908d69c6206a50a3afe14a14f104aaab Mon Sep 17 00:00:00 2001 From: wuyazishidi <2604591896@qq.com> Date: Sat, 14 Jun 2025 19:02:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=BB=E7=BA=BF=E5=8A=A8?= =?UTF-8?q?=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/0614/PathLineAnimator.cs | 159 ++++++++++++++++++++++++ Assets/Scripts/Path/LineManger.cs | 10 +- 2 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 Assets/Scripts/0614/PathLineAnimator.cs diff --git a/Assets/Scripts/0614/PathLineAnimator.cs b/Assets/Scripts/0614/PathLineAnimator.cs new file mode 100644 index 0000000..a0024d2 --- /dev/null +++ b/Assets/Scripts/0614/PathLineAnimator.cs @@ -0,0 +1,159 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +public class PathLineAnimator : MonoBehaviour +{ + private static IEnumerator enumerator; + public static void Play( + MonoBehaviour caller, + Transform origin, + Transform mover, + LineRenderer lineRenderer, + List unsortedNodes, + float moveSpeed = 2f) + { + if(enumerator!=null) + caller.StopCoroutine(enumerator); + List sortedNodes = SortNodesByGraphCost(origin.position,unsortedNodes); + List sortedPositions = sortedNodes.Select(n => n.position).ToList(); + enumerator= DrawLineCoroutine(mover, lineRenderer, sortedPositions, moveSpeed); + caller.StartCoroutine(enumerator); + } + + public static void Play( + MonoBehaviour caller, + Transform origin, + Transform mover, + LineRenderer lineRenderer, + List unsortedNodes, + float moveSpeed = 2f) + { + if(enumerator!=null) + caller.StopCoroutine(enumerator); + enumerator= DrawLineCoroutine(mover, lineRenderer, unsortedNodes, moveSpeed); + caller.StartCoroutine(enumerator); + } + + + +public static List SortNodesByGraphCost(Vector3 origin, List nodes) +{ + if (nodes == null || nodes.Count == 0) return new List(); + + List sorted = new List(); + HashSet unvisited = new HashSet(nodes); + + // ✅ 从 origin.position 找最近的节点作为起点 + MapGraph.Node current = unvisited + .OrderBy(n => Vector3.Distance(origin, n.position)) + .First(); + + sorted.Add(current); + unvisited.Remove(current); + + while (unvisited.Count > 0) + { + Dictionary candidateCosts = new Dictionary(); + + foreach (var candidate in unvisited) + { + var path = PathFinder.FindPath(current, candidate); + if (path == null) continue; + + float totalCost = 0f; + for (int i = 0; i < path.Count - 1; i++) + { + var edge = path[i].edges.Find(e => e.target == path[i + 1]); + if (edge != null) + totalCost += edge.cost; + } + + candidateCosts[candidate] = totalCost; + } + + if (candidateCosts.Count == 0) + { + Debug.LogError("排序中断:无可达点"); + break; + } + + // 找出最小权重 + float minCost = candidateCosts.Values.Min(); + + // 找出具有最小权重的所有点 + var sameCostNodes = candidateCosts + .Where(kv => Mathf.Approximately(kv.Value, minCost)) + .Select(kv => kv.Key) + .ToList(); + + // ✅ 只保留其中一个(第一个),其余全部舍弃 + MapGraph.Node selected = sameCostNodes.First(); + sorted.Add(selected); + unvisited.Remove(selected); + + for (int i = 1; i < sameCostNodes.Count; i++) + { + unvisited.Remove(sameCostNodes[i]); + } + + current = selected; + } + + return sorted; +} + + private static IEnumerator DrawLineCoroutine( + Transform mover, + LineRenderer lineRenderer, + List points, + float moveSpeed) + { + int currentIndex = 0; + + // 初始:第一段开始 + lineRenderer.positionCount = 2; + lineRenderer.SetPosition(0, points[0]); + lineRenderer.SetPosition(1, points[0]); + mover.position = points[0]; + + while (currentIndex < points.Count - 1) + { + Vector3 start = points[currentIndex]; + Vector3 end = points[currentIndex + 1]; + float t = 0f; + float segmentLength = Vector3.Distance(start, end); + + while (t < 1f) + { + t += Time.deltaTime * moveSpeed / segmentLength; + Vector3 currentPos = Vector3.Lerp(start, end, t); + mover.position = currentPos; + + // 前段保持不动,当前段动态更新 + for (int i = 0; i <= currentIndex; i++) + { + lineRenderer.SetPosition(i, points[i]); + } + + lineRenderer.SetPosition(currentIndex + 1, currentPos); + + yield return null; + } + + + currentIndex++; + + if (currentIndex < points.Count - 1) + { + // 增加一个点用于下一段 + lineRenderer.positionCount++; + } + } + + // 最后一段固定终点 + lineRenderer.SetPosition(lineRenderer.positionCount - 1, points.Last()); + mover.position = points.Last(); + } +} diff --git a/Assets/Scripts/Path/LineManger.cs b/Assets/Scripts/Path/LineManger.cs index d284b0f..4bc9512 100644 --- a/Assets/Scripts/Path/LineManger.cs +++ b/Assets/Scripts/Path/LineManger.cs @@ -26,6 +26,9 @@ public class LineManger : MonoBehaviour public Color NormalGreenColor; public Color HighlightedGreenColor; + private Transform mover; + public Transform orgin; + public static LineManger Instance; private void Awake() { @@ -174,6 +177,7 @@ public class LineManger : MonoBehaviour GetMapPoints(); CreateMap(); ResetAllSpriteRenderColor(); + mover = new GameObject().transform; } private void GetCameraPoints() @@ -361,8 +365,10 @@ public class LineManger : MonoBehaviour { positions.Add(node.position); } - lineRenderer.positionCount = positions.Count; - lineRenderer.SetPositions(positions.ToArray()); + + PathLineAnimator.Play(this, orgin,mover, lineRenderer, positions, moveSpeed: 3f); + // lineRenderer.positionCount = positions.Count; + // lineRenderer.SetPositions(positions.ToArray()); } else {