您需要更好地将状态转换逻辑与状态活动逻辑分开。当状态转换发生在同一块中时,应该运行的代码与状态处于活动状态时,应该在每一帧中运行的代码相同。
处理这个问题的一种方法是将状态转换为协同过程:
public class PlaneAI : MonoBehaviour
{
public Transform[] runwayPoints;
public Transform[] startTakeoffPoints;
public Transform[] takeoffPoints;
public NavMeshAgent navMeshAgent;
public bool takeoff = false;
bool departing = false;
bool moving = false;
int selectedRunway;
LineRenderer lr;
void Awake()
{
lr = GetComponent<LineRenderer>();
}
IEnumerator Depart()
{
navMeshAgent.SetDestination(runwayPoints[selectedRunway = Random.Range(0,
runwayPoints.Length)].position);
yield return new WaitForSeconds(3f);
departing = true;
while(departing)
{
if (navMeshAgent.pathStatus == NavMeshPathStatus.PathComplete
&& navMeshAgent.remainingDistance == 0)
{
StartCoroutine(MoveTakeoff());
yield break;
}
yield return null;
}
}
IEnumerator MoveTakeOff()
{
departing = false;
moving = true;
navMeshAgent.enabled = false;
GetComponent<Collider>().enabled = false;
transform.LookAt(new Vector3(takeoffPoints[selectedRunway].position.x, 0,
takeoffPoints[selectedRunway].position.z));
while (moving)
{
if (Vector3.Distance(transform.position,
startTakeoffPoints[selectedRunway].position) <= 0.001f)
{
StartCoroutine(TakeOff())
yield return break;
}
transform.position = Vector3.MoveTowards(transform.position,
startTakeoffPoints[selectedRunway].position, 2);
yield return null;
}
}
IEnumerator Takeoff()
{
moving = false;
takeOff = true;
transform.LookAt(takeoffPoints[selectedRunway]);
while (takeOff)
{
if (Vector3.Distance(transform.position,
startTakeoffPoints[selectedRunway].position) <= 0.001f)
{
takeoff = false;
yield break;
}
transform.position = Vector3.MoveTowards(transform.position,
takeoffPoints[selectedRunway].position, 3);
yield return null;
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.P))
{
StopAllCoroutines();
StartCoroutine(Depart());
}
lr.SetPosition(0, new Vector3(transform.position.x, 1, transform.position.z));
lr.SetPosition(1, navMeshAgent.destination);
}
}
理想情况下,状态应该是一个单一的枚举数,而不是几个布尔数,但这很有希望显示出我的意思。