0

I am working on setting up a simple little AI for a character in my game. For some reason I am having major problems getting animations to play while using the NavMeshAgent and I do not understand why. This is a waypoint system that I pooled off Unity API, and I can't even seem to get this working. I am hoping that if someone can give me some input on this if might clear some other things up as well. I am really lost here and would appreciate any input. The code on the bottom all works until it hits Patrol and then the player moves without animating. I feel like there is something more i need to know about navmesh's maybe. Or a lot more I need to know about programming in general.

    e// Patrol.cs
using UnityEngine;
using UnityEngine.AI;
using System.Collections;


public class Enemy_Patrol : MonoBehaviour
{
    public Transform[] points;
    public Animator anim; 

    private int destPoint = 0;
    private NavMeshAgent agent;

    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        anim = GetComponent<Animator>(); 

        // Disabling auto-braking allows for continuous movement
        // between points (ie, the agent doesn't slow down as it
        // approaches a destination point).
        agent.autoBraking = false;

        GotoNextPoint();
    }


    void GotoNextPoint()
    {
        // Returns if no points have been set up
        if (points.Length == 0)
            return;

        // Set the agent to go to the currently selected destination.
        agent.destination = points[destPoint].position;
        anim.SetBool("WalkForwards", true);
        anim.SetBool("IsIdle", false);
        // Choose the next point in the array as the destination,
        // cycling to the start if necessary.
        destPoint = (destPoint + 1) % points.Length;
    }


    void Update()
    {
        // Choose the next destination point when the agent gets
        // close to the current one.
        if (!agent.pathPending && agent.remainingDistance < 0.5f)

        GotoNextPoint();
    }
}


// Code i wrote to handle following chasing etc.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class AI_Tester : MonoBehaviour
{
    private float patrolSpeed = .2f;
    public NavMeshAgent agent;
    public GameObject[] waypoints;
    private int waypointInd = 0;
    public Transform player;
    static Animator anim;
    public SealForce_DestructableObjects destructableObjects;
    public Transform enemy;


    // Use this for initialization
    void Start()
    {
        anim = GetComponentInChildren<Animator>();
        agent = GetComponent<NavMeshAgent>();
        destructableObjects = GetComponent<SealForce_DestructableObjects>();
        waypoints = GameObject.FindGameObjectsWithTag("waypoints");
        waypointInd = Random.Range(0, waypoints.Length); 
    }


    void AIMovements()
    {
        if (Vector3.Distance(player.position, this.transform.position) <= 30)
        {
            Vector3 direction = player.position - this.transform.position;
            direction.y = 0;

            this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
                                        Quaternion.LookRotation(direction), 0.1f);

            if (direction.magnitude > 15)
            {
                MoveToFiringRange();
            }


            if (direction.magnitude <= 15)
            {
                AttackPlayer();
            }
        }
        else if (Vector3.Distance(player.position, this.transform.position) > 30)
        {
            WaitingOnAction();
        }
    }
    public void Update()
    {
        AIMovements();
    }
    public void AttackPlayer()
    {
        anim.SetTrigger("IsAttacking");
        anim.SetBool("IsIdle", false);
        anim.SetBool("RunForwards", false);
    }
    public void MoveToFiringRange()
    {
        this.transform.Translate(0, 0, 0.04f);
        anim.SetBool("RunForwards", true);
        anim.SetBool("IsIdle", false);
        anim.ResetTrigger("IsAttacking");
    }
    public void WaitingOnAction()
    {
        anim.SetBool("IsIdle", true);
        anim.SetBool("RunForwards", false); 

        StartCoroutine("BackToPatrol"); 
    }

//program works fine all the up to here. The only thing wrong with patrol is no animation. 

    IEnumerator BackToPatrol()
    {
        yield return new WaitForSeconds(5);
        anim.SetBool("IsIdle", false);

        Patrol(); 
    }
    public void Patrol()
    {

        Debug.Log("In Patrol"); 
        agent.speed = patrolSpeed;
        if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2)
        {
            agent.SetDestination(waypoints[waypointInd].transform.position);
            anim.SetBool("WalkForwards", true); 
        }
        if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) <= 2)
        {
            waypointInd += 1;
            if (waypointInd > waypoints.Length)
            {
                waypointInd = 0;

            }

        }
    }
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class AI_Tester : MonoBehaviour
{
    public bool isPatrolling; 
    private float patrolSpeed = 1.5f;
    public NavMeshAgent agent;
    public GameObject[] waypoints;
    private int waypointInd = 0;
    public Transform player;
    static Animator anim;
    //public SealForce_DestructableObjects destructableObjects;
    //public Transform enemy;


    // Use this for initialization
    void Start()
    {
        anim = GetComponentInChildren<Animator>();
        agent = GetComponent<NavMeshAgent>();
        //destructableObjects = GetComponent<SealForce_DestructableObjects>();
        waypoints = GameObject.FindGameObjectsWithTag("waypoints");
        waypointInd = Random.Range(0, waypoints.Length);

    }


    void AIMovements()
    {
        if (Vector3.Distance(player.position, this.transform.position) <= 30)
        { 
            Vector3 direction = player.position - this.transform.position;
            direction.y = 0;

            this.transform.rotation = Quaternion.Slerp(this.transform.rotation,
                                        Quaternion.LookRotation(direction), 0.1f);

            if (direction.magnitude > 15)
            {
                //StopCoroutine("BackToPatrol");
                StopCoroutine("Patrol");
                isPatrolling = false; 
                MoveToFiringRange();
            }


            if (direction.magnitude <= 15)
            {
                //StopCoroutine("BackToPatrol");
                StopCoroutine("Patrol");
                isPatrolling = false;  
                AttackPlayer();
            }
        }
        else if (Vector3.Distance(player.position, this.transform.position) > 30 && !isPatrolling)
        {
            //StopCoroutine("BackToPatrol");
            StopCoroutine("Patrol");
            WaitingOnAction();
        }
    }
    public void Update()
    {  
        AIMovements();  
    }
    public void AttackPlayer()
    {
        anim.SetTrigger("IsAttacking");
        anim.SetBool("IsIdle", false);
        anim.SetBool("RunForwards", false);
    }
    public void MoveToFiringRange()
    { 
        this.transform.Translate(0, 0, 0.04f);
        anim.SetBool("RunForwards", true);
        anim.SetBool("IsIdle", false);
        anim.ResetTrigger("IsAttacking");
    }
    public void WaitingOnAction()
    {
        anim.SetBool("IsIdle", true);
        anim.SetBool("RunForwards", false); 

        StartCoroutine("BackToPatrol"); 

    }
    IEnumerator BackToPatrol()
    {
        isPatrolling = true;
        yield return new WaitForSeconds(5);
        anim.SetBool("IsIdle", false); 

        yield return StartCoroutine ("Patrol");
        isPatrolling = false;
    }
    IEnumerator Patrol()
    {
        Debug.Log("In Patrol");
        agent.speed = patrolSpeed;
        agent.SetDestination(waypoints[waypointInd].transform.position);
        anim.SetBool("WalkForwards", true);

        while (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2 && !isPatrolling)
        {
            yield return null;
        }

        waypointInd++;

        if (waypointInd >= waypoints.Length) waypointInd = 0;



    }


   /* public void  Patrol()
    {
        Debug.Log("In Patrol");
        agent.speed = patrolSpeed;

        if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2)
        {
            agent.SetDestination(waypoints[waypointInd].transform.position);
            anim.SetBool("IsIdle", false); 
            anim.SetBool("WalkForwards", false);
        }
        if (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) <= 2)
        {
            waypointInd += 1;
            if (waypointInd > waypoints.Length)
            {
                waypointInd = 0;*/



}
Martin
  • 12,469
  • 13
  • 64
  • 128
Robotics101
  • 93
  • 1
  • 2
  • 9
  • If it helps at all to have the rest of the script I am using that actually works I can give it to you. For Some reason I can never get the animations to run with my waypoint scripts. Not even Unity's . – Robotics101 Jul 06 '18 at 23:59
  • how its not working? have you checked the animator controller at runtime? are the transitions executing correctly? but the animation just doesn't play? is the blue bar in the animation not progressing (it stays at the beginning)? if that's so, then maybe the animation is transitioning to itself so it doesn't progress, set the animation transition to not transition to itself. – Daahrien Jul 07 '18 at 00:06
  • The transitions are correct I am pretty sure. I have been trying different transitions and like I said in the second program everything works except when I get to patrol. When I get to patrol everything works but the Walk animation. – Robotics101 Jul 07 '18 at 00:09
  • So I figure out why the top one was not working. I have GetComponent Instead of GetComponentInChildren. I Still have not figure out why my original patrol is not working though. – Robotics101 Jul 07 '18 at 00:22
  • It put it with the old code. Last time it did not do that. Just clearify though I have tried running a StopCoroutine in both when the other states get called, and also after entering the other states. Also, as long as the coroutine does not start the first part of the program run fine ("attack", "MoveToFire", and WaitingOnAction) but after the coroutine starts the it's seems that the first part of the program that tells the character to look at play is working but the player is still trying to move to the waypoints it seems. – Robotics101 Jul 08 '18 at 16:44

1 Answers1

1

You are calling WaitingOnAction on Update every frame, which will set the animator's IsIdle back to true and start a new BackToPatrol coroutine. This should not happen. Try to check if the character has reached it's destination before calling WaitingOnAction again. Something like:

else if (Vector3.Distance(player.position, this.transform.position) > 30 && !isPatrolling)
{
    WaitingOnAction();
}

And in your Coroutine:

IEnumerator BackToPatrol()
{
    isPatrolling = true;
    yield return new WaitForSeconds(5);
    anim.SetBool("IsIdle", false);

    yield return StartCoroutine("Patrol"); 
    isPatrolling = false;
}

IEnumerator Patrol()
{
    Debug.Log("In Patrol"); 
    agent.speed = patrolSpeed;
    agent.SetDestination(waypoints[waypointInd].transform.position);
    anim.SetBool("WalkForwards", true);
    agent.isStopped = false;

    while (Vector3.Distance(this.transform.position, waypoints[waypointInd].transform.position) >= 2 && isPatrolling)
    {
        yield return null;
    }

    agent.isStopped = true;
    anim.SetBool("WalkForwards", false);
    waypointInd++;

    if(waypointInd >= waypoints.Length) waypointInd = 0;
}

I didn't test it, but something like this should work.

Nathalia Soragge
  • 1,415
  • 6
  • 21
  • It did work. I do however have some major program refinement to do to get everything working repetitively and smooth the way I need it. Thank you so much. Appreciate the help. – Robotics101 Jul 07 '18 at 18:44
  • No problem, glad to help ;) – Nathalia Soragge Jul 07 '18 at 19:31
  • So my issue is that it goes to patrol state fine but it won't stop patrolling. By that i mean it will transition to the attack state and the moving to firing range state but it will stay in the walk animation and continue to move towards the waypoints. Any ideas to why i would do that would be helpful. Thank you – Robotics101 Jul 08 '18 at 03:34
  • And again when I get rid of the patrol state every seems to transition fine. – Robotics101 Jul 08 '18 at 03:36
  • Try to call StopCoroutine("Patrol") when entering in another state. For this to work you will have to change StartCoroutine(Patrol()) to StartCoroutine("Patrol") – Nathalia Soragge Jul 08 '18 at 08:23
  • I tried that last night. Mabey I am doing it wrong, i will post it – Robotics101 Jul 08 '18 at 16:13
  • I have edited my answer with something that could help. Instead of calling StopCoroutine, just set isPatrolling to false. The problem is that the agent is never being stopped. Maybe you can have problems setting a animator trigger on the Update also... – Nathalia Soragge Jul 08 '18 at 17:39
  • agent.isStopped worked!!! I had to do it a little differently though, using an if statement. If (isPatrolling == false) agent.isStopped == true. I put that in the AIMovements function and it is working now. Thanks again. Your on a role lol – Robotics101 Jul 08 '18 at 18:03
  • Great! Good luck with your game – Nathalia Soragge Jul 09 '18 at 02:27