Reputation: 3951
So I've implemented this tutorial: https://docs.unity3d.com/Manual/nav-CouplingAnimationAndNavigation.html almost to the letter. Almost means that I'm using the 2d freeform directional
blend type instead of the simple directional
they are using. The problem is that the values for velx
and vely
(mostly this one) are fluctuating. So for example when the vely
is rising it will at some point reach 1, but before that it will go like this:
..., 0.5, 0.6, 0.5, 0.7, 0.4, 0.6, 0.8
Hopefully you get my point - the trend is rising but it occasionally goes down. This makes my animation jitter because the blend tree is jumping between states very rapidly. After some time of experimentation I found out, that in my case using number 7 as the divisor in the expression calculating the smooth
variable, so like this:
var smooth = Mathf.Min(1.0f, Time.deltaTime / 7f);
Kinda works. This means that it jitters only 70% of the time, instead of always. Anyone knows a better method of accomplishing the same effect?
Upvotes: 2
Views: 826
Reputation: 3951
Sooo... To whoever is interested: I wasn't abble to solve the jittering without some modifications to the script from the docs and my changes are as follows:
using UnityEngine;
using UnityEngine.AI;
[RequireComponent (typeof (NavMeshAgent))]
[RequireComponent (typeof (Animator))]
public class LocomotionSimpleAgent : MonoBehaviour {
private const float SmoothingCoefficient = .15f;
[SerializeField] private float _velocityDenominatorMultiplier = .5f;
[SerializeField] private float _minVelx = -2.240229f;
[SerializeField] private float _maxVelx = 2.205063f;
[SerializeField] private float _minVely = -2.33254f;
[SerializeField] private float _maxVely = 3.70712f;
public Vector3 Goal {
get { return _agent.destination; }
set {
_agent.destination = value;
_smoothDeltaPosition = Vector2.zero;
}
}
private NavMeshAgent _agent;
private Animator _animator;
private Vector2 _smoothDeltaPosition;
public void Start() {
_animator = GetComponent<Animator>();
_agent = GetComponent<NavMeshAgent>();
_agent.updatePosition = false;
_smoothDeltaPosition = default(Vector2);
Goal = transform.position;
}
public void FixedUpdate() {
var worldDeltaPosition = _agent.nextPosition - transform.position;
var dx = Vector3.Dot(transform.right, worldDeltaPosition);
var dy = Vector3.Dot(transform.forward, worldDeltaPosition);
var deltaPosition = new Vector2(dx, dy);
var smooth = Time.fixedDeltaTime / SmoothingCoefficient;
_smoothDeltaPosition = Vector2.Lerp(_smoothDeltaPosition, deltaPosition, smooth);
var velocity = _smoothDeltaPosition / (Time.fixedDeltaTime * _velocityDenominatorMultiplier);
var shouldMove = _agent.remainingDistance > .1f;
var x = Mathf.Clamp(Mathf.Round(velocity.x * 1000) / 1000, _minVelx, _maxVelx);
var y = Mathf.Clamp(Mathf.Round(velocity.y * 1000) / 1000, _minVely, _maxVely);
_animator.SetBool("move", shouldMove);
_animator.SetFloat("velx", x);
_animator.SetFloat("vely", y);
if (worldDeltaPosition.magnitude > _agent.radius / 16 && shouldMove) {
_agent.nextPosition = transform.position + 0.1f * worldDeltaPosition;
}
}
public void OnAnimatorMove() {
var position = _animator.rootPosition;
position.y = _agent.nextPosition.y;
transform.position = position;
}
}
There were also some bugs, like if you allowed the velocity to constantly rise or go down, at some point after clicking on the plane, the agent would start behaving weirdly and the above fixes it. As for the values up top - they are matching what I could find in the example project, so if you have similar problems to mine, but different animations, you'll probably have to adjust the numbers there.
Upvotes: 0