Я изменил название, чтобы отразить добавление уточняющей информации.
Я следую [Учебному пособию по Unity] [1], и когда пришло время тестировать элементы управления игроками, Unity выдала мне ошибку:
«SetDestination» может быть вызван только для активного агента, который был помещен в NavMesh.
Насколько я могу судить, мой агент активен и находится в navMesh, так что это немного сбивает с толку. Я попытался повторно выполнить navMesh и изменить положение агента, ни один из которых не работал.
Все вопросы, которые я нашел до сих пор, сводились к тому, что у спрашивающего вообще не было navMesh, так что ... да ... не очень полезно. Любые предложения о том, как решить эту проблему, пока приветствуются.
EDIT:
Я просто добавил быстрый Debug.Log(agent.isOnNavMesh);
к своему коду и низкий & вот он оценивается в true
. Пик путаница.
private void Start()
{
Debug.Log(agent.isOnNavMesh); //Evaluates *true*
agent.updateRotation = false;
inputHoldWait = new WaitForSeconds(inputHoldDelay);
destinationPosition = transform.position;
}
РЕД-2
Поместите то же самое Debug.Log(agent.isOnNavMesh);
в мой public void OnGroundClick
fxn, и оно оценивается как false
после щелчка. Начните заинтригованное замешательство.
Это вызывается системой событий Unity:
public void OnGroundClick(BaseEventData data)
{
Debug.Log(agent.isOnNavMesh); //Evaluates *FALSE*
PointerEventData pData = (PointerEventData)data;
NavMeshHit hit;
//Click World Position, hit info, sample distance, navMesh areas to use
if (NavMesh.SamplePosition(pData.pointerCurrentRaycast.worldPosition, out hit, navMeshSampleDistance, NavMesh.AllAreas))
{
destinationPosition = hit.position;
}
else
{
destinationPosition = pData.pointerCurrentRaycast.worldPosition;
}
//give the agent it's destination
agent.SetDestination(destinationPosition);
agent.isStopped = false;
}
РЕД-3
Я положил Debug.Log(agent.isOnNavMesh);
в private void Update()
, он оценивается в true
и продолжает делать это даже после того, как Щелчок вызывает public void OnGroundClick
.
Отключение и включение агента в начале OnGroundClick
не влияет на ситуацию
Хотя я все еще в растерянности, я, по крайней мере, ближе к решению, и есть больше информации, чем «это не работает, пожалуйста, помогите!» сейчас.
Вот код в полном контексте:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.AI;
public class PlayerMovement : MonoBehaviour
{
public Animator animator; //Reference to animator
public NavMeshAgent agent; //Reference to NavMeshAgent
public float inputHoldDelay = 0.5f; //Delay player ability to control character while interacting with interactable object
public float turnSpeedThreshold = 0.5f; //minimum speed before character will turn
public float speedDampTime = 0.1f; //Character rate acceleration
public float slowingSpeed = 0.175f; //Character rate of neg accel
public float turnSmoothing = 15; //Character rotational speed
private WaitForSeconds inputHoldWait; //Coroutine Wait timer to delay player input while interacting with interactable object
private Vector3 destinationPosition; //Player designated destination for the agent to pursue
private const float stopDistanceProportion = 0.1f;
private const float navMeshSampleDistance = 4f;
private readonly int hashSpeedParam = Animator.StringToHash("Speed");
private void Start()
{
Debug.Log(agent.gameObject.name); //Is the "Player" object
Debug.Log(agent.isOnNavMesh); //Evaluates *true*
agent.updateRotation = false;
inputHoldWait = new WaitForSeconds(inputHoldDelay);
destinationPosition = transform.position;
}
private void OnAnimatorMove()
{
//Velocity = Distance over Time, where Distance = change in position between frames & Time = time between frames
agent.velocity = animator.deltaPosition / Time.deltaTime;
}
private void Update()
{
Debug.Log(agent.isOnNavMesh); //Evaluates *true*
//If path pending, do nothing
if (agent.pathPending)
return;
float speed = agent.desiredVelocity.magnitude;
if (agent.remainingDistance <= agent.stoppingDistance * stopDistanceProportion)
{
Stopping(out speed);
}
else if (agent.remainingDistance <= agent.stoppingDistance)
{
Slowing(agent.remainingDistance, out speed);
}
else if(speed > turnSpeedThreshold)
{
Moving();
}
animator.SetFloat(hashSpeedParam, speed, speedDampTime, Time.deltaTime);
}
private void Stopping(out float speed)
{
agent.isStopped = true;
transform.position = destinationPosition;
speed = 0.0f;
}
private void Slowing(float distanceToDestination, out float speed)
{
agent.isStopped = true;
transform.position = Vector3.MoveTowards(transform.position, destinationPosition, slowingSpeed * Time.deltaTime);
float proportionalDistance = 1f - distanceToDestination / agent.stoppingDistance;
speed = Mathf.Lerp(slowingSpeed, 0, proportionalDistance);
}
private void Moving()
{
Quaternion targetRotation = Quaternion.LookRotation(agent.desiredVelocity);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, turnSmoothing * Time.deltaTime);
}
public void OnGroundClick(BaseEventData data)
{
agent.enabled = false; //Disabling then enabling the agent...
agent.enabled = true; //does not change anything.
Debug.Log(agent.gameObject.name); //Is the "Player" object
Debug.Log(agent.isOnNavMesh); //Evaluates *FALSE*
PointerEventData pData = (PointerEventData)data;
NavMeshHit hit;
//Click World Position, hit info, sample distance, navMesh areas to use
if (NavMesh.SamplePosition(pData.pointerCurrentRaycast.worldPosition, out hit, navMeshSampleDistance, NavMesh.AllAreas))
{
destinationPosition = hit.position;
}
else
{
destinationPosition = pData.pointerCurrentRaycast.worldPosition;
}
//give the agent it's destination
agent.SetDestination(destinationPosition);
agent.isStopped = false;
}
}