using AIMachineTools; using System.Collections; using System.Collections.Generic; using UnityEngine; public class SearchState : State { private static SearchState _instance; //only declared once private SearchState() //set instance to itself { if (_instance != null) { return; } _instance = this; } public static SearchState instance //creates the instance of the first state if it does not exist { get { if (_instance == null) { new SearchState(); } return _instance; } } public override IEnumerator InState(AIMachine owner) { Waypoint currentWaypoint = null; Waypoint previousWaypoint = null; bool firstPointVisited = false; bool travelling = false; float timeWaited = 0f; owner.RemoveMarker(); while (owner.botMachine.currentState == SearchState.instance) { if (!owner.disabled) { if (currentWaypoint == null) { GameObject[] allWaypoints = GameObject.FindGameObjectsWithTag("Waypoint"); List<Waypoint> closeWaypoints = new List<Waypoint>(); if (allWaypoints.Length > 0) { while (currentWaypoint == null) { foreach (GameObject waypoint in allWaypoints) { if (Vector3.Distance(owner.gameObject.transform.position, waypoint.transform.position) <= 50) { closeWaypoints.Add(waypoint.GetComponent<Waypoint>()); } } int random = Random.Range(0, closeWaypoints.Count); Waypoint startingWaypoint = closeWaypoints[random]; if (startingWaypoint != null) { currentWaypoint = startingWaypoint; } } } } if (firstPointVisited == true && travelling == false) { Waypoint nextWaypoint = currentWaypoint.NextWaypoint(previousWaypoint); previousWaypoint = currentWaypoint; currentWaypoint = nextWaypoint; } owner.targetWaypoint = currentWaypoint.transform.position; foreach (GameObject bot in owner.friendlyBots) { if (bot != null && !bot.GetComponent<AIAllyMachine>()) { var target = bot.GetComponent<AIMachine>().targetWaypoint; if (owner.targetWaypoint == target) { Debug.Log(bot + "has the same target as another bot"); Waypoint nextWaypoint = currentWaypoint.NextWaypoint(previousWaypoint); previousWaypoint = currentWaypoint; currentWaypoint = nextWaypoint; } } } if (owner.targetWaypoint != null) { travelling = true; if (Vector3.Angle(owner.transform.forward, owner.targetWaypoint - owner.transform.position) < 15) { MoveTurret(owner, owner.targetWaypoint); owner.thisAgent.SetDestination(owner.targetWaypoint); Debug.DrawLine(owner.transform.position, owner.targetWaypoint, Color.blue); if (travelling && Vector3.Distance(owner.transform.position, owner.targetWaypoint) <= owner.markerDistance) { travelling = false; firstPointVisited = true; } } else RotateBody(owner, owner.targetWaypoint); } if (owner.agentVelocity == new Vector3(0, 0, 0) && owner.targetWaypoint != null) { timeWaited += Time.deltaTime; if (timeWaited >= 5f) { Debug.Log(owner.displayName + " got stuck on a waypoint, generating a new point."); Waypoint nextWaypoint = currentWaypoint.NextWaypoint(previousWaypoint); previousWaypoint = currentWaypoint; currentWaypoint = nextWaypoint; timeWaited = 0; } } if (owner.canSeeEnemy && owner.enemyObject != null) { owner.botMachine.ChangeState(ChaseState.instance); yield break; } else { owner.canSeeEnemy = false; } } else { owner.thisAgent.SetDestination(owner.transform.position); } yield return null; } } private void RotateBody(AIMachine _owner, Vector3 navPoint) //called to have the bot rotate to face the waypoint before navigating to it { //declare variables that will be used to determine how to move the bot Quaternion targetRot = Quaternion.LookRotation(navPoint - _owner.transform.position); //rotate the bot over time to face the enemy _owner.transform.rotation = Quaternion.RotateTowards(_owner.transform.rotation, targetRot, Time.deltaTime * _owner.bodyRotateSpeed); //set the bots y euler angle so that it only moves on that transform _owner.transform.localEulerAngles = new Vector3(0, _owner.transform.localEulerAngles.y, 0); } private void MoveTurret(AIMachine _owner, Vector3 hitPos) //called to move the bots turret so that it faces whatever Vector3 is sent { //declare variables that will be used to determine how to move the turret Quaternion hitRot = Quaternion.LookRotation(hitPos - _owner.transform.position); Quaternion turretRot = Quaternion.LookRotation(hitPos - _owner.turretPos.transform.position); if (Vector3.Angle(_owner.turretPos.transform.forward, hitPos - _owner.turretPos.transform.position) > 5) //rotate the turret until it is facing within 5 degrees of the target { //rotate the turret over time to the target _owner.turretPos.transform.rotation = Quaternion.RotateTowards(_owner.turretPos.transform.rotation, turretRot, Time.deltaTime * _owner.turretRotateSpeed); //set the turrets y euler angle so that it only moves on that transform _owner.turretPos.transform.localEulerAngles = new Vector3(0, _owner.turretPos.transform.localEulerAngles.y, 0); } //rotate the barrel over time to the target _owner.barrelPos.transform.rotation = Quaternion.RotateTowards(_owner.barrelPos.transform.rotation, turretRot, Time.deltaTime * _owner.barrelMoveSpeed); //set the barrels y euler angle so that it only moves on that transform _owner.barrelPos.transform.localEulerAngles = new Vector3(0, _owner.barrelPos.transform.localEulerAngles.y, 0); } }