// Animancer // Copyright 2020 Kybernetik // #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value. using System; using UnityEngine; namespace Animancer.Examples.Locomotion { /// /// Demonstrates how to use Root Motion for some animations but not others. /// [AddComponentMenu(Strings.MenuPrefix + "Examples/Locomotion - Root Motion")] [HelpURL(Strings.APIDocumentationURL + ".Examples.Locomotion/RootMotion")] public sealed class RootMotion : MonoBehaviour { /************************************************************************************************************************/ /// /// A with an toggle. /// [Serializable] public class MotionTransition : ClipState.Transition { /************************************************************************************************************************/ [SerializeField, Tooltip("Determines if Root Motion should be enabled when this animation plays")] private bool _ApplyRootMotion; /************************************************************************************************************************/ public override void Apply(AnimancerState state) { base.Apply(state); state.Root.Component.Animator.applyRootMotion = _ApplyRootMotion; } /************************************************************************************************************************/ } /************************************************************************************************************************/ [SerializeField] private AnimancerComponent _Animancer; [SerializeField] private float _MaxDistance; [SerializeField] private MotionTransition[] _Animations; private Vector3 _Start; /************************************************************************************************************************/ private void OnEnable() { _Start = transform.position; Play(0); } /************************************************************************************************************************/ /// Plays the animation at the specified `index` in the array. /// This method is called by UI Buttons. public void Play(int index) { _Animancer.Play(_Animations[index]); } /************************************************************************************************************************/ /// /// Teleports this object back to its starting location if it moves too far. /// private void FixedUpdate() { if (Vector3.Distance(_Start, transform.position) > _MaxDistance) transform.position = _Start; } /************************************************************************************************************************/ // These fields determine which object the Root Motion will be applied to. // You would normally only have one of these for whichever system you are using to move your characters. // But for this example, we have all of them to demonstrate how each could be used. [SerializeField] private Transform _MotionTransform; [SerializeField] private Rigidbody _MotionRigidbody; [SerializeField] private CharacterController _MotionCharacterController; /// /// Called when the would apply Root Motion. Applies that Root Motion to a different /// object instead. /// /// This can be useful if for example the character's or /// is on a parent of the so that the model is kept /// separate from the character's mechanics. /// private void OnAnimatorMove() { if (!_Animancer.Animator.applyRootMotion) return; if (_MotionTransform != null) { _MotionTransform.position += _Animancer.Animator.deltaPosition; _MotionTransform.rotation *= _Animancer.Animator.deltaRotation; } else if (_MotionRigidbody != null) { _MotionRigidbody.MovePosition(_MotionRigidbody.position + _Animancer.Animator.deltaPosition); _MotionRigidbody.MoveRotation(_MotionRigidbody.rotation * _Animancer.Animator.deltaRotation); } else if (_MotionCharacterController != null) { _MotionCharacterController.Move(_Animancer.Animator.deltaPosition); _MotionCharacterController.transform.rotation *= _Animancer.Animator.deltaRotation; } else { // If we aren't retargeting, just let Unity apply the Root Motion normally. _Animancer.Animator.ApplyBuiltinRootMotion(); } } /************************************************************************************************************************/ } }