MrDiamond
MrDiamond

Reputation: 1072

Vector3.MoveTowards not working. It does not move or show any errors

When using Vector3.MoveTowards, it won't do anything for either one, because one can't run which causes the other to not run.

Here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
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;
    public IEnumerator Depart()
    {
        navMeshAgent.SetDestination(runwayPoints[selectedRunway = Random.Range(0, runwayPoints.Length)].position);
        yield return new WaitForSeconds(3f);
        departing = true;
    }
    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            StartCoroutine(Depart());
        }
        GetComponent<LineRenderer>().SetPosition(0, new Vector3(transform.position.x, 1, transform.position.z));
        GetComponent<LineRenderer>().SetPosition(1, navMeshAgent.destination);
        if (navMeshAgent.pathStatus == NavMeshPathStatus.PathComplete && departing && navMeshAgent.remainingDistance == 0)
        {
            Takeoff();
        }
        if (moving && Vector3.Distance(transform.position, startTakeoffPoints[selectedRunway].position) <= 0.001f)
        {
            transform.position = Vector3.MoveTowards(transform.position, takeoffPoints[selectedRunway].position, 3); // this one does not work it should be after the other one
            transform.LookAt(takeoffPoints[selectedRunway]);
            takeoff = false;
        }
    }
    public void Takeoff()
    {
        navMeshAgent.enabled = false;
        GetComponent<Collider>().enabled = false;
        transform.LookAt(new Vector3(takeoffPoints[selectedRunway].position.x, 0, takeoffPoints[selectedRunway].position.z));
        MoveTakeoff();
        departing = false;
    }
    public void MoveTakeoff()
    {
        transform.position = Vector3.MoveTowards(transform.position, startTakeoffPoints[selectedRunway].position, 2); // this one does not work
        moving = true;
        takeoff = false;
    }
}

There are no script errors, it just won't work.

The only errors that I don't think are related are:

"Invalid worldAABB. Object is too large or too far away from the origin."

"Invalid localAABB. Object transform is corrupt."

"Assertion failed on expression: 'IsFinite(d)' UnityEngine.GUIUtility:processEvent(Int32, IntPtr)"

"Assertion failed on expression: 'IsFinite(outDistanceForSort)' UnityEngine.GUIUtility:processEvent(Int32, IntPtr)"

"Assertion failed on expression: 'IsFinite(outDistanceAlongView)' UnityEngine.GUIUtility:processEvent(Int32, IntPtr)"

Upvotes: 3

Views: 553

Answers (1)

Ruzihm
Ruzihm

Reputation: 20249

You need to better separate your state transition logic from your your state activity logic. You have code that should run when a state transition occurs in the same blocks as code that should run every frame a state is active.

One way you could handle this is by turning your states into coroutines:

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);

    }
}

Ideally, the states should be a single enumerator instead of several booleans, but this hopefully shows what I'm getting at.

Upvotes: 1

Related Questions