/** * Déclenche (via une coroutine) le mouvement du transporteur vers la maison la * plus proche (sur le réseau routier), où il sera détruit (utile pour se * débarrasser des transporteurs dont le bâtiment principal est détruit). * Le stock sera alors perdu. Si aucune maison n'est disponible, le * transporteur ne bouge pas, et la coroutine va continuer d'attendre une * maison vers laquelle se rendre. **/ private IEnumerator GoHome() { RoadRouteManager roadRouteManager = GetComponent <RoadRouteManager>(); while (true) { //TODO utiliser un findNearestObjectWithPath (Utils) pour être plus générique. GameObject[] homesArray = GameObject.FindGameObjectsWithTag("Home"); float minDistance = 0.0f; FreightAreaIn nearestHomeIn = null; foreach (GameObject home in homesArray) { FreightAreaIn homeIn = home.GetComponent <BuildingStock>().freightAreaData.freightAreaIn; float distance = RoadsPathfinding.RealDistanceBetween(homeIn.road, roadRouteManager.occupiedRoad); if (distance > 0.0f && (nearestHomeIn == null || minDistance > distance)) { minDistance = distance; nearestHomeIn = homeIn; } yield return(null); } if (nearestHomeIn != null)//Sinon, c'est qu'il n'y a AUCUNE maison satisfaisante, et la boucle principale se charge de relancer la recherche { destination = nearestHomeIn.GetComponentInParent <BuildingStock>(); roadRouteManager.MoveTo(destination.freightAreaData.freightAreaIn.road, Random.Range(0.5f, 3.0f), null); yield break; } yield return(null); } }
private IEnumerator SortAvailableKeepAsideOrderManagersByDistance(Cell <PriorityQueue <float, KeepAsideOrderManager> > rslt) { StockManager stockManager = GameManager.instance.cityBuilderData.stockManager; PriorityQueue <float, KeepAsideOrderManager> rsltQueue = new PriorityQueue <float, KeepAsideOrderManager>(); IEnumerator <KeepAsideOrderManager> keepAsideEnumerator = stockManager.AllKeepAsideOrderManagers(); while (keepAsideEnumerator.MoveNext()) { KeepAsideOrderManager keepAsideManager = keepAsideEnumerator.Current; if (keepAsideManager != null)//On vérifie s'il n'a pas été détruit { float distance = Vector2.Distance(transform.position, keepAsideManager.transform.position); if (distance <= keepAsideManager.availabilityRange)//Pour éviter les calculs inutiles ; si ce n'est pas le cas, il est de toute façon trop loin { FreightAreaIn inArea = keepAsideManager.freightAreaData.freightAreaIn; FreightAreaOut outHome = freightAreaData.freightAreaOut; float roadDistance = RoadsPathfinding.RealDistanceBetween(inArea.road, outHome.road); if (roadDistance > 0.0f && roadDistance <= keepAsideManager.availabilityRange) { rsltQueue.Push(roadDistance, keepAsideManager); } } } yield return(null); } rslt.value = rsltQueue; }
/** * Coroutine à lancer pour trier selon leur distance (sur le réseau * routier) à cette route les bâtiments capable de recevoir des commandes. **/ public IEnumerator SortOrderManagersByDistance(Cell <PriorityQueue <float, OrderManager> > rslt) { PriorityQueue <float, OrderManager> rsltQueue = new PriorityQueue <float, OrderManager>(); StockManager stockManager = GameManager.instance.cityBuilderData.stockManager; IEnumerator <OrderManager> allOrderManagers = stockManager.AllOrderManagers(); while (allOrderManagers.MoveNext()) { OrderManager orderManager = allOrderManagers.Current; if (orderManager != null) { float realDistanceToOrderManager = RoadsPathfinding.RealDistanceBetween(this, orderManager.freightAreaData.freightAreaOut.road); if (realDistanceToOrderManager > 0.0f) { rsltQueue.Push(realDistanceToOrderManager, orderManager); } } yield return(null); } rslt.value = rsltQueue; yield return(null); }
public IEnumerator goOnTour(List <GameObject> toVisit) { if (prefecture != null) { List <GameObject> toReVisit = new List <GameObject>(); toVisit.Remove(prefecture); _tour = TSP.GetItinary(prefecture, toVisit); GameObject _currentDestination; while (!_tour.IsEmpty()) { _continueTour = false; _tryAgainToVisitHome = 50; _currentDestination = _tour.Pop(); goalFA = _currentDestination.GetComponentInChildren <FreightAreaIn>(); if (goalFA != null && RoadsPathfinding.RealDistanceBetween(GetComponent <RoadRouteManager>().occupiedRoad, goalFA.road) != -1) //Il existe encore une route vers ce batiment { GetComponent <RoadRouteManager>().MoveTo(goalFA.road); yield return(new WaitUntil(() => _continueTour || goalFA == null || gameObject.GetComponent <RoadRouteManager>().occupiedRoad == goalFA.road)); if (goalFA != null && _continueTour)//On a pas pu atteindre la maison et on a choisi de la skipper { toReVisit.Add(goalFA.gameObject); } if (goalFA != null && !_continueTour) { Building building = _currentDestination.GetComponent <Building>(); if (building != null) { building.RestoreHealth(); } GetComponent <SpriteRenderer>().enabled = false;//TODO il est toujours sur la FA et donc le lock est toujours activé ! yield return(new WaitForSeconds(Random.Range(2.0f, 5.0f))); GetComponent <SpriteRenderer>().enabled = true; } } } if (toReVisit.Count != 0 && _trytoRevisitCount-- != 0) { StartCoroutine(goOnTour(toReVisit)); } else { StartCoroutine(GoBack()); } } }
/** * Coroutine à lancer pour effectuer une recherche parmi les entrepôts disponibles * quel est le plus proche remplissant une condition donnée. Pour les calculs * de distance, ce sont ici les freight area d'ENTREE (in) qui sont utilisées, ATTENTION! **/ public static IEnumerator FindNearestWarehouseSatisfyingCondition(RoadData startPoint, Func <Warehouse, bool> acceptanceFunction, Cell <Warehouse> rslt, HashSet <FreightAreaIn> toIgnore) { PriorityQueue <float, Warehouse> sortedWarehouses = new PriorityQueue <float, Warehouse>(); IEnumerator <Warehouse> allWarehouses = GameManager.instance.cityBuilderData.stockManager.AllWarehouses(); while (allWarehouses.MoveNext()) { Warehouse warehouse = allWarehouses.Current; if (warehouse != null)// Car il peut avoir été détruit depuis le début de la coroutine ! { FreightAreaIn warehouseIn = warehouse.orderManager.freightAreaData.freightAreaIn; if (!toIgnore.Contains(warehouseIn) && acceptanceFunction(warehouse)) { float distanceToWarehouse = Vector2.Distance(warehouseIn.transform.position, startPoint.transform.position); sortedWarehouses.Push(distanceToWarehouse, warehouse); } } } if (!sortedWarehouses.IsEmpty()) { Warehouse bestWarehouse = sortedWarehouses.Pop(); float pathDistance = RoadsPathfinding.RealDistanceBetween(startPoint, bestWarehouse.orderManager.freightAreaData.freightAreaIn.road); yield return(null); while (!sortedWarehouses.IsEmpty() && (pathDistance > sortedWarehouses.LowestKey() || pathDistance < 0.0f)) { Warehouse nearestAsTheCrowFlies = sortedWarehouses.Pop(); float newPathDistance = RoadsPathfinding.RealDistanceBetween(startPoint, nearestAsTheCrowFlies.orderManager.freightAreaData.freightAreaIn.road); if (newPathDistance >= 0.0f && (newPathDistance < pathDistance || pathDistance < 0.0f)) { pathDistance = newPathDistance; bestWarehouse = nearestAsTheCrowFlies; } yield return(null); } if (pathDistance >= 0.0f) { rslt.value = bestWarehouse; } } }
//TODO faire une version avec une co-routine plus efficace (un pathfinding/frame) public static GameObject GetNearestObjectWithPath(RoadData origin, string tag, HashSet <GameObject> exclude) { GameObject[] objectsWithTag = GameObject.FindGameObjectsWithTag(tag); float minDistance = Mathf.Infinity; GameObject nearest = null; foreach (GameObject nearObject in objectsWithTag) { RoadData destinationRoadData = nearObject.GetComponentInChildren <FreightAreaIn>() == null ? null : nearObject.GetComponentInChildren <FreightAreaIn>().road; if (destinationRoadData != null && (exclude == null || (exclude != null && !exclude.Contains(nearObject)))) { float distance = RoadsPathfinding.RealDistanceBetween(destinationRoadData, origin); if (distance != -1.0f && distance < minDistance) { minDistance = distance; nearest = nearObject; } } } return(nearest); }
//TODO pour l'instant, pas de TSP, c'est un algo qui établi un itinéraire en prenant à chaque fois le gameObject le plus proche à vol d'oiseau du précédent. /** * Pré : origin doit avoir un RoadData * */ public static PriorityQueue <int, GameObject> GetItinary(GameObject origin, List <GameObject> toVisit) { PriorityQueue <int, GameObject> rslt = new PriorityQueue <int, GameObject>(); GameObject previous = origin; int i = 0; while (toVisit.Count > 0) { GameObject nearest = GetNearestObject(previous, toVisit); if (previous.GetComponentInChildren <RoadData>() != null && nearest.GetComponentInChildren <RoadData>() != null && RoadsPathfinding.RealDistanceBetween(previous.GetComponentInChildren <RoadData>(), nearest.GetComponentInChildren <RoadData>()) != -1)//On checke qu'il y a quand même bien un passage { rslt.Push(i, nearest); previous = nearest; i++; } toVisit.Remove(nearest); } return(rslt); }