251 lines
6.4 KiB
C#
251 lines
6.4 KiB
C#
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
[RequireComponent(typeof(LineRenderer))]
|
||
public class GuideArrowPath : MonoBehaviour
|
||
{
|
||
[SerializeField] private LineRenderer lineRenderer; // 序列化字段,可以通过编辑器设置
|
||
|
||
// 新增:路径平滑参数
|
||
public float smoothSpeed = 5f;
|
||
private List<Vector3> targetPath = new List<Vector3>();
|
||
private List<Vector3> currentPath = new List<Vector3>();
|
||
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<LineRenderer>();
|
||
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<LineRenderer>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置路径(外部调用)
|
||
/// </summary>
|
||
public void SetPath(List<Vector3> path)
|
||
{
|
||
if (path == null || path.Count < 2)
|
||
return;
|
||
|
||
// 优化路径点数量
|
||
path = OptimizePathPoints(path);
|
||
|
||
// 设置目标路径
|
||
targetPath = new List<Vector3>(path);
|
||
|
||
// 如果当前没有路径,直接设置
|
||
if (currentPath.Count == 0)
|
||
{
|
||
currentPath = new List<Vector3>(targetPath);
|
||
UpdateLineRenderer(currentPath);
|
||
}
|
||
else
|
||
{
|
||
// 开始平滑过渡
|
||
isTransitioning = true;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 平滑过渡路径
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 优化路径点数量
|
||
/// </summary>
|
||
private List<Vector3> OptimizePathPoints(List<Vector3> path)
|
||
{
|
||
if (path.Count <= maxPathPoints)
|
||
return path;
|
||
|
||
List<Vector3> optimized = new List<Vector3>();
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新LineRenderer
|
||
/// </summary>
|
||
private void UpdateLineRenderer(List<Vector3> 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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 显示路径
|
||
/// </summary>
|
||
public void ShowPath()
|
||
{
|
||
if (lineRenderer != null)
|
||
lineRenderer.enabled = true;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏路径
|
||
/// </summary>
|
||
public void ClosePath()
|
||
{
|
||
if (lineRenderer != null)
|
||
lineRenderer.enabled = false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清理路径数据
|
||
/// </summary>
|
||
public void ClearPath()
|
||
{
|
||
targetPath.Clear();
|
||
currentPath.Clear();
|
||
isTransitioning = false;
|
||
|
||
if (lineRenderer != null)
|
||
{
|
||
lineRenderer.positionCount = 0;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前路径点数量
|
||
/// </summary>
|
||
public int GetPathPointCount()
|
||
{
|
||
return currentPath.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取路径总长度
|
||
/// </summary>
|
||
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;
|
||
}
|
||
} |