using System.Collections; using System.Collections.Generic; using UnityEngine; using DevelopEngine; using XFramework; using System; using UnityEngine.EventSystems; //场景物体控制器 用于引用存储、获取、物体外部控制、厂区分配、统计需同步物体的位置并发送等逻辑 public class GameObjectManager : MonoSingleton { List Cars = new List(); List areaFlages = new List();//规划完成的一区九场 Dictionary> inAreaCarDic = new Dictionary>();//分配完所属区域的车辆 bool onLooked;//教员监视状态 float timer; Dictionary> allGOs = new Dictionary>();//所有待管理的对象 CarCtrl currentSelectCar;//当前选中的车辆 用于后期控制 public CarCtrlType ctrlType = CarCtrlType.AI; AdjustingCarIconData[] carIconMsgs;//待发送的车辆图标数据类 Surveyor rulerManager; private void Update() { if (onLooked) //同步模式下 同步位置信息 { GetCarsPosAndSend(); } RayHitMoveCar(); rulerManager?.Update(); } //获取点击事件 控制车辆移动 private void RayHitMoveCar() { if (EventSystem.current != null && EventSystem.current.IsPointerOverGameObject()) return; //射线检测时屏蔽UI部分 if (Cars.Count < 0) return; //无车辆时 不需要射线检测 if (Input.GetMouseButtonDown(0)) { RaycastHit hit;//鼠标射线检测 Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (Physics.Raycast(ray, out hit, 2000) && hit.collider.gameObject.layer == LayerMask.NameToLayer("Floor"))//只有点击到地面时才设置车辆位移 { SetCarMovePoints(hit.point); } } } //梳理车辆位置信息 发送到服务端 每0.5f发送一次同步位置信息 private void GetCarsPosAndSend() { if (Cars.Count < 0) return; timer += Time.unscaledTime; if (timer < 0.5f) return; timer = 0; if (carIconMsgs == null || carIconMsgs.Length != Cars.Count) { carIconMsgs = new AdjustingCarIconData[Cars.Count]; } for (int i = 0; i < Cars.Count; i++) { if (carIconMsgs[i] == null) carIconMsgs[i] = new AdjustingCarIconData(); carIconMsgs[i].carName = Cars[i].transform.name; Vector2 pos = Cars[i].iconBase_thisIcon.GetComponent().anchoredPosition; carIconMsgs[i].anchorPos = new VectorTwo(pos); carIconMsgs[i].angle = ((CarIconInstanceCtrl)Cars[i].iconBase_thisIcon).dir.transform.localEulerAngles.z; } TCPManager.Instance.SendNetMsg(carIconMsgs, NetMsgName.Syn); } //改变选中装备的展开状态 internal void ChangeCarOpening() { //throw new NotImplementedException(); currentSelectCar?.ChangeOpening(); } //修理所展开时 改变车辆控制方式为人员控制 注册展开事件 展开时分配所属分区 public void StartPersonCtrl() { ctrlType = CarCtrlType.Person; for (int i = 0; i < Cars.Count; i++) { Cars[i].ChangeCtrlType(CarCtrlType.Person); Cars[i].carOpenedEvent += CarOpened; Cars[i].transform.GetOrAddComponent().Event_ParamClick += Event_ParamClick; } CameraCtrl.Instance.AddGOEventSystem(); CameraCtrl.Instance.rightButtonEvent += RightButtonEvent; } //右键取消当前选中车辆的选中状态 private void RightButtonEvent() { if (currentSelectCar != null) { currentSelectCar.carStateChangedEvent -= ShowCarState;//取消车辆状态监视 currentSelectCar.IsSelect = false;//关闭车辆选中状态 ShowCarState(CarState.none);//情况车辆状态显示UI currentSelectCar = null;//清空选中车辆 } } //修理所展开科目时的 车辆选取事件 private void Event_ParamClick(GOEventSystem.GOPointerEventData data) { CarCtrl pointHitCar = data.pointerPress.GetComponentInParent(); if (pointHitCar == null) return; if (pointHitCar.OtherUserCtrl) return;//协同模式下他人正在控制的物体无法获取 if (currentSelectCar != pointHitCar)//选了一个新的车辆 { if (currentSelectCar != null)//当前已经选了一个车辆 { currentSelectCar.IsSelect = false; currentSelectCar.carStateChangedEvent -= ShowCarState;//取消对上一个选中车辆的状态监视事件 } currentSelectCar = pointHitCar; currentSelectCar.IsSelect = true; currentSelectCar.carStateChangedEvent += ShowCarState; ShowCarState(currentSelectCar.CarState);//选中车辆时显示车辆状态 Debug.Log(currentSelectCar.gameObject.name); } } //当前选中车辆的状态发生变化 private void ShowCarState(CarState carState) { GameMain.Instance.UIManager.ChangePanel("CarState",carState); } //车辆展开完毕时执行 为车辆分配所属区域 private void CarOpened(CarCtrl car) { DistributionAreaForOneCar(car); } //为当前选择车辆设置移动路点 private void SetCarMovePoints(Vector3 vector3) { if (currentSelectCar != null)//选择车辆后点击地面时 移动车辆 { currentSelectCar.SetWayPoints(new List() { vector3 }); } } //获取首车Trans public Transform GetFirstCar() { for (int i = 0; i < Cars.Count; i++) { if (Cars[i].carType == CarPosType.firstCar) return Cars[i].transform; } return null; } /// /// 教员开始监视或取消监视时执行 /// /// public void SetAdjustingState(bool isLooked) { this.onLooked = isLooked; } /// /// 注入待管理的对象 /// /// 待管理对象的类型 /// 带管理的对象 public void InjeectGO(ManagerGOTypes type, GameObject t,int id) { if (!allGOs.ContainsKey(type)) allGOs.Add(type, new Dictionary()); allGOs[type][id] = t; } ///// ///// 获取某类型的所有对象 ///// ///// 对象类型 //public GameObject[] GetGOs(ManagerGOTypes type) //{ // if (allGOs.ContainsKey(type)) // return allGOs[type].ToArray(); // return null; //} /// /// 删除突发事件检测器 /// public void DestoryTuFaGO(int id) { if (allGOs[ManagerGOTypes.tufa].ContainsKey(id)) { Destroy(allGOs[ManagerGOTypes.tufa][id].gameObject); allGOs[ManagerGOTypes.tufa].Remove(id); } else { Debug.Log($"不存在id为{id}的触发器,无需删除!"); } } //存储新建车辆 便于后续调用 按照排列顺序添加 public void SetNewCar(CarCtrl carCtrl) { if (Cars.Count > 0)//设置前一辆车为后车跟随对象 { carCtrl.SetFollowTarget(Cars[Cars.Count - 1].transform); } Cars.Add(carCtrl); } //重新为所有车辆规划所属厂区 public void DistributionAreaForCars() { for (int i = 0; i < Cars.Count; i++) { if (Cars[i].CarState == CarState.opened || Cars[i].CarState == CarState.openingAnim)//完成展开的/展开过程中的车辆规划厂区 未展开的不进行规划 { DistributionAreaForOneCar(Cars[i]); } } } //按照最近距离原则 为车辆分配所属厂区 private void DistributionAreaForOneCar(CarCtrl car) { string areaName = GetNearestDistanceArea(car.transform.position); if (!inAreaCarDic.ContainsKey(areaName)) inAreaCarDic.Add(areaName, new List()); inAreaCarDic[areaName].Add(car); car.SetArea(areaName); } //获取与车辆最近的厂区名称 private string GetNearestDistanceArea(Vector3 carPos) { float nearDistance = float.MaxValue; string nearFlageName = ""; for (int i = 0; i < areaFlages.Count; i++) { float currentDis = Vector3.Distance(carPos, areaFlages[i].transform.position); if (currentDis < nearDistance) { nearDistance = currentDis; nearFlageName = areaFlages[i].AreaName; } } return nearFlageName; } //记录完成位置规划的厂区 public void AddPlannedArea(AreaFlageCtrl area) { areaFlages.Add(area); inAreaCarDic.Add(area.AreaName, new List()); if (StudentStateManager.Instance.LearnState == LearnState.learning)//训练模式提示厂区规划距离是否合适 { string checkResult = EditorAppraiser.CheckAreaDistance(areaFlages);//先检查厂区之间的距离 if (!string.IsNullOrEmpty(checkResult))//厂区之间距离不符合要求 { GameMain.Instance.UIManager.ShowPromptText(checkResult, Color.blue); } else if(area.AreaName== AreaNameEnum.洗消场.ToString())//厂区间距符合要求 在继续检查是否是洗消场 { checkResult = EditorAppraiser.CheckAreaToWaterDistance(area.transform);//若是洗消场则继续检查距离水源的间距 if (!string.IsNullOrEmpty(checkResult))//洗消场与水源距离不符合要求 { GameMain.Instance.UIManager.ShowPromptText(checkResult, Color.blue); } } } } //重新规划时移除 public void RemoveArea(AreaFlageCtrl area) { if (areaFlages.Contains(area)) { areaFlages.Remove(area); inAreaCarDic.Remove(area.AreaName); } } //获取当前所有完成规划的厂区 public List GetAllAreas() { return areaFlages; } //改变当前棋子是否能够 捡起 public void ChangeAreaFlagePick(bool can) { Debug.Log($"当前旗子交互状态:{can}"); for (int i = 0; i < areaFlages.Count; i++) { areaFlages[i].ChangePicked(can); } } //获取当前所有厂区的车辆Trans规划汇总 若无车辆时存入区域标志Trans public Dictionary> GetAreaAndCars() { Dictionary> areaAndTransDic = new Dictionary>(); foreach (var item in inAreaCarDic) { List inAreaTrans = new List(); for (int i = 0; i < item.Value.Count; i++) { inAreaTrans.Add(item.Value[i].transform); } if (inAreaTrans.Count == 0)//未在厂区内部规划车辆 { inAreaTrans.Add(ArrayHelper.Find(areaFlages, (P) => P.AreaName == item.Key).transform);//将厂区Trans 加入 用于计算距离 } areaAndTransDic.Add(item.Key, inAreaTrans); } return areaAndTransDic; } //车队开始移动 public void StartAIMove() { for (int i = 0; i < Cars.Count; i++) { Cars[i].StartMove(); } } //车队结束移动 public void StopMove() { for (int i = 0; i < Cars.Count; i++) { Cars[i].StopMove(); } } //设置行军路径 车队首个元素为首车 public void SetWayPoints(List points) { Cars[0].SetWayPoints(points); } //获取所有的车辆 public List GetCarList() { return Cars; } ///// ///// 硬件控制当前选中的车辆 ///// //public void CtrlCarMove(float hor,float ver,float handBreak) //{ // currentSelectCar?.CarMove(hor, ver, handBreak); //} /// /// 改变测量状态 /// /// true 开始测量模式 false 关闭测量模式 public void ChangeCLState(bool isOn) { if (isOn)//开时测量 创建测量员 { rulerManager = new Surveyor(Resources.Load(ResourcesManager.GetPath("Ruler"))); } else//结束测量 销毁测量员 { rulerManager?.StopCL(); rulerManager = null; } } } /// /// 待管理的物体类型 /// public enum ManagerGOTypes { //行军车辆 car, //修理厂区域标志 areaFlag, //突发事件触发器 tufa, //VR模式下能看到的提示文字 vr3DText, }