统一耦合导航和动画
Coupling navigation and animation in unity
所以我已经实施了本教程: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
希望您明白我的意思 - 趋势在上升,但偶尔会下降。这使我的动画抖动,因为混合树在状态之间跳跃得非常快。经过一段时间的实验,我发现,在我的例子中,在计算 smooth
变量的表达式中使用数字 7 作为除数,所以像这样:
var smooth = Mathf.Min(1.0f, Time.deltaTime / 7f);
有点效果。这意味着它只有 70% 的时间抖动,而不是总是抖动。谁知道实现相同效果的更好方法?
Sooo...对于任何感兴趣的人:
如果不对文档中的脚本进行一些修改,我无法解决抖动问题,我的更改如下:
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;
}
}
还有一些错误,比如如果你允许速度不断上升或下降,在点击飞机后的某个时刻,代理会开始表现得很奇怪,上面修复了它。
至于上面的值 - 它们与我在示例项目中可以找到的值相匹配,所以如果你遇到与我类似的问题,但动画不同,你可能需要调整那里的数字。
所以我已经实施了本教程: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
希望您明白我的意思 - 趋势在上升,但偶尔会下降。这使我的动画抖动,因为混合树在状态之间跳跃得非常快。经过一段时间的实验,我发现,在我的例子中,在计算 smooth
变量的表达式中使用数字 7 作为除数,所以像这样:
var smooth = Mathf.Min(1.0f, Time.deltaTime / 7f);
有点效果。这意味着它只有 70% 的时间抖动,而不是总是抖动。谁知道实现相同效果的更好方法?
Sooo...对于任何感兴趣的人: 如果不对文档中的脚本进行一些修改,我无法解决抖动问题,我的更改如下:
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;
}
}
还有一些错误,比如如果你允许速度不断上升或下降,在点击飞机后的某个时刻,代理会开始表现得很奇怪,上面修复了它。 至于上面的值 - 它们与我在示例项目中可以找到的值相匹配,所以如果你遇到与我类似的问题,但动画不同,你可能需要调整那里的数字。