using System.Collections.Generic; using UnityEngine; [RequireComponent(typeof(LineRenderer))] public class GuideArrowPath : MonoBehaviour { [SerializeField] private LineRenderer lineRenderer; // 序列化字段,可以通过编辑器设置 // 新增:路径平滑参数 public float smoothSpeed = 5f; private List targetPath = new List(); private List currentPath = new List(); private bool isTransitioning = false; // 路径显示设置 public LayerMask obstacleMask = 1; public float pathHeight = 0.5f; public int maxPathPoints = 50; // 限制路径点数量 public float minPointDistance = 0.1f; // 最小点间距 void Awake() { // 确保获取预制体上的LineRenderer if (lineRenderer == null) { lineRenderer = GetComponent(); if (lineRenderer == null) { Debug.LogError("GuideArrowPre预制体缺少LineRenderer组件!"); return; } } // 初始化LineRenderer InitializeLineRenderer(); } void Update() { // 平滑过渡路径 if (isTransitioning && targetPath.Count > 0) { SmoothTransitionPath(); } } private void InitializeLineRenderer() { // 确保有LineRenderer组件 if (lineRenderer == null) { lineRenderer = GetComponent(); if (lineRenderer == null) { Debug.LogError("无法找到LineRenderer组件!"); return; } } // 设置默认LineRenderer属性 // 注意:这些设置可能会被预制体上的设置覆盖 if (lineRenderer.material == null) { lineRenderer.material = new Material(Shader.Find("Sprites/Default")); } if (lineRenderer.startWidth <= 0) { lineRenderer.startWidth = 0.1f; lineRenderer.endWidth = 0.05f; } if (lineRenderer.startColor == Color.clear) { lineRenderer.startColor = Color.cyan; lineRenderer.endColor = Color.blue; } lineRenderer.positionCount = 0; } /// /// 设置路径(外部调用) /// public void SetPath(List path) { if (path == null || path.Count < 2) return; // 优化路径点数量 path = OptimizePathPoints(path); // 设置目标路径 targetPath = new List(path); // 如果当前没有路径,直接设置 if (currentPath.Count == 0) { currentPath = new List(targetPath); UpdateLineRenderer(currentPath); } else { // 开始平滑过渡 isTransitioning = true; } } /// /// 平滑过渡路径 /// private void SmoothTransitionPath() { bool pathChanged = false; // 确保当前路径和目标路径长度一致 while (currentPath.Count < targetPath.Count) currentPath.Add(targetPath[0]); while (currentPath.Count > targetPath.Count) currentPath.RemoveAt(currentPath.Count - 1); // 平滑移动每个点 for (int i = 0; i < targetPath.Count; i++) { Vector3 targetPoint = targetPath[i]; Vector3 currentPoint = currentPath[i]; // 如果点距离较远,使用平滑移动 if (Vector3.Distance(currentPoint, targetPoint) > minPointDistance) { currentPath[i] = Vector3.Lerp(currentPoint, targetPoint, Time.deltaTime * smoothSpeed); pathChanged = true; } } // 更新渲染 if (pathChanged) { UpdateLineRenderer(currentPath); } else { isTransitioning = false; } } /// /// 优化路径点数量 /// private List OptimizePathPoints(List path) { if (path.Count <= maxPathPoints) return path; List optimized = new List(); float step = (float)path.Count / maxPathPoints; for (int i = 0; i < maxPathPoints; i++) { int index = Mathf.Min(Mathf.FloorToInt(i * step), path.Count - 1); optimized.Add(path[index]); } // 确保包含起点和终点 if (!optimized.Contains(path[0])) optimized[0] = path[0]; if (!optimized.Contains(path[path.Count - 1])) optimized[optimized.Count - 1] = path[path.Count - 1]; return optimized; } /// /// 更新LineRenderer /// private void UpdateLineRenderer(List path) { if (lineRenderer == null || path.Count < 2) return; // 调整高度 Vector3[] adjustedPath = new Vector3[path.Count]; for (int i = 0; i < path.Count; i++) { adjustedPath[i] = new Vector3(path[i].x, pathHeight, path[i].z); } lineRenderer.positionCount = adjustedPath.Length; lineRenderer.SetPositions(adjustedPath); } /// /// 显示路径 /// public void ShowPath() { if (lineRenderer != null) lineRenderer.enabled = true; } /// /// 隐藏路径 /// public void ClosePath() { if (lineRenderer != null) lineRenderer.enabled = false; } /// /// 清理路径数据 /// public void ClearPath() { targetPath.Clear(); currentPath.Clear(); isTransitioning = false; if (lineRenderer != null) { lineRenderer.positionCount = 0; } } /// /// 获取当前路径点数量 /// public int GetPathPointCount() { return currentPath.Count; } /// /// 获取路径总长度 /// public float GetPathLength() { if (currentPath.Count < 2) return 0f; float length = 0f; for (int i = 1; i < currentPath.Count; i++) { length += Vector3.Distance(currentPath[i - 1], currentPath[i]); } return length; } }