private void InitAgents() { /// Iterate over each SquirrelInfo and configure foreach (AgentInfo truckInfo in AgentsInfo) { if (truckInfo.AgentPrefab == null || truckInfo.Start == null) { Debug.LogError($"SquirrelInfo is incorrectly configured!"); continue; } /// instantiate the squirrel and add to list GameObject inst = Instantiate(truckInfo.AgentPrefab, m_agentParent); m_instantiatedAgents.Add(inst); /// Get the Aware component and listen to events and set move path ACOTruck acoTruck = inst.GetComponent <ACOTruck>(); if (acoTruck) { acoTruck.Cargo.AddPackages(truckInfo.CargoAmount); /// Create ACOConnection list between each goal location List <ACOConnection> goalACOConnections = CalculateGoalsAndRoutes(truckInfo.Goals); /// Get the closest ACO goal node to use as start GameObject acoPathFirstNode = GetClosestACOGoalNodeToPosition(goalACOConnections, truckInfo.Start.transform.position); // Calculate ACO path from all waypoints, using the ACOConnections generated List <ACOConnection> route = this.GenerateACOPath(AntColonyConfig.MaximumIterations, AntColonyConfig.Ants, m_allWaypoints.ToArray(), goalACOConnections, acoPathFirstNode, AntColonyConfig.MaxPathLength); /// Get last ACO node to calculate A* path back to target start position GameObject acoPathLastNode = route.LastOrDefault().ToNode; /// A* calculate paths from start to ACO start, and from ACO end to start List <Connection> startToACOStart = this.NavigateAStar(truckInfo.Start, acoPathFirstNode); List <Connection> acoEndToStart = this.NavigateAStar(acoPathLastNode, truckInfo.Start); /// Set this agent to move along ACO path acoTruck.SetMovePath(startToACOStart, route, acoEndToStart); /// Register to listen to events of trucks acoTruck.OnTravelNewConnection += OnTruckTravelNewConnection; acoTruck.OnReachedGoal += OnAgentReachedACOGoal; } else { Debug.LogError($"Missing ACOTruck script on Prefab '{truckInfo.AgentPrefab.name}'!"); } } }
private void OnTruckTravelNewConnection(ACOTruck truck, IConnection targetTravelConnection) { // Update or add new connection to list if (m_currentTruckConnections.ContainsKey(truck)) { m_currentTruckConnections[truck] = targetTravelConnection; } else { m_currentTruckConnections.Add(truck, targetTravelConnection); } }
public void Update() { if (m_currentTruckConnections.Count > 0) { /// For each truck and it's current connection foreach (KeyValuePair <ACOTruck, IConnection> thisKvp in m_currentTruckConnections) { /// Compare waypoint names to check if they are the same KeyValuePair <ACOTruck, IConnection> matchingKvp = m_currentTruckConnections .FirstOrDefault(kvp => kvp.Value.ToNode.name == thisKvp.Value.ToNode.name && kvp.Key.name != thisKvp.Key.name); ACOTruck truckOne = thisKvp.Key; ACOTruck truckTwo = matchingKvp.Key; /// If current iterarte truck is waiting, check if they can resume /// Only check truck one as the others will be checked next iteration if (truckOne.IsWaiting) { List <ACOTruck> waitingTrucks = new List <ACOTruck>(); bool isOnSameConnection = false; foreach (KeyValuePair <ACOTruck, IConnection> checkKvp in m_currentTruckConnections) { if (!checkKvp.Key.IsWaiting) { continue; } if (thisKvp.Value.ToNode.name == checkKvp.Value.ToNode.name) { //isOnSameConnection = true; waitingTrucks.Add(checkKvp.Key); } } // More than 1 truck waiting at same connection, resume first one in list if (waitingTrucks.Count > 1) { waitingTrucks[0].ResumeMovement(); Debug.Log($"Resuming Truck '{waitingTrucks[0]}' in queue of '{waitingTrucks.Count}'"); } // else if truckOne has no others waiting, resume else if (!isOnSameConnection) { truckOne.ResumeMovement(); Debug.Log($"Resuming Truck '{truckOne.name}'"); } } // Check match isn't null if (matchingKvp.Key != null && matchingKvp.Value != null) { /// If isn't waiting and connections are matching... bool eitherTruckWaiting = truckOne.IsWaiting || truckTwo.IsWaiting; if (!eitherTruckWaiting && thisKvp.Value.ToNode.name == matchingKvp.Value.ToNode.name) { if (truckOne.Cargo.PackageCount > truckTwo.Cargo.PackageCount) { ///truckOne is slower, pause it truckOne.PauseMovement(); Debug.Log($"Pausing Truck '{truckOne.name};"); } else { /// truckTwo is slower /// or cargo is same so prioritise truckTwo truckTwo.PauseMovement(); Debug.Log($"Pausing Truck '{truckTwo.name}'"); } } } } } }
private void OnAgentReachedACOGoal(ACOTruck agent, GameObject acoGoal) { agent.DeliverPackage(); }