RootMotion.cs 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Animancer // https://kybernetik.com.au/animancer // Copyright 2022 Kybernetik //
  2. #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value.
  3. using Animancer.Units;
  4. using System;
  5. using UnityEngine;
  6. namespace Animancer.Examples.Locomotion
  7. {
  8. /// <summary>Demonstrates how to use Root Motion for some animations but not others.</summary>
  9. /// <example><see href="https://kybernetik.com.au/animancer/docs/examples/locomotion/root-motion">Root Motion</see></example>
  10. /// https://kybernetik.com.au/animancer/api/Animancer.Examples.Locomotion/RootMotion
  11. ///
  12. [AddComponentMenu(Strings.ExamplesMenuPrefix + "Locomotion - Root Motion")]
  13. [HelpURL(Strings.DocsURLs.ExampleAPIDocumentation + nameof(Locomotion) + "/" + nameof(RootMotion))]
  14. public sealed class RootMotion : MonoBehaviour
  15. {
  16. /************************************************************************************************************************/
  17. /// <summary>
  18. /// A <see cref="ClipTransition"/> with an <see cref="_ApplyRootMotion"/> toggle.
  19. /// </summary>
  20. [Serializable]
  21. public class MotionTransition : ClipTransition
  22. {
  23. /************************************************************************************************************************/
  24. [SerializeField, Tooltip("Should Root Motion be enabled when this animation plays?")]
  25. private bool _ApplyRootMotion;
  26. /************************************************************************************************************************/
  27. public override void Apply(AnimancerState state)
  28. {
  29. base.Apply(state);
  30. state.Root.Component.Animator.applyRootMotion = _ApplyRootMotion;
  31. }
  32. /************************************************************************************************************************/
  33. }
  34. /************************************************************************************************************************/
  35. [SerializeField] private AnimancerComponent _Animancer;
  36. [SerializeField, Meters] private float _MaxDistance;
  37. [SerializeField] private MotionTransition[] _Animations;
  38. private Vector3 _Start;
  39. /************************************************************************************************************************/
  40. private void OnEnable()
  41. {
  42. _Start = transform.position;
  43. Play(0);
  44. }
  45. /************************************************************************************************************************/
  46. /// <summary>Plays the animation at the specified `index` in the <see cref="_Animations"/> array.</summary>
  47. /// <remarks>This method is called by UI Buttons.</remarks>
  48. public void Play(int index)
  49. {
  50. _Animancer.Play(_Animations[index]);
  51. }
  52. /************************************************************************************************************************/
  53. /// <summary>
  54. /// Teleports this object back to its starting location if it moves too far.
  55. /// </summary>
  56. private void FixedUpdate()
  57. {
  58. if (Vector3.Distance(_Start, transform.position) > _MaxDistance)
  59. transform.position = _Start;
  60. }
  61. /************************************************************************************************************************/
  62. // These fields determine which object the Root Motion will be applied to.
  63. // You would normally only have one of these for whichever system you are using to move your characters.
  64. // But for this example, we have all of them to demonstrate how each could be used.
  65. [SerializeField] private Transform _MotionTransform;
  66. [SerializeField] private Rigidbody _MotionRigidbody;
  67. [SerializeField] private CharacterController _MotionCharacterController;
  68. /// <summary>
  69. /// Called when the <see cref="Animator"/> would apply Root Motion. Applies that Root Motion to a different
  70. /// object instead.
  71. /// <para></para>
  72. /// This can be useful if for example the character's <see cref="Rigidbody"/> or
  73. /// <see cref="CharacterController"/> is on a parent of the <see cref="Animator"/> so that the model is kept
  74. /// separate from the character's mechanics.
  75. /// </summary>
  76. private void OnAnimatorMove()
  77. {
  78. if (!_Animancer.Animator.applyRootMotion)
  79. return;
  80. if (_MotionTransform != null)
  81. {
  82. _MotionTransform.position += _Animancer.Animator.deltaPosition;
  83. _MotionTransform.rotation *= _Animancer.Animator.deltaRotation;
  84. }
  85. else if (_MotionRigidbody != null)
  86. {
  87. _MotionRigidbody.MovePosition(_MotionRigidbody.position + _Animancer.Animator.deltaPosition);
  88. _MotionRigidbody.MoveRotation(_MotionRigidbody.rotation * _Animancer.Animator.deltaRotation);
  89. }
  90. else if (_MotionCharacterController != null)
  91. {
  92. _MotionCharacterController.Move(_Animancer.Animator.deltaPosition);
  93. _MotionCharacterController.transform.rotation *= _Animancer.Animator.deltaRotation;
  94. }
  95. else
  96. {
  97. // If we aren't retargeting, just let Unity apply the Root Motion normally.
  98. _Animancer.Animator.ApplyBuiltinRootMotion();
  99. }
  100. }
  101. /************************************************************************************************************************/
  102. }
  103. }