Сочетание навигации и анимации в единстве
Итак, я реализовал этот учебник: https://docs.unity3d.com/Manual/nav-CouplingAnimationAndNavigation.html почти к письму. Почти означает, что я использую 2d freeform directional
тип смеси вместо simple directional
они используют. Проблема в том, что значения для velx
а также vely
(в основном это) колеблются. Так, например, когда vely
поднимается, в какой-то момент достигнет 1, но до этого будет так:
..., 0,5, 0,6, 0,5, 0,7, 0,4, 0,6, 0,8
Надеюсь, вы поняли мою точку зрения - тенденция растет, но иногда снижается. Это заставляет мою анимацию дрожать, потому что дерево смешивания очень быстро перемещается между состояниями. После некоторого времени экспериментирования я обнаружил, что в моем случае, используя число 7 в качестве делителя в выражении, вычисляющем smooth
переменная, вот так:
var smooth = Mathf.Min(1.0f, Time.deltaTime / 7f);
Вроде работает. Это означает, что он дрожит только 70% времени, а не всегда. Кто-нибудь знает лучший метод достижения того же эффекта?
1 ответ
Оооо... Для тех, кто заинтересован: я не смог решить дрожание без некоторых изменений в сценарии из документов, и мои изменения заключаются в следующем:
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;
}
}
Были также некоторые ошибки, например, если вы позволяли скорости постоянно повышаться или понижаться, в какой-то момент после нажатия на самолет агент начинал вести себя странно, и вышеописанное исправляет это. Что касается значений сверху - они совпадают с тем, что я мог найти в примере проекта, поэтому, если у вас есть похожие проблемы с моими, но с другой анимацией, вам, вероятно, придется скорректировать числа там.