public bool IsOnOffMeshLink() { //Debug.Log ("is off mesh link " + CentralizedManager.IsOffMeshLink(currentState.getPosition())); //return offMeshLinkWayPoint[currentPlanExecutionIndex]; if (currentPlanExecutionIndex >= gridNavigationTasks.Count) { return(false); } Vector3 meshLinkStartPos = gridNavigationTasks[currentPlanExecutionIndex].goalState.getPosition(); if (CentralizedManager.IsOffMeshLink(meshLinkStartPos) == true) { Debug.LogError("on off mesh link " + currentPlanExecutionIndex + " " + meshLinkStartPos); } return(CentralizedManager.IsOffMeshLink(meshLinkStartPos)); }
public void notifyEvent(Event ev, System.Object data) { switch (ev) { case Event.GLOBAL_PATH_CHANGED: Debug.Log("the global path has changed, we must update the path"); // removing the agent from the polygons associated with the old path in the centralized manager if (GlobalNavigator.usingDynamicNavigationMesh) { for (int i = 0; i < numGlobalPathWaypoints; i++) { CentralizedManager.polygonDictionary[globalPathPolygonIndices[i]].agents.Remove(this); } } // probably make this an event handler if (GlobalNavigator.pathStatus != NavMeshPathStatus.PathInvalid) { // TODO :: do some checking how much plan has changed // ALSO, we could do some filtering here maybe --- sometimes it gives points which are very close to each otehr Debug.Log("number of points in nav mesh path " + GlobalNavigator.numberOfNodes); // we dont want to put in the start state, so starting from 1 int currentGlobalPathWaypoint = 0; for (int i = 1; i < GlobalNavigator.numberOfNodes; i++) { // should we round off here ... we prob want to round of when we give it to the discrete planner // TODO this rounding off might sometimes place it on an obstacle // either we make hte nav mesh more conservative (give it 0.5 boundary around obstracles) or do some check here Vector3 p = GlobalNavigator.path[i]; // check for off mesh link before rounding off -- only using x-z values // using previous point to determin because the dictionary keys in using the start point -- NOT ANY MORE bool offMeshLinkState = CentralizedManager.IsOffMeshLink(GlobalNavigator.path[i]); p.x = Mathf.Round(p.x); p.y = Mathf.Round(p.y); p.z = Mathf.Round(p.z); // TODO : maybe off mesh link has its own time computation float time = (GlobalNavigator.pathCost[i] / GlobalNavigator.totalPathCost) * (goalState._time - currentState._time); // we ignore points that are the same as the previos point in the nav mesh path if (currentGlobalPathWaypoint != 0 && globalPath[currentGlobalPathWaypoint - 1].positionEquals(p)) { continue; } // todo check for automatic offmesh link as well ... maybe we will just create all of them manually if (currentGlobalPathWaypoint < globalPath.Count) { // some global path nodes have been statically allocated if (currentGlobalPathWaypoint >= numGlobalPathWaypoints && offMeshLinkState == false) { // we are now introducing more waypoints than before -- we need to make these valid globalPath[currentGlobalPathWaypoint].notifyObservers(Event.GOAL_VALID); } } else { _addNewEmptyGlobalPathWayPointAtIndex(currentGlobalPathWaypoint); if (offMeshLinkState == false) { globalPath[currentGlobalPathWaypoint].notifyObservers(Event.GOAL_VALID); } } // TODO: here check if the position actually changed -- else no need to call setPosition -- which triggers goal change event globalPath[currentGlobalPathWaypoint].setPosition(p); // adding time computation // TODO : REMOVE TIME.TIME if (currentGlobalPathWaypoint == 0) { globalPath[currentGlobalPathWaypoint]._time = currentState._time + time; } else { globalPath[currentGlobalPathWaypoint]._time = globalPath[currentGlobalPathWaypoint - 1]._time + time; } // TODO COMPUTE SPEED // storing offmesh link state if (offMeshLinkState == true) // this is an offlink { globalPath[currentGlobalPathWaypoint].notifyObservers(Event.GOAL_INVALID); } // setting off mesh link offMeshLinkWayPoint[currentGlobalPathWaypoint] = offMeshLinkState; if (GlobalNavigator.usingDynamicNavigationMesh) { globalPathPolygonIndices[currentGlobalPathWaypoint] = GlobalNavigator.recastSteeringManager.GetClosestPolygon(p); // adding agent to the respective polygon in the centralized manager if (CentralizedManager.polygonDictionary.ContainsKey(globalPathPolygonIndices[currentGlobalPathWaypoint]) == false) { CentralizedManager.polygonDictionary.Add(globalPathPolygonIndices[currentGlobalPathWaypoint], new PolygonData()); } CentralizedManager.polygonDictionary[globalPathPolygonIndices[currentGlobalPathWaypoint]].agents.Add(this); } currentGlobalPathWaypoint++; } Debug.LogWarning("current " + currentGlobalPathWaypoint + " prev " + numGlobalPathWaypoints); for (int i = currentGlobalPathWaypoint; i < numGlobalPathWaypoints; i++) { // this loop is iterating through all states in globalPath which are currently inactive globalPath[i].notifyObservers(Event.GOAL_INVALID); } numGlobalPathWaypoints = currentGlobalPathWaypoint; } else { Debug.LogError("Path is invalid for agent"); // this does happen when the goal is on an obstacle } break; } }
public static void CalculateNavigationMeshPath(Vector3 startPosition, Vector3 goalPosition, int passableMask) { ClearNavigationMeshPath(); switch (navigationMeshChoice) { default: case NavigationMeshChoice.USE_UNITY: NavMeshPath unityPath = new NavMeshPath(); NavMesh.CalculatePath(startPosition, goalPosition, passableMask, unityPath); pathStatus = unityPath.status; if (pathStatus == NavMeshPathStatus.PathInvalid) { numberOfNodes = 0; } else { if (unityPath.corners.Length >= maxNumberOfNodes) { Debug.LogWarning("Navigation mesh path greater than maximum number of nodes"); numberOfNodes = maxNumberOfNodes; pathStatus = NavMeshPathStatus.PathPartial; } else { numberOfNodes = unityPath.corners.Length; } for (int i = 0; i < numberOfNodes; i++) { // MAKING SURE LAST WAYPOINT IS THE GOAL if (i == numberOfNodes - 1) { path[i] = goalPosition; } else { path[i] = unityPath.corners[i]; } // computing path cost if (i == 0) { pathCost[i] = 0.0f; } else { // assuming that all off mesh links will override cost if (CentralizedManager.IsOffMeshLink(path[i])) { pathCost[i] = CentralizedManager.GetOffMeshLinkInformation(path[i]).offMeshLink.costOverride; } else { pathCost[i] = Vector3.Distance(path[i], path[i - 1]); } } totalPathCost += pathCost[i]; } } break; case NavigationMeshChoice.USE_RECAST: if (recastSteeringManager == null) { recastSteeringManager = GameObject.Find("ADAPTPrefab").GetComponentInChildren <SteeringManager>(); } numberOfNodes = recastSteeringManager.FindPath(startPosition, goalPosition, path, maxNumberOfNodes); if (numberOfNodes > 0) { path[numberOfNodes - 1] = goalPosition; } // computing path cost for (int i = 1; i < numberOfNodes; i++) { // TODO : incorporate number of obstacles from centralized manager here pathCost[i] = Vector3.Distance(path[i], path[i - 1]); totalPathCost += pathCost[i]; } if (numberOfNodes == 0) { pathStatus = NavMeshPathStatus.PathInvalid; } else if (numberOfNodes == maxNumberOfNodes) { pathStatus = NavMeshPathStatus.PathPartial; } else { pathStatus = NavMeshPathStatus.PathComplete; } break; } }