Unity NavMesh Agent未移动。

huangapple go评论126阅读模式
英文:

Unity NavMesh Agent Not Moving

问题

以下是代码的中文翻译部分:

// EnemyLocomotionManager.cs

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

public class EnemyLocomotionManager : MonoBehaviour
{
    private BoxCollider boxCollider;
    private Rigidbody[] RDrigidbodies;
    private Collider[] colliders;

    public float moveSpeed = 10f;
    public Rigidbody enemyRb;
    NavMeshAgent navMeshAgent;
    EnemyAnimatorManager enemyAnimatorManager;
    EnemyManager enemyManager;
    public CharacterStats currentTarget;
    [SerializeField] LayerMask detectionLayer;

    public float rotationSpeed = 25;
    public float distanceFromTarget;
    public float stoppingDistance = 0.5f;

    private void Awake()
    {
        RDrigidbodies = GetComponentsInChildren<Rigidbody>();
        colliders = GetComponentsInChildren<Collider>();

        boxCollider = GetComponent<BoxCollider>();
        enemyRb = GetComponent<Rigidbody>();
        enemyManager = GetComponent<EnemyManager>();
        enemyAnimatorManager = GetComponent<EnemyAnimatorManager>();
        navMeshAgent = GetComponentInChildren<NavMeshAgent>();
        // 禁用Ragdoll
        SetCollidersEnabled(false);
        SetRigidBodiesKinematic(false);
        boxCollider.enabled = true;
    }

    private void Start()
    {
        navMeshAgent.enabled = false;
        enemyRb.isKinematic = false;
    }

    public void HandleDetection()
    {
        Collider[] colliders = Physics.OverlapSphere(transform.position, enemyManager.detectionRadius, detectionLayer);

        for (int i = 0; i < colliders.Length; i++)
        {
            CharacterStats characterStats = colliders[i].transform.GetComponent<CharacterStats>();
            if (characterStats != null)
            {
                Debug.Log("已检测到目标");
                // 检查团队ID

                // 指向具有该脚本的对象的方向
                Vector3 targetDirection = characterStats.transform.position - transform.position;

                // 返回当前方向与目标方向之间的角度
                float viewableAngle = Vector3.Angle(targetDirection, transform.forward);
                // 检查是否在视野范围内
                // if (viewableAngle > enemyManager.minimumDetectionAngle && viewableAngle < enemyManager.maximumDetectionAngle)
                // {
                currentTarget = characterStats;
                // }
            }
        }
    }

    public void HandleMoveToTarget()
    {
        Debug.Log("处理移动到目标"); // 添加日志以指示正在执行此函数

        Vector3 targetDirection = currentTarget.transform.position - transform.position;
        float viewableAngle = Vector3.Angle(targetDirection, transform.forward);
        distanceFromTarget = Vector3.Distance(currentTarget.transform.position, transform.position);

        // 记录值以查看发生了什么
        Debug.Log($"可见角度:{viewableAngle},距离目标:{distanceFromTarget}");

        if (enemyManager.isPerformingAction)
        {
            Debug.Log("正在执行动作,停止移动");
            enemyAnimatorManager.anim.SetFloat("Vertical", 0, 0.1f, Time.deltaTime);
            navMeshAgent.enabled = false;
        }
        else
        {
            if (distanceFromTarget > stoppingDistance)
            {
                Debug.Log("朝向目标移动");
                enemyAnimatorManager.anim.SetFloat("Vertical", 1, 0.1f, Time.deltaTime);
            }
            else if (distanceFromTarget <= stoppingDistance)
            {
                Debug.Log("已达到停止距离");
                enemyAnimatorManager.anim.SetFloat("Vertical", 0, 0.1f, Time.deltaTime);
            }
        }

        HandleRotateToTarget(); // 在HandleRotateToTarget内添加一个日志以检查是否正在执行

        navMeshAgent.transform.localPosition = Vector3.zero;
        navMeshAgent.transform.localRotation = Quaternion.identity;
    }

    private void HandleRotateToTarget()
    {
        // 手动旋转
        if (enemyManager.isPerformingAction)
        {
            Vector3 direction = currentTarget.transform.position - transform.position;
            direction.y = 0;
            direction.Normalize();

            if (direction == Vector3.zero)
            {
                direction = transform.forward;
            }
            Quaternion targetRotation = Quaternion.LookRotation(direction);
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed / Time.deltaTime);
        }
        // 使用路径查找旋转
        else
        {
            // 此功能
            // 导航网格代理
            Vector3 relativeDirection = transform.InverseTransformDirection(navMeshAgent.desiredVelocity);
            Vector3 targetVelocity = enemyRb.velocity;

            navMeshAgent.enabled = true;
            navMeshAgent.SetDestination(currentTarget.transform.position);
            Debug.Log("设置目标位置");
            enemyRb.velocity = targetVelocity;
            transform.rotation = Quaternion.Slerp(transform.rotation, navMeshAgent.transform.rotation, rotationSpeed / Time.deltaTime);
        }
    }

    private void SetCollidersEnabled(bool enabled)
    {
        foreach (Collider col in colliders)
        {
            col.enabled = enabled;
        }
    }

    private void SetRigidBodiesKinematic(bool kinematic)
    {
        foreach (Rigidbody rb in RDrigidbodies)
        {
            rb.isKinematic = kinematic;
        }
    }

    private void ActivateRagdoll()
    {
        boxCollider.enabled = false;
        enemyRb.isKinematic = true;
        enemyAnimatorManager.anim.enabled = false;

        SetCollidersEnabled(true);
        SetRigidBodiesKinematic(false);
    }
}
// EnemyManager.cs

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

public class EnemyManager : MonoBehaviour
{
    EnemyLocomotionManager enemyLocomotionManager;
    public bool isPerformingAction;
    public float detectionRadius = 20;
    public float maximumDetectionAngle = 50;
    public float minimumDetectionAngle = -50;

    void Awake()
    {
        enemyLocomotionManager = GetComponent<EnemyLocomotionManager>();
    }

    private void FixedUpdate()
    {
        HandleCurrentAction();
    }

    void HandleCurrentAction()
    {
        if (enemyLocomotionManager.currentTarget == null)
        {
            enemyLocomotionManager.HandleDetection();
        }
        else
        {
            enemyLocomotionManager.HandleMoveToTarget();
        }
    }
}
// EnemyAnimatorManager.cs

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

public class EnemyAnimatorManager : AnimatorManager
{
    EnemyLocomotionManager enemyLocomotionManager;

    private void Awake()
    {
        enemyLocomotionManager = GetComponentInParent<EnemyLocomotionManager>();
        anim = GetComponent<Animator>();
    }

    void OnAnimatorMove()
    {
        float delta = Time.deltaTime;
        enemyLocomotionManager.enemyRb.drag = 0;
        Vector3 deltaPosition = anim.deltaPosition;
        deltaPosition.y = 0;
        Vector3 velocity = deltaPosition / delta;
        enemyLocomotionManager.enemyRb.velocity = velocity;
   

<details>
<summary>英文:</summary>

Currently, I am trying to set up a simple script where an enemy will move towards and rotate towards the player. The rotation &amp; running animations play just fine, but the enemy that is supposed to move is stuck in place.

I have tried Debugging it with logs as well as baking the navmesh, the issue could have somthing to do with velocity but I&#39;m just not sure. Thanks for reading this.

Here is the Code as well as the inspector:

[  
image](https://i.stack.imgur.com/EIZp3.png)

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

public class EnemyLocomotionManager : MonoBehaviour
{
private BoxCollider boxCollider;
private Rigidbody[] RDrigidbodies;
private Collider[] colliders;

public float moveSpeed = 10f;

public Rigidbody enemyRb;
NavMeshAgent navMeshAgent;
EnemyAnimatorManager enemyAnimatorManager;
EnemyManager enemyManager;
public CharacterStats currentTarget;
[SerializeField] LayerMask detectionLayer;

public float rotationSpeed = 25;
public float distanceFromTarget;
public float stoppingDistance = 0.5f;
private void Awake()
{
RDrigidbodies = GetComponentsInChildren&lt;Rigidbody&gt;();
colliders = GetComponentsInChildren&lt;Collider&gt;();
boxCollider= GetComponent&lt;BoxCollider&gt;();
enemyRb = GetComponent&lt;Rigidbody&gt;();
enemyManager = GetComponent&lt;EnemyManager&gt;();    
enemyAnimatorManager= GetComponent&lt;EnemyAnimatorManager&gt;();
navMeshAgent = GetComponentInChildren&lt;NavMeshAgent&gt;();
//DisableRagdoll
SetCollidersEnabled(false);
SetRigidBodiesKinematic(false);
boxCollider.enabled = true ;
}
private void Start()
{
navMeshAgent.enabled = false;
enemyRb.isKinematic= false;
}
public void HandleDetection()
{
Collider[] colliders = Physics.OverlapSphere(transform.position, enemyManager.detectionRadius, detectionLayer);
for (int i = 0; i &lt; colliders.Length; i++)
{
CharacterStats characterStats = colliders[i].transform.GetComponent&lt;CharacterStats&gt;();
if(characterStats != null )
{
Debug.Log(&quot;HaSDetectedDertc&quot;);
//Check for team ID
//Direction towards the object that has that script
Vector3 targetDirection = characterStats.transform.position - transform.position;
//returns the angle between current direction &amp; target direction
float viewableAngle = Vector3.Angle(targetDirection, transform.forward);
//check if its in our FOV
//    if( viewableAngle &gt; enemyManager.minimumDetectionAngle &amp;&amp; viewableAngle&lt; enemyManager.maximumDetectionAngle)
//    {
currentTarget = characterStats;
//   }
}
}
}
public void HandleMoveToTarget()
{
Debug.Log(&quot;Handling Move To Target&quot;); // Add a log to indicate this function is being executed
Vector3 targetDirection = currentTarget.transform.position - transform.position;
float viewableAngle = Vector3.Angle(targetDirection, transform.forward);
distanceFromTarget = Vector3.Distance(currentTarget.transform.position, transform.position);
// Log values to see what&#39;s happening
Debug.Log($&quot;Viewable Angle: {viewableAngle}, Distance From Target: {distanceFromTarget}&quot;);
if (enemyManager.isPerformingAction)
{
Debug.Log(&quot;Performing Action, Stopping Movement&quot;);
enemyAnimatorManager.anim.SetFloat(&quot;Vertical&quot;, 0, 0.1f, Time.deltaTime);
navMeshAgent.enabled = false;
}
else
{
if (distanceFromTarget &gt; stoppingDistance)
{
Debug.Log(&quot;Moving Towards Target&quot;);
enemyAnimatorManager.anim.SetFloat(&quot;Vertical&quot;, 1, 0.1f, Time.deltaTime);
}
else if (distanceFromTarget &lt;= stoppingDistance)
{
Debug.Log(&quot;Reached Stopping Distance&quot;);
enemyAnimatorManager.anim.SetFloat(&quot;Vertical&quot;, 0, 0.1f, Time.deltaTime);
}
}
HandleRotateToTarget(); // Add a log inside HandleRotateToTarget to check if it&#39;s being executed
navMeshAgent.transform.localPosition = Vector3.zero;
navMeshAgent.transform.localRotation = Quaternion.identity;
}
private void HandleRotateToTarget()
{
//Rotate manually
if(enemyManager.isPerformingAction)
{
Vector3 direction = currentTarget.transform.position - transform.position;
direction.y = 0;
direction.Normalize();
if(direction == Vector3.zero)
{
direction = transform.forward;
}
Quaternion targetRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed/Time.deltaTime);
}
//rotate with pathfinding
else
{
//this function
//navmesh agents
Vector3 relativeDirection = transform.InverseTransformDirection(navMeshAgent.desiredVelocity);
Vector3 targetVelocity = enemyRb.velocity;
navMeshAgent.enabled = true;
navMeshAgent.SetDestination(currentTarget.transform.position);      
Debug.Log(&quot;Set Destination&quot;);
enemyRb.velocity = targetVelocity;
transform.rotation = Quaternion.Slerp(transform.rotation, navMeshAgent.transform.rotation, rotationSpeed / Time.deltaTime);
}
}
private void SetCollidersEnabled(bool enabled)
{
foreach(Collider col in colliders)
{
col.enabled = enabled;
}
}
private void SetRigidBodiesKinematic(bool kinematic)
{
foreach(Rigidbody rb in RDrigidbodies)
{
rb.isKinematic= kinematic;
}
}
private void ActivateRagdoll()
{
boxCollider.enabled = false;
enemyRb.isKinematic = true;
enemyAnimatorManager.anim.enabled = false;
SetCollidersEnabled(true);
SetRigidBodiesKinematic(false);
}

}


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

public class EnemyManager : MonoBehaviour
{
EnemyLocomotionManager enemyLocomotionManager;
public bool isPerformingAction;
public float detectionRadius = 20;
public float maximumDetectionAngle = 50;
public float minimumDetectionAngle = -50;

// Start is called before the first frame update
void Awake()
{
enemyLocomotionManager= GetComponent&lt;EnemyLocomotionManager&gt;();
}
private void FixedUpdate()
{
HandleCurrentAction();
}
// Update is called once per frame
void HandleCurrentAction()
{
if (enemyLocomotionManager.currentTarget == null)
{
enemyLocomotionManager.HandleDetection();
}
else
{
enemyLocomotionManager.HandleMoveToTarget();
}
}

}


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

public class EnemyAnimatorManager : AnimatorManager
{
EnemyLocomotionManager enemyLocomotionManager;
private void Awake()
{
enemyLocomotionManager = GetComponentInParent<EnemyLocomotionManager>();
anim= GetComponent<Animator>();
}
void OnAnimatorMove()
{
float delta = Time.deltaTime;
enemyLocomotionManager.enemyRb.drag = 0;
Vector3 deltaPosition = anim.deltaPosition;
deltaPosition.y = 0;
Vector3 velocity = deltaPosition / delta;
enemyLocomotionManager.enemyRb.velocity = velocity;
}
}


</details>
# 答案1
**得分**: 0
记住,在 OnAnimatorMove() 正常工作的前提下,Unity 编辑器中的 Animator 组件的 Apply Root Motion 复选框应该被勾选。
<details>
<summary>英文:</summary>
Remember that for the OnAnimatorMove() to work correctly, the Animator component&#39;s Apply Root Motion checkbox should be checked in the Unity editor.
</details>

huangapple
  • 本文由 发表于 2023年8月11日 03:29:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76878794.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定