using UnityEngine; namespace VOID.Generic.Objects.Unit.Animations { /// /// Little hacky trick to make traversal root motion animation ALWAYS move by identical distance. /// /// Requirements: /// 1. Attach this to start/loop/end states in animator /// 2. Transitions should have as small as possible exit time, less than 0.1 (0.0 would be best) /// public class MatchTargetTraversalStateHelper : StateMachineBehaviour { private bool _didMatchTarget; private Vector3 _startPosition; public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { _didMatchTarget = false; _startPosition = animator.transform.position; } public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if (animator.GetCurrentAnimatorStateInfo(layerIndex).fullPathHash != stateInfo.fullPathHash) return; if (_didMatchTarget) return; _didMatchTarget = true; var clip = animator.GetCurrentAnimatorClipInfo(layerIndex)[0].clip; var clipOffset = animator.transform.TransformDirection(clip.length * clip.averageSpeed); var repeat = clip.isLooping ? 100 : 1; animator.MatchTarget( _startPosition + clipOffset*repeat, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(Vector3.one, 0), stateInfo.normalizedTime, repeat ); } public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { animator.InterruptMatchTarget(false); } } }