using System; using System.Collections; using System.Collections.Generic; using AX.MessageSystem; using UnityEngine; using AX.InputSystem; using UnityEngine.AI; using AX.NetworkSystem; using System.Linq.Expressions.Reimplement; using System.Reflection; public class CloneStayingAreaTool : CloneBase//集结区调车时注意场景中是否还有名称显示的预设(TheHeadName) { [SerializeField] [Tooltip("距离地面距离")] protected float Height = 0; public float AreaPrefabSize; private List NowMyCarList; public List PosPoints;//集结区停放车辆点位总位置集合 public List HadPos = new List();//没有停车的空位 private CloneCmdArgs data; private CarMoveOutController Controller; private long AreaID; private int PosNum; public bool isGetedCars; public float SafeRange = 15f; public bool IsSafe; private List DangerousList = new List(); private Transform P_Disasters; private NavMeshQueryFilter filter; private NavMeshHit nhit; private GameObject WaterCarParent; Vector2 vLU; Vector2 vLD; Vector2 vRU; Vector2 vRD; Ray rayLU; Ray rayLD; Ray rayRU; Ray rayRD; RaycastHit HitLU; RaycastHit HitLD; RaycastHit HitRU; RaycastHit HitRD; public bool cloneAble;//true表示能克隆或停放;否则不行 void Awake() { NowMyCarList = new List(); P_Disasters = transform.parent.parent.Find("P_Disasters"); WaterCarParent = GameObject.Find("P_Cars").transform.Find("P_WaterTanker").gameObject; filter.agentTypeID = WaterCarParent.GetComponent().clonePrefab.GetComponent().agentTypeID; filter.areaMask = WaterCarParent.GetComponent().clonePrefab.GetComponent().areaMask; } public override void Execute(IMessage obj) { if (!isGetedCars) { GetMyCars(); isGetedCars = true; } if (transform.childCount > 0) { foreach (Transform t in transform) { if (t.GetComponent().UserID == CurrentUserInfo.mySelf.Id) return; } } var gameObjID = (long)obj.Sender; data = ((CloneCmdArgs)obj.Data); if (data.cloneObjType == cloneObjType) { var hitPoint = data.hitPos; CheckCloneAble(hitPoint); if (!cloneAble) { return; } Vector3 clonedObjPos = new Vector3(hitPoint.x, hitPoint.y + Height, hitPoint.z); var clonedObj = EntitiesManager.Instance.CreateObj(clonePrefab, clonedObjPos, transform, gameObjID); clonedObj.name = CloneObjNameTool.Instance().GetCloneObjectName(cloneObjType); SelectedObjs.gameObjs.Add(clonedObj); //设置克隆物体所在楼层等基本属性,属性从点击的对象上获取 var hitObj = EntitiesManager.Instance.GetEntityByID(data.gameObjID); CloneGameObjInfo hitObjInfo = hitObj.GetComponent(); CloneGameObjInfo cloneObjInfo = clonedObj.GetComponent(); cloneObjInfo.gameObjType = cloneObjType; cloneObjInfo.UserID = CurrentUserInfo.mySelf.Id; cloneObjInfo.buildNum = hitObjInfo.buildNum; cloneObjInfo.floorNum = hitObjInfo.floorNum; cloneObjInfo.interlayerNum = hitObjInfo.interlayerNum; AreaID = clonedObj.GetComponent().gameObjID; Controller = clonedObj.GetComponent(); //获取集结区停车位置,总共8个 PosPoints = GetPoints(data.hitPos, AreaPrefabSize / 2, 8); HadPos.Clear(); //停放车辆 SetMyCars(); //判断集结区位置是否在火灾下风向 GetDangerousList(clonedObjPos); //判断设置位置是否在下风向 if (!IsSafeJude(clonedObjPos)) { //发送错误报告同步信息 ReportErroeSyncData arg = new ReportErroeSyncData(); //if (GetComponent()) { arg.Time = TIME_SYNC.time; } arg.SendUserID = CurrentUserInfo.mySelf.Id; arg.errorset = CurrentUserInfo.role.ToString();//"集结区设置错误"; arg.describe = "集结区设置在火灾下风口"; NetworkManager.Default.SendAsync("REPORT_ERROR_SYNC", arg); } } } /// /// 检查当前克隆位置能否克隆集结区(或者当前位置能否停放集结区) /// /// public bool CheckCloneAble(Vector3 hitPoint) { vLU = Camera.main.WorldToScreenPoint(hitPoint + Vector3.left * AreaPrefabSize / 2 + Vector3.forward * AreaPrefabSize / 2); vLD = Camera.main.WorldToScreenPoint(hitPoint + Vector3.left * AreaPrefabSize / 2 + Vector3.back * AreaPrefabSize / 2); vRU = Camera.main.WorldToScreenPoint(hitPoint + Vector3.right * AreaPrefabSize / 2 + Vector3.forward * AreaPrefabSize / 2); vRD = Camera.main.WorldToScreenPoint(hitPoint + Vector3.right * AreaPrefabSize / 2 + Vector3.back * AreaPrefabSize / 2); rayLU = Camera.main.ScreenPointToRay(vLU); rayLD = Camera.main.ScreenPointToRay(vLD); rayRU = Camera.main.ScreenPointToRay(vRU); rayRD = Camera.main.ScreenPointToRay(vRD); if (Physics.Raycast(rayLU, out HitLU)) { //if (!(HitLU.transform.gameObject.layer == LayerMask.NameToLayer("CarRoad") && HitLU.transform.GetComponent())) if (NavMesh.SamplePosition(HitLU.point, out nhit, 0.5f, filter)) { if (Vector3.Distance(HitLU.point, nhit.position) > 0.2f) { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } else { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } if (Physics.Raycast(rayLD, out HitLD)) { if (NavMesh.SamplePosition(HitLD.point, out nhit, 0.5f, filter)) { if (Vector3.Distance(HitLD.point, nhit.position) > 0.2f) { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } else { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } if (Physics.Raycast(rayRU, out HitRU)) { if (NavMesh.SamplePosition(HitRU.point, out nhit, 0.5f, filter)) { if (Vector3.Distance(HitRU.point, nhit.position) > 0.2f) { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } else { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } if (Physics.Raycast(rayRD, out HitRD)) { if (NavMesh.SamplePosition(HitRD.point, out nhit, 0.5f, filter)) { if (Vector3.Distance(HitRD.point, nhit.position) > 0.2f) { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } else { LoadPromptWin.Instance.LoadTextPromptWindow("当前位置无法设置集结区!", 0.5f); cloneAble = false; return cloneAble; } } return cloneAble = true; } private void GetMyCars() { //if (GameSettings.othersSettings.mode == Mode.manoeuvre) //{ // if (GameSettings.othersSettings.CarList.Count > 0) // foreach (var item in GameSettings.othersSettings.CarList) // { // if (NowMyCarList.Count > 0) // { // for (int i = 0; i < NowMyCarList.Count; i++) // { // if (!NowMyCarList.Contains(item.Key)) // { // NowMyCarList.Add(item.Key); // break; // } // } // } // else // { // NowMyCarList.Add(item.Key); // } // } //} //if (GameSettings.othersSettings.mode == Mode.Practice) //{ if (GameSettings.othersSettings.CarList.Count > 0) { foreach (var item in GameSettings.othersSettings.CarList) { for (int i = 0; i < item.Value; i++) { FireCarEngine car = DeepCopyByReflection(item.Key); NowMyCarList.Add(car); } } // 演习模式单独处理车辆载人数 if (GameSettings.othersSettings.mode == Mode.manoeuvre) { // if(GameSettings.othersSettings.personNum >0) { int carnum = 0; foreach (var item in GameSettings.othersSettings.CarList) { carnum += item.Value; } int[] PersonNum = new int[carnum]; int nowperson = GameSettings.othersSettings.personNum; while (nowperson > 0) { for (int i = 0; i < NowMyCarList.Count; i++) { if (nowperson > 0 && PersonNum[i] < NowMyCarList[i].PassengerCapacity) { PersonNum[i] += 1; nowperson--; } } } for (int i = 0; i < NowMyCarList.Count; i++) { NowMyCarList[i].PassengerCapacity = PersonNum[i]; } for (int i = 0; i < PersonNum.Length; i++) { NowMyCarList[i].PassengerCapacity = PersonNum[i]; Debug.Log(NowMyCarList[i].PassengerCapacity); } } } } //} } //用来显示收到新调派的车辆 public void ReceiveNewCars(List NewCars) { List deepnewcars = new List(); for (int i = 0; i < NewCars.Count; i++) { FireCarEngine car = DeepCopyByReflection(NewCars[i]); deepnewcars.Add(car); } //演练模式单独处理当前客户端车辆载人数 if (GameSettings.othersSettings.mode == Mode.manoeuvre) { int nowperson = GameSettings.othersSettings.nowperson; if (nowperson > 0) { int[] PersonNum = new int[deepnewcars.Count]; while (nowperson > 0) { for (int i = 0; i < deepnewcars.Count; i++) { if (nowperson > 0 && PersonNum[i] < deepnewcars[i].PassengerCapacity) { PersonNum[i] += 1; nowperson--; } } } for (int i = 0; i < deepnewcars.Count; i++) { deepnewcars[i].PassengerCapacity = PersonNum[i]; } } } foreach (var NewCar in deepnewcars) { NowMyCarList.Add(NewCar); } if (Controller == null)//没有克隆集结区直接返回 return; //if (Controller.PosList.Count == 0)//集结区没有车了 //{ // SetMyCars(); // return; //} while (HadPos.Count > 0 && NowMyCarList.Count > 0) { FillCarSpace(); } //while (Controller.PosList.Count < PosNum && NowMyCarList.Count > 0) //{ // if (Controller.PosList.Count == 0)//车辆都不在集结区了重新刷出车辆 // { // //SetMyCars(NowMyCarList.Count > PosNum ? PosNum : NowMyCarList.Count); // } // else // { // List PosList = GetPoints(data.hitPos, AreaPrefabSize / 2, PosNum); // foreach (var pos in PosList) // { // if (!Controller.PosList.Contains(pos)) // { // FillCarSpace();//空点位点出车 // break; // } // } // } //} } /// /// 空位出车 /// public void FillCarSpace() { if (NowMyCarList.Count > 0) { CloneCmdArgs arg = new CloneCmdArgs(); arg.gameObjID = AreaID; arg.cloneObjType = (CloneObjType)NowMyCarList[0].Type; arg.hitPos = HadPos[0]; arg.fireCarEngine = NowMyCarList[0]; long Id = EntitiesManager.Instance.CreateObjID(CurrentUserInfo.mySelf.Id); CloneCommand.Instance.Execute(Id, arg); NowMyCarList.Remove(NowMyCarList[0]); Controller.PosList.Add(HadPos[0]); HadPos.RemoveAt(0); } } //克隆车的控制 public void SetMyCars() { Controller.tool = this; int j = 0; for (; ; ) { if (j > 7 || NowMyCarList.Count == 0) break; CloneCmdArgs arg = new CloneCmdArgs(); arg.gameObjID = AreaID; arg.cloneObjType = (CloneObjType)NowMyCarList[0].Type; arg.hitPos = PosPoints[j]; Controller.PosList.Add(PosPoints[j]); arg.fireCarEngine = NowMyCarList[0]; if (GameSettings.othersSettings.mode == Mode.manoeuvre) { arg.fireCarEngine.PassengerCapacity = NowMyCarList[0].PassengerCapacity; } long Id = EntitiesManager.Instance.CreateObjID(CurrentUserInfo.mySelf.Id); CloneCommand.Instance.Execute(Id, arg); NowMyCarList.Remove(NowMyCarList[0]); j++; } for (int i = j; i < PosPoints.Count; i++) { HadPos.Add(PosPoints[i]); } } //集结区点位,目前最大是8 private List GetPoints(Vector3 centerPoint, float radius, int num) { List ResultList = new List(); switch (num) { case 1: ResultList.Add(centerPoint); break; case 2: ResultList.Add(centerPoint + Vector3.left * radius / 3); ResultList.Add(centerPoint + Vector3.right * radius / 3); break; case 3: ResultList.Add(centerPoint); ResultList.Add(centerPoint + Vector3.left * radius / 2); ResultList.Add(centerPoint + Vector3.right * radius / 2); break; case 4: ResultList.Add(centerPoint + Vector3.left * radius / 4); ResultList.Add(centerPoint + Vector3.right * radius / 4); ResultList.Add(centerPoint + Vector3.left * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 1.2f); break; case 5: ResultList.Add(centerPoint); ResultList.Add(centerPoint + Vector3.right * radius / 1.2f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 1.2f + Vector3.back * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 1.2f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 1.2f + Vector3.back * radius / 1.2f); break; case 6: ResultList.Add(centerPoint + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.back * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 1.5f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 1.5f + Vector3.back * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 1.5f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 1.5f + Vector3.back * radius / 1.2f); break; case 7: ResultList.Add(centerPoint); ResultList.Add(centerPoint + Vector3.right * radius / 3f); ResultList.Add(centerPoint + Vector3.right * radius + Vector3.forward * radius); ResultList.Add(centerPoint + Vector3.right * radius + Vector3.back * radius); ResultList.Add(centerPoint + Vector3.left * radius / 3f); ResultList.Add(centerPoint + Vector3.left * radius + Vector3.forward * radius); ResultList.Add(centerPoint + Vector3.left * radius + Vector3.back * radius); break; case 8: ResultList.Add(centerPoint + Vector3.left * radius / 4f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 4f + Vector3.back * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 4f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 4f + Vector3.back * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 1.3f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.left * radius / 1.3f + Vector3.back * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 1.3f + Vector3.forward * radius / 1.2f); ResultList.Add(centerPoint + Vector3.right * radius / 1.3f + Vector3.back * radius / 1.2f); break; } return ResultList; } /// /// 克隆点周围火灾列表 /// /// void GetDangerousList(Vector3 setpos) { float Helfdiagonal = Mathf.Sqrt(2) * (AreaPrefabSize / 2); DangerousList.Clear(); CloneGameObjInfo[] allDisaster = P_Disasters.GetComponentsInChildren(); for (int i = 0; i < allDisaster.Length; i++) { if ( allDisaster[i].gameObjType == CloneObjType.fireNormal || allDisaster[i].gameObjType == CloneObjType.LiquidLevel) { if (allDisaster[i].gameObjType == CloneObjType.fireNormal) { //普通火,计算普通火到集结区对角线一半的距离 if (Vector3.Distance(setpos, allDisaster[i].transform.position) < (SafeRange + Helfdiagonal)) { DangerousList.Add(allDisaster[i].gameObject); } } if (allDisaster[i].gameObjType == CloneObjType.LiquidLevel) { //如果是全液面火 long guanID = allDisaster[i].GetComponent().TargetNormalID; if (EntitiesManager.Instance.GetEntityByID(guanID) && EntitiesManager.Instance.GetEntityByID(guanID).GetComponent()) { OilTankMessage msg = EntitiesManager.Instance.GetEntityByID(guanID).GetComponent(); float direction = msg.Tank_D; Vector3 tankpos = new Vector3(msg.transform.position.x, setpos.y + Height, transform.position.z); if (Vector3.Distance(setpos, tankpos) < (SafeRange + Helfdiagonal + direction / 2)) { DangerousList.Add(allDisaster[i].gameObject); } } else { Debug.LogError("找不到Id为" + guanID + "的油罐或者油罐上没有OilTankMessage"); } } } } } /// /// 判断集结区是否在下风向 /// /// private bool IsSafeJude(Vector3 setpos) { bool safe = true; GameObject wind = GameObject.Find("WindZone"); if (wind.GetComponent().windMain <= 0) { safe = true; } else//设置了风力 { if (DangerousList.Count <= 0) { safe = true; } else//防止范围内有火灾 { Vector3 windNormal = wind.transform.forward.normalized;//风向 for (int i = 0; i < DangerousList.Count; i++) { Vector3 pos_fire = DangerousList[i].transform.position - setpos;//集结区-火的向量 Vector2 xoz = new Vector2(pos_fire.x, pos_fire.z);//集结区-火的向量 的xoz平面向量 float dot_vec2 = Vector2.Dot(xoz, new Vector2(windNormal.x, windNormal.z));//该向量与风向的点成 if (dot_vec2 > 0) { safe = false; break; } } //Vector3 verticalNormal = Vector3.Cross(windNormal, Vector3.up).normalized;//风向垂直方向 //float Slope = verticalNormal.z / verticalNormal.x;//斜率 //float intercept = setpos.z - Slope * setpos.x;//截距 ////集结区的中心点所在直线方程为:y=slope*x+intercept //for (int i = 0; i < DangerousList.Count; i++) //{ // float y = Slope * DangerousList[i].transform.position.x + intercept + Mathf.Sqrt(2) * (AreaPrefabSize / 2); // if (y < DangerousList[i].transform.position.z) // { // safe = false; // } //} } } return safe; } public static T DeepCopyByReflection(T obj) { if (obj is string || obj.GetType().IsValueType) return obj; object retval = Activator.CreateInstance(obj.GetType()); FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); foreach (var field in fields) { try { field.SetValue(retval, DeepCopyByReflection(field.GetValue(obj))); } catch { } } return (T)retval; } }