/// --------------------------------------------- /// Behavior Designer /// Copyright (c) Opsive. All Rights Reserved. /// https://www.opsive.com /// --------------------------------------------- namespace Opsive.BehaviorDesigner.Samples { using UnityEngine; using UnityEngine.AI; /// /// An example showing how to synchronize NavMeshAgent movement with the Animator. This solution depends on the Animator having a "Forward" float Animator parameter. /// public class AnimationSynchronizer : MonoBehaviour { [Tooltip("Should root motion be used?")] [SerializeField] private bool m_UseRootMotion; [Tooltip("The NavMeshAgent stopping distance. Setting this value will prevent the agent from wobbling back and forth trying to arrive precisely on the destination.")] [SerializeField] private float m_StoppingDistance = 0.2f; [Tooltip("The multiplier to apply to the Forward Animator parameter value.")] [SerializeField] private float m_ForwardParameterMultiplier = 1f; [Tooltip("The damping time to reach the Forward Animator parameter value.")] [SerializeField] private float m_ForwardDampingTime = 0.01f; private Transform m_Transform; private Animator m_Animator; private NavMeshAgent m_NavMeshAgent; private int m_ForwardParameterHash = Animator.StringToHash("Forward"); /// /// Initialize the default values. /// private void Awake() { m_Transform = transform; m_Animator = GetComponent(); m_NavMeshAgent = GetComponent(); m_NavMeshAgent.stoppingDistance = m_StoppingDistance; m_NavMeshAgent.updatePosition = !m_UseRootMotion; } /// /// Updates the Animator value based on the NavMesh path. /// private void Update() { var localVelocity = Vector3.ProjectOnPlane(m_Transform.InverseTransformDirection(m_NavMeshAgent.velocity), Vector3.up).normalized; // Set the Forward parameter. This is specific to the sample Animator Controller. m_Animator.SetFloat(m_ForwardParameterHash, localVelocity.z * m_ForwardParameterMultiplier, m_ForwardDampingTime, Time.deltaTime); // If using root motion set the position within OnAnimatorMove. if (!m_UseRootMotion) { m_Transform.position = m_NavMeshAgent.nextPosition; } } /// /// Sets a new Forward Paramter Multiplier value. /// /// The new value. public void SetForwardMultiplier(float multiplier) { m_ForwardParameterMultiplier = multiplier; } /// /// Applies the root motion movement. /// private void OnAnimatorMove() { if (!m_UseRootMotion) { return; } m_Transform.position += m_Animator.deltaPosition; m_NavMeshAgent.nextPosition = m_Transform.position; } } }