I’m trying to implement a custom animation for when my character follows an OffMeshLink on a NavMesh. I found some code from the Unity manual that is supposed to give you direct control over following an OffMeshLink - unfortunately, it is not working.
I copied and pasted the code into a C# script and added the script as a component to my object with a NavMeshAgent. When my agent walks over an OffMeshLink, the agent freezes and will not move further. After some debugging the problem seems to be that the script becomes stuck on the line
agent.transform.position = Vector3.MoveTowards (agent.transform.position, endPos, agent.speed*Time.deltaTime);
This is because agent.transform.position is not updating. Even though agent.transform.position is being assigned a new value each time through the while loop, something is overriding this and each time the line is evaluated again, agent.transform.position has reverted to its original value. I can get around this by setting agent.enabled = false before evaluating this loop; however, this creates a jerky animation and I’m not sure it’s the right way to go about it.
What’s the right way to have the script take control of my NavMesh agent while it’s supposed to be following the OffMeshLink?
using UnityEngine;
using System.Collections;public enum OffMeshLinkMoveMethod {
Teleport,
NormalSpeed,
Parabola
}[RequireComponent (typeof (NavMeshAgent))]
public class AgentLinkMover : MonoBehaviour {
public OffMeshLinkMoveMethod method = OffMeshLinkMoveMethod.Parabola;
IEnumerator Start () {
NavMeshAgent agent = GetComponent<NavMeshAgent> ();
agent.autoTraverseOffMeshLink = false;
while (true) {
if (agent.isOnOffMeshLink) {
if (method == OffMeshLinkMoveMethod.NormalSpeed)
yield return StartCoroutine (NormalSpeed (agent));
else if (method == OffMeshLinkMoveMethod.Parabola)
yield return StartCoroutine (Parabola (agent, 2.0f, 0.5f));
agent.CompleteOffMeshLink ();
}
yield return null;
}
}
IEnumerator NormalSpeed (NavMeshAgent agent) {
OffMeshLinkData data = agent.currentOffMeshLinkData;
Vector3 endPos = data.endPos + Vector3.up*agent.baseOffset;
while (agent.transform.position != endPos) {
agent.transform.position = Vector3.MoveTowards (agent.transform.position, endPos, agent.speed*Time.deltaTime);
yield return null;
}
}
IEnumerator Parabola (NavMeshAgent agent, float height, float duration) {
OffMeshLinkData data = agent.currentOffMeshLinkData;
Vector3 startPos = agent.transform.position;
Vector3 endPos = data.endPos + Vector3.up*agent.baseOffset;
float normalizedTime = 0.0f;
while (normalizedTime < 1.0f) {
float yOffset = height * 4.0f*(normalizedTime - normalizedTime*normalizedTime);
agent.transform.position = Vector3.Lerp (startPos, endPos, normalizedTime) + yOffset * Vector3.up;
normalizedTime += Time.deltaTime / duration;
yield return null;
}
}
}