Files
Zombie/Assets/_Valheim/Scripts/Player/GuideArrowPath.cs
2025-12-03 11:25:14 +08:00

251 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Mirror;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class GuideArrowPath : NetworkBehaviour
{
[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;
}
}