添加画线动画

This commit is contained in:
2025-06-14 19:02:32 +08:00
parent 4961b6f7da
commit df30729490
2 changed files with 167 additions and 2 deletions

View File

@ -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<MapGraph.Node> unsortedNodes,
float moveSpeed = 2f)
{
if(enumerator!=null)
caller.StopCoroutine(enumerator);
List<MapGraph.Node> sortedNodes = SortNodesByGraphCost(origin.position,unsortedNodes);
List<Vector3> 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<Vector3> unsortedNodes,
float moveSpeed = 2f)
{
if(enumerator!=null)
caller.StopCoroutine(enumerator);
enumerator= DrawLineCoroutine(mover, lineRenderer, unsortedNodes, moveSpeed);
caller.StartCoroutine(enumerator);
}
public static List<MapGraph.Node> SortNodesByGraphCost(Vector3 origin, List<MapGraph.Node> nodes)
{
if (nodes == null || nodes.Count == 0) return new List<MapGraph.Node>();
List<MapGraph.Node> sorted = new List<MapGraph.Node>();
HashSet<MapGraph.Node> unvisited = new HashSet<MapGraph.Node>(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<MapGraph.Node, float> candidateCosts = new Dictionary<MapGraph.Node, float>();
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<Vector3> 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();
}
}

View File

@ -26,6 +26,9 @@ public class LineManger : MonoBehaviour
public Color NormalGreenColor; public Color NormalGreenColor;
public Color HighlightedGreenColor; public Color HighlightedGreenColor;
private Transform mover;
public Transform orgin;
public static LineManger Instance; public static LineManger Instance;
private void Awake() private void Awake()
{ {
@ -174,6 +177,7 @@ public class LineManger : MonoBehaviour
GetMapPoints(); GetMapPoints();
CreateMap(); CreateMap();
ResetAllSpriteRenderColor(); ResetAllSpriteRenderColor();
mover = new GameObject().transform;
} }
private void GetCameraPoints() private void GetCameraPoints()
@ -361,8 +365,10 @@ public class LineManger : MonoBehaviour
{ {
positions.Add(node.position); 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 else
{ {