using UnityEngine; namespace ECM2 { /// /// /// RootMotionController. /// /// Helper component to get Animator root motion velocity vector (animRootMotionVelocity). /// /// This must be attached to a game object with an Animator component. /// [RequireComponent(typeof(Animator))] public class RootMotionController : MonoBehaviour { #region FIELDS protected Animator _animator; protected Vector3 _rootMotionDeltaPosition; protected Quaternion _rootMotionDeltaRotation; #endregion #region METHOD /// /// Flush any accumulated deltas. This prevents accumulation while character is toggling root motion. /// public virtual void FlushAccumulatedDeltas() { _rootMotionDeltaPosition = Vector3.zero; _rootMotionDeltaRotation = Quaternion.identity; } /// /// Return current root motion rotation and clears accumulated delta rotation. /// public virtual Quaternion ConsumeRootMotionRotation() { Quaternion rootMotionRotation = _rootMotionDeltaRotation; _rootMotionDeltaRotation = Quaternion.identity; return rootMotionRotation; } /// /// Get the calculated root motion velocity. /// public virtual Vector3 GetRootMotionVelocity(float deltaTime) { if (deltaTime == 0.0f) return Vector3.zero; Vector3 rootMotionVelocity = _rootMotionDeltaPosition / deltaTime; return rootMotionVelocity; } /// /// Return current root motion velocity and clears accumulated delta positions. /// public virtual Vector3 ConsumeRootMotionVelocity(float deltaTime) { Vector3 rootMotionVelocity = GetRootMotionVelocity(deltaTime); _rootMotionDeltaPosition = Vector3.zero; return rootMotionVelocity; } #endregion #region MONOBEHAVIOUR /// /// If overriden, base method MUST be called. /// public virtual void Awake() { _animator = GetComponent(); if (_animator == null) { Debug.LogError($"RootMotionController: There is no 'Animator' attached to the '{name}' game object.\n" + $"Please attach a 'Animator' to the '{name}' game object"); } } /// /// If overriden, base method MUST be called. /// public virtual void Start() { _rootMotionDeltaPosition = Vector3.zero; _rootMotionDeltaRotation = Quaternion.identity; } /// /// If overriden, base method MUST be called. /// public virtual void OnAnimatorMove() { // Accumulate root motion deltas between character updates _rootMotionDeltaPosition += _animator.deltaPosition; _rootMotionDeltaRotation = _animator.deltaRotation * _rootMotionDeltaRotation; } #endregion } }