Unity跨脚本传递Vector3列表后,对象完成首段路径后停止移动
问题分析与解决方案
核心问题
问题出在StartMoving和NextStep的交互逻辑上:
当完成第一段路径调用NextStep()时,会执行StartMoving(pathRover)。此时StartMoving第一行就是pathRover.Clear(),直接清空了当前剩余的路径点;之后尝试从已清空的pathReceived(也就是pathRover本身)中添加元素,自然得不到任何内容,最终pathRover.Count变为0,触发StopMoving()导致机器人停止。
修复方案
方案1:重构路径推进逻辑(推荐)
直接移除已完成的路径点,避免重复调用StartMoving时清空列表:
public List<Vector3> pathRover; [SerializeField] private float roverSpeed; [SerializeField] private float roverRotateSpeed; private float dotto; private bool isRotating = false; private bool isLerping = false; private Vector3 startPosition; private Vector3 targetPosition; private void FixedUpdate() { if (isRotating) { dotto = Vector3.Dot(transform.TransformDirection(Vector3.forward), (new Vector3(targetPosition.x, 0, targetPosition.z) - new Vector3(startPosition.x, 0, startPosition.z)).normalized); if (dotto < 0.98f) { transform.Rotate(0, Time.deltaTime * roverRotateSpeed, 0); } else { isLerping = true; isRotating = false; } } else if (isLerping) { var step = roverSpeed * Time.deltaTime; transform.position = Vector3.MoveTowards(transform.position, targetPosition, step); if (Vector3.Distance(transform.position, targetPosition) <= 1f) { NextStep(); } } } public void StartMoving(List<Vector3> pathReceived) { if (pathReceived.Count == 0) { StopMoving(); return; } pathRover.Clear(); foreach (var point in pathReceived) { pathRover.Add(point); } SetNextTarget(); } // 单独处理目标点设置逻辑 private void SetNextTarget() { if (pathRover.Count == 0) { StopMoving(); return; } startPosition = transform.position; var targetPoint = pathRover[0]; targetPosition = new Vector3(targetPoint.x, targetPoint.y + 0.7f, targetPoint.z); isRotating = true; } public void StopMoving() { isRotating = false; isLerping = false; pathRover.Clear(); } public void NextStep() { isLerping = false; // 移除已到达的路径点 pathRover.RemoveAt(0); SetNextTarget(); }
方案2:区分外部/内部调用(最小改动)
给StartMoving添加参数标记,避免内部调用时清空列表:
public void StartMoving(List<Vector3> pathReceived, bool isInternalCall = false) { if (pathReceived.Count <= 0) { StopMoving(); return; } // 仅外部传入路径时清空并复制 if (!isInternalCall) { pathRover.Clear(); foreach (var point in pathReceived) { pathRover.Add(point); } } if (pathRover.Count > 0) { startPosition = transform.position; targetPosition = new Vector3(pathRover[0].x, pathRover[0].y + 0.7f, pathRover[0].z); isRotating = true; } else { StopMoving(); } } public void NextStep() { isLerping = false; pathRover.RemoveAt(0); // 内部调用,跳过清空逻辑 StartMoving(pathRover, true); }
额外优化点
- 原代码中
pathReceived.Count > 1的判断不合理,应该允许路径只有一个点(直接移动到目标) - 可以将
Vector3.Distance的判断阈值改为更小的值(比如0.1f),避免因阈值过大导致提前触发下一步
内容的提问来源于stack exchange,提问作者RuviDot
相关产品推荐
相关产品推荐

