public class FollowerJumpLinkHandler : IOffMeshLinkHandler, IOffMeshLinkStateMachine
{
public event Action OnBeginTraversal;
public event Action OnEndTraversal;
public bool CancelTraversal { get; set; }
private readonly EnemyInfo _enemyInfo;
private readonly JumpConfig _jumpConfig;
private readonly string _jump1AnimatorState, _jump2AnimatorState, _jump3AnimatorState, _jump4AnimatorState;
public FollowerJumpLinkHandler(
EnemyInfo enemyInfo,
JumpConfig jumpConfig,
string jump1AnimatorState = "Jump1",
string jump2AnimatorState = "Jump2",
string jump3AnimatorState = "Jump3",
string jump4AnimatorState = "Jump4")
{
_enemyInfo = enemyInfo;
_jumpConfig = jumpConfig;
_jump1AnimatorState = jump1AnimatorState;
_jump2AnimatorState = jump2AnimatorState;
_jump3AnimatorState = jump3AnimatorState;
_jump4AnimatorState = jump4AnimatorState;
}
IOffMeshLinkStateMachine IOffMeshLinkHandler.GetOffMeshLinkStateMachine(AgentOffMeshLinkTraversalContext context) => this;
void IOffMeshLinkStateMachine.OnFinishTraversingOffMeshLink(AgentOffMeshLinkTraversalContext context)
{
OnEndTraversal?.Invoke();
}
void IOffMeshLinkStateMachine.OnAbortTraversingOffMeshLink()
{
Debug.Log("An agent aborted traversing an off-mesh link");
}
IEnumerable IOffMeshLinkStateMachine.OnTraverseOffMeshLink(AgentOffMeshLinkTraversalContext ctx)
{
OnBeginTraversal?.Invoke();
CancelTraversal = false;
var start = (Vector3)ctx.link.relativeStart;
var end = (Vector3)ctx.link.relativeEnd;
var dir = end - start;
// Disable local avoidance while traversing the off-mesh link.
// If it was enabled, it will be automatically re-enabled when the agent finishes traversing the link.
ctx.DisableLocalAvoidance();
// Move and rotate the agent to face the other side of the link.
// When reaching the off-mesh link, the agent may be facing the wrong direction.
while (!ctx.MoveTowards(
position: start,
rotation: Quaternion.LookRotation(dir, ctx.movementPlane.up),
gravity: true,
slowdown: true).reached)
{
if (CancelTraversal) yield break;
yield return null;
}
_enemyInfo.AnimatorUtils.PlayForce(_jump1AnimatorState);
float normalizedTime = 0.0f;
while (normalizedTime < 1.0f)
{
if (CancelTraversal) yield break;
int currentFrameIndex = 0;
for (int i = 0; i < _jumpConfig.JumpCurve.keys.Length; i++)
{
if (_jumpConfig.JumpCurve.keys[i].time > normalizedTime) break;
currentFrameIndex = i;
}
switch (currentFrameIndex)
{
default:
case 0:
_enemyInfo.AnimatorUtils.Play(_jump1AnimatorState);
break;
case 1:
_enemyInfo.AnimatorUtils.Play(_jump2AnimatorState);
break;
case 2:
_enemyInfo.AnimatorUtils.Play(_jump3AnimatorState);
break;
}
float yOffset = _jumpConfig.JumpCurve.Evaluate(normalizedTime);
ctx.transform.Position = Vector3.Lerp(start, end, normalizedTime) + yOffset * Vector3.up;
normalizedTime += Time.deltaTime / _jumpConfig.JumpDuration;
yield return null;
}
bool landingFinished = false;
_enemyInfo.AnimatorUtils.Play(_jump4AnimatorState, () =>
{
landingFinished = true;
});
while (!landingFinished && !CancelTraversal)
{
yield return null;
}
}
}
I am using the code above to handle traversal of offmesh links with the follower entity. My issue is that when the agent plays the jump4AnimatorState i don’t apply any movement, but he starts to slide backwards. Am I doing something wrong? Could this be a bug? (He seems to be sliding towards the relativeStart of the link)