using UnityEngine; using UnityEngine.AI; namespace TowerDefense.Agents { /// /// Agent that can pass "over" towers that block the path /// public class FlyingAgent : Agent { /// /// Time to wait to clear the navmesh obstacles /// protected float m_WaitTime = 0.5f; /// /// The current time to wait until we can resume agent movement as normal /// protected float m_CurrentWaitTime; /// /// If flying agents are blocked, they should still move through obstacles /// protected override void OnPartialPathUpdate() { if (!isPathBlocked) { state = State.OnCompletePath; return; } if (!isAtDestination) { return; } m_NavMeshAgent.enabled = false; m_CurrentWaitTime = m_WaitTime; state = State.PushingThrough; } /// /// Controls behaviour based on the states , /// and /// protected override void PathUpdate() { switch (state) { case State.OnCompletePath: OnCompletePathUpdate(); break; case State.OnPartialPath: OnPartialPathUpdate(); break; case State.PushingThrough: PushingThrough(); break; } } /// /// When flying agents are pushing through, give them a small amount of time to clear the gap and turn on their agent /// once time elapses /// protected void PushingThrough() { m_CurrentWaitTime -= Time.deltaTime; // Move the agent, overriding its NavMeshAgent until it reaches its destination transform.LookAt(m_Destination.transform, Vector3.up); transform.position += transform.forward * m_NavMeshAgent.speed * Time.deltaTime; if (m_CurrentWaitTime > 0) { return; } // Check if there is a navmesh under the agent, if not, then reset the timer NavMeshHit hit; if (!NavMesh.Raycast(transform.position + Vector3.up, Vector3.down, out hit, navMeshMask)) { m_CurrentWaitTime = m_WaitTime; } else { // If the time elapses, and there is a NavMesh under it, resume agent movement as normal m_NavMeshAgent.enabled = true; NavigateTo(m_Destination.transform.position); state = isPathBlocked ? State.OnPartialPath : State.OnCompletePath; } } } }