using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using XFramework.Objects; using XFramework; using UnityEngine.UI; public class PlanningPlaneCtrl : MonoBehaviour, IPointerDownHandler { public GameObject wayPointIcon; public GameObject line; public Transform wayPointParentTrans;//与地图大小完全一致的Panel 作为所有路点路径的父物体 便于管理 Dictionary> wayPointIcons = new Dictionary>();//线路路点图标 Dictionary> lineIcons = new Dictionary>();//线路路径图标 bool drawLine; WayType currentEditorLine; Color arriveColor; Color unArriveColor; NavMeshManager navMeshManager; // Start is called before the first frame update void Start() { navMeshManager = FindObjectOfType(); // StartDrawLine("首选", Color.green, Color.red); } //绘制路径 根据屏幕坐标 private void DrawPathFromScreenPoint(Vector2 point,Color lineColor) { Vector2 UIPos = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(this.GetComponent(), point, null, out UIPos);//将点击时鼠标的屏幕坐标转换为UI锚点坐标 GameObject newPoint = ObjectPool.Instance.Instantiate(wayPointIcon, wayPointParentTrans);//直接在点击的位置生成路点 //newPoint.transform.SetParent(wayPointParentTrans); newPoint.GetComponent().anchoredPosition = UIPos; newPoint.GetComponent().color = lineColor; if (wayPointIcons[currentEditorLine].Count > 0)//非首个路点生成路径线 { newPoint.gameObject.SetActive(true); newPoint.transform.localScale = this.transform.localScale * (1 / this.transform.localScale.x); Vector2 lastPointUIPos = wayPointIcons[currentEditorLine][wayPointIcons[currentEditorLine].Count - 1].GetComponent().anchoredPosition; float angle = Vector2.SignedAngle(UIPos - lastPointUIPos, Vector2.left); if (-angle > 90 || -angle < -90) angle += 180; Vector2 lineUIPos = (UIPos + lastPointUIPos) / 2; GameObject newLine = ObjectPool.Instance.Instantiate(line,Vector2.zero, Quaternion.AngleAxis(-angle, Vector3.forward), wayPointParentTrans);//生成路径 newLine.transform.localScale = Vector3.one /** (1 / this.transform.localScale.x)*/; newLine.GetComponent().anchoredPosition = lineUIPos; newLine.GetComponent().color = lineColor; float screenDistance = Vector2.Distance(UIPos, lastPointUIPos); //float mapPixel = screenDistance* this.transform.localScale.x; newLine.GetComponent().sizeDelta = new Vector2(screenDistance, 3 /** this.transform.localScale.x*/); lineIcons[currentEditorLine].Add(newLine); } else//首路点不显示 { newPoint.gameObject.SetActive(false); //navMeshManager.SetStartPos(new Vector3(worldPos.x, Terrain.activeTerrain.SampleHeight(worldPos), worldPos.y)); } wayPointIcons[currentEditorLine].Add(newPoint); } /// /// 学员端开启路径规划功能 并设置默认颜色 /// /// 可达路点的颜色 /// 不可达路点的颜色 public void StartDrawLine(WayType wayType,Color arriveColor,Color unArriveColor) { if (navMeshManager == null) { GameObject navGameObject = new GameObject("NavMesh"); navMeshManager = navGameObject.transform.GetOrAddComponent(); } currentEditorLine = wayType; this.arriveColor = arriveColor; this.unArriveColor = unArriveColor; if (!wayPointIcons.ContainsKey(wayType)) { wayPointIcons.Add(wayType, new List()); lineIcons.Add(wayType, new List()); } else if(wayPointIcons[wayType].Count>0)//再次开始编辑某一线路时 若该线路已经有路点 则将最后一个点位设置为寻路组件的起点 { Vector3 lastPointIconAnchoredPos = wayPointIcons[wayType][wayPointIcons[wayType].Count - 1].GetComponent().anchoredPosition; Vector3 worldPos = MapHelper.GetWorldPosFromAnchPos(lastPointIconAnchoredPos); navMeshManager.SetStartPos(worldPos); } drawLine = true; } //结束绘制 public void StopDrawLine() { drawLine = false; } //点击设置路点 当前所有路点均由鼠标确定 后续完善成由地形确定 public void OnPointerDown(PointerEventData eventData) { if (!drawLine) return; if (eventData.button == PointerEventData.InputButton.Left) { Vector2 pointIconLocaPostion = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(wayPointParentTrans.GetComponent(), eventData.position, null, out pointIconLocaPostion); Vector3 worldPos = MapHelper.GetWorldPosFromAnchPos(pointIconLocaPostion); if (wayPointIcons[currentEditorLine].Count <= 0)//首个路点执行 { SetFirstPoint(eventData.position, worldPos); } else { CheckNewPointAndDraw(eventData.position, worldPos); } } else if (eventData.button == PointerEventData.InputButton.Right) { RemoveLastPoint(); } } //检查路点可达性 并绘制线路 后续可完善为按照返回的路点绘制详细线路 private void CheckNewPointAndDraw(Vector2 mousePostion, Vector3 worldPos) { Vector3[] wayPoints = navMeshManager.SetTargetPointPostion(worldPos); //Debug.Log("wayPoints:"+wayPoints.Length); if (wayPoints == null) { DrawPathFromScreenPoint(mousePostion, unArriveColor); GameObject gameObject = new GameObject("unArrivePoint"); gameObject.transform.position = worldPos; } else //if (wayPoints.Length <= 200)//只返回两个路点时 无需增加中间点 暂不实现 { DrawPathFromScreenPoint(mousePostion, arriveColor); } //else //{ // for (int i = 1; i < wayPoints.Length-1; i++) // { // Vector2 anchoredPos = new Vector2(wayPoints[i].x, wayPoints[i].z) / mapScale - new Vector2(4096, 4096); // Debug.Log("计算出的锚点坐标:"+anchoredPos); // DrawPathFromLoaclAnchoredPoint(anchoredPos, arriveColor); // //Vector2 V2fromInScreen = RectTransformUtility.WorldToScreenPoint(Camera.main, from.transform.position); // } //} } //设置首个路点 默认首个路点一定可达 无需检测可达性 private void SetFirstPoint(Vector2 mousePostion, Vector3 worldPos) { navMeshManager.SetStartPos(worldPos); navMeshManager.transform.position = worldPos; DrawPathFromScreenPoint(mousePostion, arriveColor); } bool hasDefultPoint; //将首车位置设置为所有线路的默认起始位置点 public void SetDefultFirstPoint(Vector2 anchoredPostion) { Debug.Log(anchoredPostion); GameObject newPoint = ObjectPool.Instance.Instantiate(wayPointIcon, wayPointParentTrans); newPoint.GetComponent().anchoredPosition = anchoredPostion; newPoint.gameObject.SetActive(false); wayPointIcons.Add(WayType.备选, new List()); wayPointIcons[WayType.备选].Add(newPoint); lineIcons.Add(WayType.备选, new List()); wayPointIcons.Add(WayType.首选, new List()); wayPointIcons[WayType.首选].Add(newPoint); lineIcons.Add(WayType.首选, new List()); hasDefultPoint = true; } //移除最后一个路点和对应的路径 private void RemoveLastPoint() { int lastPointIndex = 0; if (hasDefultPoint)//有默认起始点时保留起始点位 需要清除默认点位时 另行开启接口 lastPointIndex = 1; if (wayPointIcons[currentEditorLine].Count > lastPointIndex) { ObjectPool.Instance.Destroy(wayPointIcons[currentEditorLine][wayPointIcons[currentEditorLine].Count - 1]); wayPointIcons[currentEditorLine].RemoveAt(wayPointIcons[currentEditorLine].Count - 1); } if (lineIcons[currentEditorLine].Count > 0) { ObjectPool.Instance.Destroy(lineIcons[currentEditorLine][lineIcons[currentEditorLine].Count - 1]); lineIcons[currentEditorLine].RemoveAt(lineIcons[currentEditorLine].Count - 1); Vector2 lastPointPos = wayPointIcons[currentEditorLine][wayPointIcons[currentEditorLine].Count - 1].GetComponent().anchoredPosition;//移除路径时更新路点位置 Debug.Log(lastPointPos); navMeshManager.SetStartPos(MapHelper.GetWorldPosFromAnchPos(lastPointPos)); } } /// /// 获取规划路径点世界坐标 /// /// public List GetPlaneWayPoints(WayType wayType, out string wayPointError) { List wayPointsWorldPostion = new List(); for (int i = 0; i < wayPointIcons[wayType].Count; i++) { wayPointsWorldPostion.Add(MapHelper.GetWorldPosFromAnchPos(wayPointIcons[wayType][i].GetComponent().anchoredPosition)); } if (wayPointsWorldPostion.Count > 0) wayPointError = null; else wayPointError = LocalizationManager.Format("未规划{0}线路", LocalizationManager.DisplayName(wayType.ToString())); return wayPointsWorldPostion; } /// /// 检查两条线路是否规划完毕 /// /// public string CheckPlanningFinished() { string error=""; if (!lineIcons.ContainsKey(WayType.首选)|| lineIcons[WayType.首选].Count < 0) error = LocalizationManager.Get("未规划首选线路"); if (!lineIcons.ContainsKey(WayType.备选) || lineIcons[WayType.备选].Count < 0) error = LocalizationManager.Get("未规划备选线路"); return error; } /// /// 获取当前规划的所有路径物体 /// /// public Dictionary> GetLines() { return lineIcons; } /// /// 教员端根据导调初始化数据绘制路径 /// /// key 路径类型 value.item.x y代表 某段线路锚点位置 z代表该段线路长度 public void DrawLine(Dictionary> lines) { foreach (var item in lines) { Color lineColor; if (item.Key == WayType.首选) lineColor = Color.green; else lineColor = Color.yellow; if (!lineIcons.ContainsKey(item.Key)) lineIcons.Add(item.Key, new List()); for (int i = 0; i < item.Value.Count; i++) { GameObject newLine = ObjectPool.Instance.Instantiate(line, wayPointParentTrans);//生成路径 RectTransform rectTransform = newLine.GetComponent(); rectTransform.anchoredPosition = item.Value[i].anchorPos.GetVector2(); rectTransform.localEulerAngles = new Vector3(0, 0, item.Value[i].angleZ); rectTransform.sizeDelta = new Vector2(item.Value[i].sizeX,3);//高度保持3个像素 长度以学员端传回的实际像素值为准 rectTransform.localScale = Vector3.one; newLine.GetComponent().color = lineColor; lineIcons[item.Key].Add(newLine); } } } /// /// 清空已经绘制的线路 /// public void Clear() { foreach (var item in wayPointIcons) { for (int i = 0; i < item.Value.Count; i++) { ObjectPool.Instance.Destroy(item.Value[i]); } } wayPointIcons.Clear(); foreach (var item in lineIcons) { for (int i = 0; i < item.Value.Count; i++) { ObjectPool.Instance.Destroy(item.Value[i]); } } lineIcons.Clear(); } } //路径类型 public enum WayType { 首选, 备选, }