使anim.SetBool与NavMeshAgent配合使用时出现问题

时间:2018-07-06 23:57:26

标签: c# unity3d navmesh

我正在为游戏中的角色设置一个简单的小AI。由于某些原因,我在使用NavMeshAgent时要播放动画时遇到了很多问题,我不明白为什么。我汇集了Unity API,这是一个航点系统,我什至无法正常工作。我希望,如果有人可以在这方面给我一些意见,也可以解决其他问题。我在这里真的迷路了,不胜感激。底部的代码一直有效,直到命中Patrol,然后玩家移动且没有动画。我觉得我需要进一步了解navmesh。或一般而言,我需要了解更多信息。

    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;*/



}

1 个答案:

答案 0 :(得分:1)

您正在每帧更新上调用WaitingOnAction,这会将动画制作者的IsIdle设置为true,并开始新的BackToPatrol协程。这不应该发生。再次调用WaitingOnAction之前,请尝试检查字符是否已到达目的地。像这样:

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

在您的协同程序中:

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

我没有测试它,但是类似的东西应该可以工作。