Beispiel #1
0
    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);
    }