void UpdateGuidance() { // mid-level, plots a set of waypoints to the objective target. Also sets speed for autopilot. // if no target, clear the wpList and set speed to min // if no LOS to target, get the closest wpLOS to target (or just check this once per second) // if that node has changed: // get the closest wpLOS to self // get the wp path and save it // if not, prune the wpList until only one node has LOS // if LOS to target, use the pseudo-PN code already written // // Set Point Speed: If no target, set min. If no LOS to target, set max. If LOS to target and close to target, match speed. if (!targeting.target) { guidance.HasLOSToTarget = false; guidance.wpsToTarget.Clear(); guidance.LOS = transform.up; guidance.angleLOS = 0f; guidance.setPointSpeed = Mathf.Min(0.1f, guidance.speedLimit); // idling return; } // can agent either move to, or shoot, the target guidance.HasLOSToTarget = WaypointManager.HasLOS(gameObject, targeting.target, true, new HashSet <WallType>() { WallType.EntityPass, WallType.ProjectilePass }); guidance.setPointSpeed = guidance.speedLimit; if (!guidance.HasLOSToTarget) { // check if the wpList is empty or if self or target do not have LOS to their respective nodes. // this may not necessarily work off of the closest wp with LOS to target but it is faster to // check than getting the closest node on every update. if (!guidance.wpsToTarget.Any() || !WaypointManager.HasLOS(guidance.wpsToTarget.Last(), targeting.target, true, new HashSet <WallType>() { WallType.EntityPass }) || !WaypointManager.HasLOS(guidance.wpsToTarget.First(), gameObject, true, new HashSet <WallType>() { WallType.EntityPass })) { int closestWpToTarget = WaypointManager.GetClosestWaypointWithLOS(targeting.target); int closestWPToSelf = WaypointManager.GetClosestWaypointWithLOS(gameObject); // if either of the above are -1, this will return an empty list guidance.wpsToTarget = WaypointManager.GetPath(closestWPToSelf, closestWpToTarget); } // prune; if agent can see the next wp, no need for the current wp else if (guidance.wpsToTarget.Count > 1 && WaypointManager.HasLOS(gameObject, guidance.wpsToTarget[1], true, new HashSet <WallType>() { WallType.EntityPass })) { guidance.wpsToTarget.RemoveAt(0); } if (guidance.wpsToTarget.Any()) { guidance.LOS = guidance.wpsToTarget[0].transform.position - transform.position; Debug.DrawLine(transform.position, guidance.wpsToTarget[0].transform.position, Color.green); for (int i = 0; i < guidance.wpsToTarget.Count - 1; i++) { Debug.DrawLine(guidance.wpsToTarget[i].transform.position, guidance.wpsToTarget[i + 1].transform.position, Color.green); } } } else { // aim directly at target guidance.LOS = targeting.lineToTgt; // match speed if (targeting.rb2D && guidance.LOS.magnitude < targeting.radius) { guidance.setPointSpeed = Mathf.Min(guidance.speedLimit, targeting.rb2D.velocity.magnitude); } } guidance.angleLOS = Vector2.Angle(guidance.LOS, transform.up) * Mathf.Sign(Vector3.Cross(transform.up, guidance.LOS).z); }