using UnityEngine; using System.Collections; using System; using AX.TrackRecord; using AX.MessageSystem; using UnityEngine.AI; using System.Collections.Generic; using System.Linq; public class AgentControl : MonoBehaviour { private UnityEngine.AI.NavMeshAgent agent; public UnityEngine.AI.NavMeshPath NavMeshPath; private UnityEngine.AI.NavMeshObstacle obstacle;//寻路障碍 public Vector3 point; public int cengNum; public BuildType buildType; private RaycastHit hit; DateTime t1, t2; public bool toshinei; [HideInInspector] public int lastMask = 0; /// 寻路过程中的拐点 public Vector3[] nowpath; // private bool IsFirstPFFlag = false;//该记录的第一次寻路标志,开始记录时赋值true void Awake() { pathfindingLayer = 1 << 25 | 1 << 26| 1 << 31; agent = GetComponent(); agent.acceleration = 50000000; NavMeshPath = new UnityEngine.AI.NavMeshPath(); lastMask = GetComponent().areaMask; if (this.transform.parent.gameObject.name == "pxiaofangche") agent.speed = 7f * 3f; else { agent.speed = 3.5f * 3f; } if (GetComponent()) {//如果 有障碍组件,就添加切换脚本,如果没有,跳过即可---------------此处在消防车加上NavmeshObstacle后需要修改 obstacle = GetComponent(); agent.enabled = false; obstacle.enabled = true; gameObject.AddComponent(); } else { agent.enabled = true; } gameObject.AddComponent(); } public void Setpath(Vector3[] path) { nowpath = path; } void Update() { //寻路:初始速度;恒定,以此记录寻路时间 //回放:时间恒定,对应的目的点一样,以此计算出寻路速度; if (Input.GetMouseButtonDown(1)) { t2 = DateTime.Now; if (t2 - t1 > new TimeSpan(0, 0, 0, 0, 249)) {//不是要寻路的双击,没必要切换这些乱七八糟的 t1 = t2; return; } if (!TrackRecordHelpClass.CheckIfCanControl()) { return; } if (GetComponent().isConnectCar && name.Contains("xiaofangche")) { MessageDispatcher.SendMessage("Operatinghints", (object)"请收起消防管线再移动消防车"); return; } if (obstacle) {//obstacle这货存在时的寻路方式 StartCoroutine(delayActive()); } else { //obstacle 不存在时 的寻路方式 FindingPath(); } } } public void SetNearestXfy(Vector3[] points,int startID) { if (points.Length > 1) { var targetPoint = points[startID + 1]; var xfyList = InputManager.Instance_.GetSelectedCharacters(); float min = 10000; int index = 0; for (int i = 0; i < xfyList.Count; i++) { var distance = Vector3.Distance(targetPoint, xfyList[i].transform.position); if (distance < min) { min = distance; index = i; } } //foreach(Transform xfy in GameObject.Find("pxiaofangyuan").transform) //{ // xfy.GetComponent().canRecordPathFinding = false; //} xfyList[index].GetComponent().theNearestXFY = true; } } private string GetXFYName(Vector3 navTo) { var xfyList = InputManager.Instance_.GetSelectedCharacters(); int index = -1; float near = 100; for (int i = 0; i < xfyList.Count; i++) { var distance = Vector3.Distance(navTo, xfyList[i].transform.position); if (distance < near) { near = distance; index = i; } } return xfyList[index].name; } private void setXiaoFangYuan() { int curMask = 0; setCengNum(hit.transform.gameObject); if (GetComponent().cengID == 0 && cengNum == 0)//判断是否只在室外寻路,防止从室内抄近路 { //GetComponent().areaMask = 24; //curMask = 24; } else { //GetComponent().areaMask = 25; //curMask = 25; } if (GetComponent().cengID == 0 && cengNum != 0)//判断是否由室外进入室内 { toshinei = GetComponent().toShiNei(); } else { toshinei = true; } //toOtherCeng = GetComponent().toOtherCeng(cengNum); if (RecordManager.Instance.IsRecording) { if (lastMask != curMask) { lastMask = curMask; MessageDispatcher.SendMessage((object)name, "RECORDMASKCHANGEEVENT"); } } } private void setCengNum(GameObject obj) { //if (obj.transform.parent) //{ // GameObject pobj = obj.transform.parent.gameObject; // if (obj.tag == "nei") // { // string hitName = obj.name; // cengNum = int.Parse(hitName.Substring(3)); // return; // } // else // { // cengNum = 0; // } // setCengNum(pobj); //} if (obj.GetComponent()) { cengNum = obj.GetComponent().cengID; buildType = obj.GetComponent().CengIDBuildType; //MessageDispatcher.SendMessage(this.name, "SetCengID", build); } } /// /// 延迟激活NavmeshAgent,因其同时与NavmeshObstacle激活会出现位置的短位移 /// /// IEnumerator delayActive() { obstacle.enabled = false; yield return null; if (!obstacle.enabled) { FindingPath(); } else { StartCoroutine(delayActive()); } } LayerMask pathfindingLayer = 1 << 25 | 1 << 26; float GetF1(float f) { float f1 = Mathf.Abs(f); int fi = (int)(f1 * 10); f1 = (float)(fi / 10.0f); return f1;//* (f < 0 ? -1 : 1) } void FindingPath() { t1 = t2; agent.enabled = true; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //the mouse ray has hit a collider in the scene if (Physics.Raycast(ray, out hit, Mathf.Infinity, pathfindingLayer)) { NavMeshPath.ClearCorners(); try { UnityEngine.AI.NavMesh.CalculatePath(transform.position, hit.point, GetComponent().areaMask, NavMeshPath); } catch (Exception e) { System.Diagnostics.Trace.TraceError(e.Message); } NavMeshPath np = new NavMeshPath(); UnityEngine.AI.NavMesh.CalculatePath(transform.position, transform.position, GetComponent().areaMask, np); bool flag = np.corners.Length > 0 ? true : false; //Debug.Log(np.corners.Length); if (np.corners.Length == 0)//物体本身处于自己不能寻路的地方 { MessageDispatcher.SendMessage("Operatinghints", (object)"该类型物体在此区域无法寻路!"); return; } if (gameObject.name.Contains("xiaofangche") && hit.collider.gameObject.layer == 26) { MessageDispatcher.SendMessage("Operatinghints", (object)"该类型物体无法到达目的地!"); return; } if (tag == "Player")//如果是消防员 { GetComponent().setLine(); setXiaoFangYuan(); toshinei = GetComponent().toShiNei();//直接执行该方法,使得室外也会消耗管线 if (toshinei) { //if (GetComponent().areaMask == 25) //{ //任务是铺设管线或者照明线相关 if (TrackRecordHelpClass.IsCanDrawLine(GetComponent().TaskName)) { GetComponent().setPath(NavMeshPath.corners);//将新的寻路关键点传给画线脚本 } GetComponent().nowpath = NavMeshPath.corners;//将新的寻路关键点传给记录脚本 ///////////////////// //SetNearestXfy(NavMeshPath.corners, 0); //Vector3 newPoint = new Vector3(hit.point.x, hit.point.y + 1f, hit.point.z); if (GetComponent()) { GetComponent().SetList(); GetComponent().StartGo_(hit.transform.gameObject); } Transform Trager = GameObject.Find("target").transform; if (Trager.transform.parent != null) { Trager.transform.localPosition = new Vector3(0, 4.36f, 0); } if (transform.Find("Bip01/Bip01 Pelvis/Bip01 Spine/shuiqiang").gameObject.activeInHierarchy) {//如果水枪被激活, if (!GetComponent().HasLine()) {//并且没有拿消防水带和照明线,不能寻路 MessageDispatcher.SendMessage("Operatinghints", (object)"请装备管线或停止灭火再移动"); InputManager.Instance_.removeItem(gameObject);//将其从框选中删除 return; } } else { GetComponent().LineList_GameObject.Clear();//消防员跑离管线,清除身上已有管线数组,若要出水,需要重新连接管线 } if (GetComponent().TaskName.Contains("铺设照明线")) { if (!GetComponent().HasLine()) { //没有拿照明线,不能寻路铺设照明线 MessageDispatcher.SendMessage("Operatinghints", (object)"请装备照明线后铺设"); InputManager.Instance_.removeItem(gameObject);//将其从框选中删除 return; } } try { agent.SetDestination(hit.point); } catch(Exception e) { Debug.Log(e); MessageDispatcher.SendMessage("Operatinghints", (object)"目的地无法寻路到达!"); } } } else { GetComponent().nowpath = NavMeshPath.corners /*agent.path.corners*/; //传递寻路拐点数组 GetComponent().pathIndex = 0;//重置数组索引 GetComponent().nowpath = NavMeshPath.corners; if (GetComponent()) { GetComponent().StartGo_(hit.transform.gameObject); } try { agent.SetDestination(hit.point); } catch (Exception e) { Debug.Log(e); MessageDispatcher.SendMessage("Operatinghints", (object)"目的地无法寻路到达!"); } } } } public void delayNav(UnityEngine.AI.NavMeshPath navMeshPath, EventRecordItem_two eventItem) { if (obstacle) { StartCoroutine(delay(navMeshPath, eventItem)); } else { agent.enabled = true; Setpath(navMeshPath.corners);//将新的寻路关键点传给寻路脚本 agent.SetDestination(eventItem.Navto); gameObject.GetComponent().nowpath = navMeshPath.corners /*agent.path.corners*/; //传递寻路拐点数组 gameObject.GetComponent().pathIndex = 0;//重置数组索引 } } IEnumerator delay(UnityEngine.AI.NavMeshPath navMeshPath, EventRecordItem_two eventItem) { obstacle.enabled = false; yield return null; if (!obstacle.enabled) { agent.enabled = true; Setpath(navMeshPath.corners);//将新的寻路关键点传给寻路脚本 agent.SetDestination(eventItem.Navto); gameObject.GetComponent().nowpath = navMeshPath.corners /*agent.path.corners*/; //传递寻路拐点数组 gameObject.GetComponent().pathIndex = 0;//重置数组索引 } else { StartCoroutine(delay(navMeshPath, eventItem)); } } }