添加画线动画
This commit is contained in:
159
Assets/Scripts/0614/PathLineAnimator.cs
Normal file
159
Assets/Scripts/0614/PathLineAnimator.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user