using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using AX.TrackRecord; using AX.MessageSystem; using System.Linq; using UnityEngine.AI; public class XiaoFangYuanDrawLine : MonoBehaviour { // Use this for initialization public GameObject cloneObj; public GameObject nullobject; private GameObject prlineObj; public GameObject Line;//管线模型 public GameObject Zhaomingxian;//照明线模型 public GameObject Guanxian;//管线模型 private Vector3 placementPos;//第一碰撞点 private Vector3 placementPos2;//第二碰撞点 private Vector3[] nowpath; private Vector3[] newpath; private float timer = 0; private bool IsFirstPFFlag = false;//该记录的第一次寻路标志,开始记录时赋值true private UnityEngine.AI.NavMeshPath NavMeshPath; public List Allpath = new List();//关键点 public List AllLine = new List();//水带、照明线 public List AllLineDistance = new List();//水带长度 private int pointIndex = 1; private bool flag; float time; float allLineDistance;//可用管线长度(管线总长减别人已用的长度) float drawLineDistance;//已用管线长度 float DifferenceLine;//管线超出长度 private int MultipleSpeed=1;//回放播放倍数 void Awake() { NavMeshPath = new NavMeshPath(); TheBackView.instance.SpeedChangeEvent += OnSpeedChangeEvent; MultipleSpeed = LoadManager.Instance.speedFactor; } void Start() { //string name = this.name + "drawline"; string name_ = "TeamName-drawline-Zhaomingxian-" + this.name; if (!GameObject.Find(name_)) { prlineObj = Instantiate(nullobject) as GameObject; prlineObj.name = name_; prlineObj.transform.parent = GameObject.Find("pdrawline").transform; prlineObj.AddComponent();//用来记录删除消防管线 } else { prlineObj = GameObject.Find(name_); } } void OnDestroy() { TheBackView.instance.SpeedChangeEvent -= OnSpeedChangeEvent; } /// /// 找到当前最靠近的Index点 /// /// /// /// private int GetNearest(List nowpath, Vector3 point) { int index = 0; var result = (from x in nowpath select new { Key = x, Value = Vector3.Distance(point, x), Index = index++ }) .OrderBy(x => x.Value).Take(Mathf.Min(1, nowpath.Count)); // 太多了,按照接近程度 take 10 个。 index = result.ToList()[0].Index; return index; } private bool IsPointOnSegment(Vector3 Pi, Vector3 Pj, Vector3 Q) { if ((Q.x - Pi.x) * (Pj.z - Pi.z) == (Pj.x - Pi.x) * (Q.z - Pi.z) //叉乘 && Mathf.Min(Pi.x, Pj.x) <= Q.x && Q.x <= Mathf.Max(Pi.x, Pj.x)//保证Q点坐标在pi,pj之间 && Mathf.Min(Pi.z, Pj.z) <= Q.y && Q.y <= Mathf.Max(Pi.z, Pj.z)) return true; else return false; } // Update is called once per frame void /*Fixed*/Update() { if (!HasLine()) { nowpath = null; return; } drawLine(); time += Time.deltaTime; if (time >= 0.5f/ MultipleSpeed)//间隔0.5秒重新规划下管线 { time = 0.0f; if (nowpath != null && pointIndex < nowpath.Length&&GetComponent().velocity.magnitude>0)//只有移动的时候需要纠正路线 { changeLine(); } else if (flag)//寻路停止后再纠正一下管线位置 { changeLine(); flag = false; } } } private void drawLine() { if (nowpath != null) { if (Allpath.Count == 0) { Allpath.Add(nowpath[0]); } for (int i = pointIndex; i < nowpath.Length; i++) { if (Vector3.Distance(transform.position, nowpath[i]) < 1.0f) { placementPos = nowpath[i - 1]; placementPos2 = nowpath[i]; pointIndex = i + 1; Allpath.Add(placementPos2); } } } } private void changeLine() { //float dis = Allpath.Count == 0 ? 0.0f : Vector3.Distance(transform.position, Allpath[Allpath.Count - 1]); if (!getDistance()) { if (this.GetComponent().enabled) { this.GetComponent().StopAllCoroutines(); this.GetComponent().enabled = false; this.GetComponent().enabled = false; this.transform.position = correctLine(); //this.GetComponent().positionjiuzheng = true; this.GetComponent().enabled = true; this.GetComponent().enabled = true; nowpath = null;//停止画线 return; } else { this.GetComponent().enabled = true; this.GetComponent().StopAllCoroutines(); this.GetComponent().enabled = false; this.GetComponent().enabled = false; this.transform.position = correctLine(); //this.GetComponent().positionjiuzheng = true; this.GetComponent().enabled = true; nowpath = null;//停止画线 } } if (Allpath.Count == 0) { if (GetComponent().velocity.magnitude>0) { MessageDispatcher.SendMessage("Operatinghints", (object)"水带长度不足,请装备水带"); } return; } else if (Allpath.Count == 1) { for (int i = AllLine.Count - 1; i >= 0; i--) { if (GameObject.Find(AllLine[i])) { Destroy(GameObject.Find(AllLine[i])); //NetworkManager.Instance.Send("ENTITY_DESTROY", AllLine[i]); } AllLine.RemoveAt(i); //if(i< AllLineDistance.Count - 1) //{ AllLineDistance.RemoveAt(i); //} } NavMeshPath.ClearCorners(); try { //计算范围外距离最近的关键点和当前位置的平滑路径 UnityEngine.AI.NavMesh.CalculatePath(Allpath[0], transform.position, -1, NavMeshPath); } catch (Exception e) { System.Diagnostics.Trace.TraceError(e.Message); } //根据生成的关键点画线 newpath = NavMeshPath.corners; for (int k = 1; k < newpath.Length; k++) { placementPos = newpath[k - 1]; placementPos2 = newpath[k]; Vector3 tempPos = (placementPos + placementPos2) / 2;//计算两个点的中点坐标, cloneObj = Instantiate(Line, tempPos, Quaternion.identity) as GameObject; var LineMsg = cloneObj.GetComponent(); //LineMsg.MessageInit(); //LineMsg.userID = DeptList.UserID; //LineMsg.roleName = DeptList.RoleName; LineMsg.objectNum = BandLineMessage.Num; LineMsg.objectType = "drawline"; //LineMsg.parentName = prlineObj.name; cloneObj.GetComponent().cengID = this.GetComponent().cengID; cloneObj.GetComponent().CengIDBuildType = this.GetComponent().CengIDBuildType; //cloneObj.name = LineMsg.objectType + LineMsg.objectNum; cloneObj.name = "TeamName-" + LineMsg.objectType + "-" + "Zhaomingxian-" + LineMsg.objectNum; cloneObj.transform.parent = prlineObj.transform; cloneObj.transform.forward = (cloneObj.transform.position - placementPos).normalized;//改变线条的朝向 float distance = Vector3.Distance(placementPos, placementPos2);//计算两点的距离 cloneObj.transform.localScale = new Vector3(6f, 6f, distance * 10.75f);//延长线条,连接两点。 //cloneObj.AddComponent("DrawLineSync"); Allpath.Add(placementPos2); AllLine.Add(cloneObj.name); AllLineDistance.Add(distance); } } else if (Allpath.Count >= 2) { float dis = Vector3.Distance(transform.position, Allpath[Allpath.Count - 1]); for (int i = Allpath.Count - 1; i >= 1; i--) { //实际有效点是 i-1 dis += Vector3.Distance(Allpath[i], Allpath[i - 1]); if (dis > 10.0f) { //倒序删除范围内的活动关键点 for (int j = Allpath.Count - 1; j >= i; j--) { Allpath.RemoveAt(j); } for (int j = AllLine.Count - 1; j >= i - 1; j--)//这里分开循环是因为Allpath,AllLine的长度并不是一直相同的 { if (GameObject.Find(AllLine[j])) { Destroy(GameObject.Find(AllLine[j])); //NetworkManager.Instance.Send("ENTITY_DESTROY", AllLine[j]); } AllLine.RemoveAt(j); //if (j < AllLineDistance.Count - 1) //{ AllLineDistance.RemoveAt(j); //} } NavMeshPath.ClearCorners(); try { //计算范围外距离最近的关键点和当前位置的平滑路径 UnityEngine.AI.NavMesh.CalculatePath(Allpath[i - 1], transform.position, -1, NavMeshPath); } catch (Exception e) { System.Diagnostics.Trace.TraceError(e.Message); } //根据生成的关键点画线 newpath = NavMeshPath.corners; for (int k = 1; k < newpath.Length; k++) { placementPos = newpath[k - 1]; placementPos2 = newpath[k]; Vector3 tempPos = (placementPos + placementPos2) / 2;//计算两个点的中点坐标, cloneObj = Instantiate(Line, tempPos, Quaternion.identity) as GameObject; var LineMsg = cloneObj.GetComponent(); //LineMsg.MessageInit(); //LineMsg.userID = DeptList.UserID; //LineMsg.roleName = DeptList.RoleName; LineMsg.objectNum = BandLineMessage.Num; LineMsg.objectType = "drawline"; //LineMsg.parentName = prlineObj.name; cloneObj.GetComponent().cengID = this.GetComponent().cengID; cloneObj.GetComponent().CengIDBuildType = this.GetComponent().CengIDBuildType; //cloneObj.name = LineMsg.objectType + LineMsg.objectNum; cloneObj.name = "TeamName-" + LineMsg.objectType + "-" + "Zhaomingxian-" + LineMsg.objectNum; cloneObj.transform.parent = prlineObj.transform; cloneObj.transform.forward = (cloneObj.transform.position - placementPos).normalized;//改变线条的朝向 float distance = Vector3.Distance(placementPos, placementPos2);//计算两点的距离 cloneObj.transform.localScale = new Vector3(6f, 6f, distance * 10.75f);//延长线条,连接两点。 //cloneObj.AddComponent("DrawLineSync"); Allpath.Add(placementPos2); AllLine.Add(cloneObj.name); AllLineDistance.Add(distance); } break; } else if (i == 1)//从起点到现在位置都没超过限定距离 { for (int j = Allpath.Count - 1; j > 0; j--) { Allpath.RemoveAt(j);//删除除起点外的所有点 } for (int j = AllLine.Count - 1; j >= 0; j--) { if (GameObject.Find(AllLine[j])) { Destroy(GameObject.Find(AllLine[j])); //NetworkManager.Instance.Send("ENTITY_DESTROY", AllLine[j]); } AllLine.RemoveAt(j);//删除所有线 //if (j < AllLineDistance.Count - 1) //{ AllLineDistance.RemoveAt(j); //} } NavMeshPath.ClearCorners(); try { //计算范围外距离最近的关键点和当前位置的平滑路径 UnityEngine.AI.NavMesh.CalculatePath(Allpath[0], transform.position, -1, NavMeshPath); } catch (Exception e) { System.Diagnostics.Trace.TraceError(e.Message); } //根据生成的关键点画线 newpath = NavMeshPath.corners; for (int k = 1; k < newpath.Length; k++) { placementPos = newpath[k - 1]; placementPos2 = newpath[k]; Vector3 tempPos = (placementPos + placementPos2) / 2;//计算两个点的中点坐标 cloneObj = Instantiate(Line, tempPos, Quaternion.identity) as GameObject; var LineMsg = cloneObj.GetComponent(); //LineMsg.MessageInit(); //LineMsg.userID = DeptList.UserID; //LineMsg.roleName = DeptList.RoleName; LineMsg.objectNum = BandLineMessage.Num; LineMsg.objectType = "drawline"; //LineMsg.parentName = prlineObj.name; cloneObj.GetComponent().cengID = this.GetComponent().cengID; cloneObj.GetComponent().CengIDBuildType = this.GetComponent().CengIDBuildType; //cloneObj.name = LineMsg.objectType + LineMsg.objectNum; cloneObj.name = "TeamName-" + LineMsg.objectType + "-" + "Zhaomingxian-" + LineMsg.objectNum; cloneObj.transform.parent = prlineObj.transform; cloneObj.transform.forward = (cloneObj.transform.position - placementPos).normalized;//改变线条的朝向 float distance = Vector3.Distance(placementPos, placementPos2);//计算两点的距离 cloneObj.transform.localScale = new Vector3(6f, 6f, distance * 10.75f);//延长线条,连接两点。 //cloneObj.AddComponent("DrawLineSync"); Allpath.Add(placementPos2); AllLine.Add(cloneObj.name); AllLineDistance.Add(distance); } } } } setLineXiaoHao(); } public void setLine() { var task = GetComponent().TaskName; if (task.Contains("灭火") || task.Contains("掩护") || task.Contains("铺设水带") || task.Contains("洗消")) { Line = Guanxian; } else if (task.Contains("铺设照明线")) { Line = Zhaomingxian; } } public void setPath(Vector3[] path) { setLine(); Debug.Log(Line.name); nowpath = path; pointIndex = 1; flag = true; } /// /// 判断是否携带了管线和照明线 /// /// public bool HasLine() { float disLine = 0.0f;//携带管线长 float disZhaoMingXian = 0.0f;//携带照明线长 GameObject obj; //List AllMembers = this.GetComponent().AllMembers; //List AllMembers = InputManager.Instance_.GetSelectedCharacters(); List AllMembers = GetComponent().xfyList; for (int i = 0; i < AllMembers.Count; i++) { obj = AllMembers[i]; if (obj && obj.name.Contains("xiaofangyuan")) { disLine += obj.GetComponent().getHaveLine(); disZhaoMingXian += obj.GetComponent().getHaveZhaoMingXian(); } } if (Line.name.Equals(Guanxian.name)) { if (disLine < 0.5f) { return false; } } else if (Line.name.Equals(Zhaomingxian.name)) { if (disZhaoMingXian < 0.5f) { return false; } } return true; } /// /// 判断消防员携带水带是否还有剩余 /// /// private bool getDistance() { bool flag = true; allLineDistance = getAllLine(); drawLineDistance = getDrawLine(); if (allLineDistance < 0)//allLineDistance < drawLineDistance {//可用管线<0 flag = false; //DifferenceLine = drawLineDistance - allLineDistance;//超出可用范围长度 DifferenceLine = Mathf.Abs(allLineDistance);//超出可用范围长度 } return flag; } //获取该消防员可用的管线、照明线长度 private float getAllLine() { float dis = 0.0f; float disLine = 0.0f;//携带管线长 float disZhaoMingXian = 0.0f;//携带照明线长 float disDraw = 0.0f;//已用长度 GameObject obj; List AllMembers = this.GetComponent().AllMembers; for (int i = 0; i < AllMembers.Count; i++) { obj = AllMembers[i]; disLine += obj.GetComponent().getHaveLine(); disZhaoMingXian += obj.GetComponent().getHaveZhaoMingXian(); disDraw += obj.GetComponent().getDrawLine(); } //dis = disLine > disZhaoMingXian ? disZhaoMingXian : disLine;//取最短值作为管线可用长度 //dis -= disDraw; //dis += this.GetComponent().getDrawLine(); //if (dis>getHaveZhaoMingXian()) //{ // dis = getHaveZhaoMingXian(); // MessageDispatcher.SendMessage("Operatinghints", (object)"水带长度不足,请装备水带"); //} //Debug.Log("可用照明线长度为:" + dis+"携带照明线的长度为:"+getHaveZhaoMingXian()); if (Line.name.Equals(Guanxian.name)) { dis = disLine - disDraw; } else if (Line.name.Equals(Zhaomingxian.name)) { dis = disZhaoMingXian - disDraw; } return dis; } //获取该消防员已用的管线长度 public float getDrawLine() { float dis = 0.0f; Debug.Log("AllLineDistance.Count" + AllLineDistance.Count); for (int i = 0; i < AllLineDistance.Count; i++) { dis += AllLineDistance[i]; } Debug.Log(dis); return dis; } //获取该消防员携带的管线长度 public float getHaveLine() { float dis = 0.0f; Dictionary costSelectedEquips = this.GetComponent().costSelectedEquips; foreach (var item in costSelectedEquips) { if (item.Key.Contains("消防高压水带")) { dis = item.Value.selectedEquipNum * item.Value.unit; } } return dis; } //获取该消防员携带的照明线长度 public float getHaveZhaoMingXian() { float dis = 0.0f; Dictionary costSelectedEquips = this.GetComponent().costSelectedEquips; foreach (var item in costSelectedEquips) { if (item.Key.Contains("救生照明线")) { dis = item.Value.selectedEquipNum * item.Value.unit; } } return dis; } //管线超出可用管线范围纠正方法 private Vector3 correctLine() { //int k = 0; Vector3 pos = new Vector3(); float dis = 0; for (int i = AllLineDistance.Count - 1; i >= 0; i--) { //倒序找出应该回退到第几条线上 dis += AllLineDistance[i]; if (dis >= DifferenceLine) { float ab = dis - DifferenceLine; float x = Allpath[i].x + (Allpath[i + 1].x - Allpath[i].x) * ab / AllLineDistance[i]; float y = Allpath[i].y + (Allpath[i + 1].y - Allpath[i].y) * ab / AllLineDistance[i]; float z = Allpath[i].z + (Allpath[i + 1].z - Allpath[i].z) * ab / AllLineDistance[i]; pos = new Vector3(x, y, z);//算出回退后消防员所在位置 //倒序删除多出的关键点和线 for (int j = Allpath.Count - 1; j >= i + 1; j--) { Allpath.RemoveAt(j); } for (int j = AllLine.Count - 1; j >= i; j--)//这里分开循环是因为Allpath,AllLine的长度并不是一直相同的 { if (GameObject.Find(AllLine[j])) { Destroy(GameObject.Find(AllLine[j])); //NetworkManager.Instance.Send("ENTITY_DESTROY", AllLine[j]); } AllLine.RemoveAt(j); //if(j< AllLineDistance.Count - 1) //{ AllLineDistance.RemoveAt(j); //} } //将删除后最后一个点和消防员新位置连点成线 placementPos = Allpath[i]; placementPos2 = pos; Vector3 tempPos = (placementPos + placementPos2) / 2;//计算两个点的中点坐标 cloneObj = Instantiate(Line, tempPos, Quaternion.identity) as GameObject; var LineMsg = cloneObj.GetComponent(); //LineMsg.MessageInit(); //LineMsg.userID = DeptList.UserID; //LineMsg.roleName = DeptList.RoleName; LineMsg.objectNum = BandLineMessage.Num; LineMsg.objectType = "drawline"; //LineMsg.parentName = prlineObj.name; cloneObj.GetComponent().cengID = this.GetComponent().cengID; cloneObj.GetComponent().CengIDBuildType = this.GetComponent().CengIDBuildType; cloneObj.name = LineMsg.objectType + LineMsg.objectNum; cloneObj.transform.parent = prlineObj.transform; cloneObj.transform.forward = (cloneObj.transform.position - placementPos).normalized;//改变线条的朝向 float distance = Vector3.Distance(placementPos, placementPos2);//计算两点的距离 cloneObj.transform.localScale = new Vector3(6f, 6f, distance * 10.75f);//延长线条,连接两点。 //cloneObj.AddComponent("DrawLineSync"); Allpath.Add(placementPos2); AllLine.Add(cloneObj.name); AllLineDistance.Add(distance); break; } } return pos; } /// /// 消耗为0时,执行该方法即可将消耗重置,已使用数量标记为0 /// 消耗不为0时,即为计算消耗 /// private void setLineXiaoHao() { float dis = 0.0f; float disLine = 0.0f;//管线长 float disZhaoMingXian = 0.0f;//照明线长 GameObject obj; //List AllMembers = this.GetComponent().AllMembers; List AllMembers = GetComponent().xfyList;//使用该数组计算管线消耗,确保室外寻路也会消耗管线 for (int i = 0; i < AllMembers.Count; i++)//计算出总消耗量 { obj = AllMembers[i]; dis += obj.GetComponent().getDrawLine(); } Debug.Log(dis); if (Line.name.Equals(Guanxian.name)) { disLine = dis; } else if (Line.name.Equals(Zhaomingxian.name)) { disZhaoMingXian = dis; } for (int i = 0; i < AllMembers.Count; i++)//按照顺序将消耗分配给成员 { obj = AllMembers[i]; Dictionary costSelectedEquips = obj.GetComponent().costSelectedEquips; foreach (var item in costSelectedEquips) { if (item.Key.Contains("消防高压水带")) { item.Value.useNum = 0; if (disLine >= item.Value.selectedEquipNum * item.Value.unit) //如果消耗管线总数大于此人选择的管线,那么此人管线全部标记为已消耗,再从下一个人身上继续扣除 { item.Value.useNum = item.Value.selectedEquipNum; disLine -= item.Value.selectedEquipNum * item.Value.unit; } else { //如果剩余消耗管线总数小于此人选择的管线,那么此人管线向上取整标记为已消耗,无需再从下一个人身上继续扣除了 item.Value.useNum =(int) Math.Ceiling(disLine / item.Value.unit);//向上取整 disLine = 0.0f; } } else if (item.Key.Contains("救生照明线")) { item.Value.useNum = 0; if (disZhaoMingXian >= item.Value.selectedEquipNum * item.Value.unit) { item.Value.useNum = item.Value.selectedEquipNum; disZhaoMingXian -= item.Value.selectedEquipNum * item.Value.unit; } else { item.Value.useNum = (int)Math.Ceiling(disZhaoMingXian / item.Value.unit);//向上取整 disZhaoMingXian = 0.0f; } } } } } //收起管线 public void destoryLine() { for (int i = 0; i < AllLine.Count; i++) { if (GameObject.Find(AllLine[i])) { Destroy(GameObject.Find(AllLine[i])); //NetworkManager.Instance.Send("ENTITY_DESTROY", AllLine[i]); } } Allpath.Clear(); AllLine.Clear(); AllLineDistance.Clear(); nowpath = null; setLineXiaoHao(); } private void OnSpeedChangeEvent(SpeedChangeEventArgs e) { if (e.speed == 0) return; MultipleSpeed = e.speed; } }