英文:
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 & 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'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<Rigidbody>();
colliders = GetComponentsInChildren<Collider>();
boxCollider= GetComponent<BoxCollider>();
enemyRb = GetComponent<Rigidbody>();
enemyManager = GetComponent<EnemyManager>();
enemyAnimatorManager= GetComponent<EnemyAnimatorManager>();
navMeshAgent = GetComponentInChildren<NavMeshAgent>();
//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 < colliders.Length; i++)
{
CharacterStats characterStats = colliders[i].transform.GetComponent<CharacterStats>();
if(characterStats != null )
{
Debug.Log("HaSDetectedDertc");
//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 & target direction
float viewableAngle = Vector3.Angle(targetDirection, transform.forward);
//check if its in our FOV
// if( viewableAngle > enemyManager.minimumDetectionAngle && viewableAngle< enemyManager.maximumDetectionAngle)
// {
currentTarget = characterStats;
// }
}
}
}
public void HandleMoveToTarget()
{
Debug.Log("Handling Move To Target"); // 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's happening
Debug.Log($"Viewable Angle: {viewableAngle}, Distance From Target: {distanceFromTarget}");
if (enemyManager.isPerformingAction)
{
Debug.Log("Performing Action, Stopping Movement");
enemyAnimatorManager.anim.SetFloat("Vertical", 0, 0.1f, Time.deltaTime);
navMeshAgent.enabled = false;
}
else
{
if (distanceFromTarget > stoppingDistance)
{
Debug.Log("Moving Towards Target");
enemyAnimatorManager.anim.SetFloat("Vertical", 1, 0.1f, Time.deltaTime);
}
else if (distanceFromTarget <= stoppingDistance)
{
Debug.Log("Reached Stopping Distance");
enemyAnimatorManager.anim.SetFloat("Vertical", 0, 0.1f, Time.deltaTime);
}
}
HandleRotateToTarget(); // Add a log inside HandleRotateToTarget to check if it'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("Set Destination");
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<EnemyLocomotionManager>();
}
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's Apply Root Motion checkbox should be checked in the Unity editor.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论